All language subtitles for [English (auto-generated)] Learn Solidity, Blockchain Development, & Smart Contracts Powered By AI (1)

af Afrikaans
ak Akan
sq Albanian
am Amharic
ar Arabic
hy Armenian
az Azerbaijani
eu Basque
be Belarusian
bem Bemba
bn Bengali
bh Bihari
bs Bosnian
br Breton
bg Bulgarian
km Cambodian
ca Catalan
ceb Cebuano
chr Cherokee
ny Chichewa
zh-CN Chinese (Simplified)
zh-TW Chinese (Traditional)
co Corsican
hr Croatian
cs Czech
da Danish
nl Dutch
en English
eo Esperanto
et Estonian
ee Ewe
fo Faroese
tl Filipino
fi Finnish
fr French
fy Frisian
gaa Ga
gl Galician
ka Georgian
de German
el Greek
gn Guarani
gu Gujarati
ht Haitian Creole
ha Hausa
haw Hawaiian
iw Hebrew
hi Hindi
hmn Hmong
hu Hungarian
is Icelandic
ig Igbo
id Indonesian
ia Interlingua
ga Irish
it Italian
ja Japanese
jw Javanese
kn Kannada
kk Kazakh
rw Kinyarwanda
rn Kirundi
kg Kongo
ko Korean
kri Krio (Sierra Leone)
ku Kurdish
ckb Kurdish (Soranรฎ)
ky Kyrgyz
lo Laothian
la Latin
lv Latvian
ln Lingala
lt Lithuanian
loz Lozi
lg Luganda
ach Luo
lb Luxembourgish
mk Macedonian
mg Malagasy
ms Malay
ml Malayalam
mt Maltese
mi Maori
mr Marathi
mfe Mauritian Creole
mo Moldavian
mn Mongolian
my Myanmar (Burmese)
sr-ME Montenegrin
ne Nepali
pcm Nigerian Pidgin
nso Northern Sotho
no Norwegian
nn Norwegian (Nynorsk)
oc Occitan
or Oriya
om Oromo
ps Pashto
pl Polish
pt-BR Portuguese (Brazil)
pt Portuguese (Portugal)
pa Punjabi
qu Quechua
ro Romanian
rm Romansh
nyn Runyakitara
ru Russian
sm Samoan
gd Scots Gaelic
sr Serbian
sh Serbo-Croatian
st Sesotho
tn Setswana
crs Seychellois Creole
sn Shona
sd Sindhi
si Sinhalese
sk Slovak
sl Slovenian
so Somali
es Spanish
es-419 Spanish (Latin American)
su Sundanese
sw Swahili
sv Swedish
tg Tajik
ta Tamil
tt Tatar
te Telugu
th Thai
ti Tigrinya
to Tonga
lua Tshiluba
tum Tumbuka
tr Turkish
tk Turkmen
tw Twi
ug Uighur
uk Ukrainian
ur Urdu
uz Uzbek
vi Vietnamese
cy Welsh
wo Wolof
xh Xhosa
yi Yiddish
yo Yoruba
zu Zulu

Original subtitles

all right welcome back welcome to the

defi section of this course we scroll

all the way down here Foundry defi we

can see the code that we're going to

work with for this course now I got to

say ahead of time defi is an absolutely

massive topic quite frankly that

deserves an entire video of itself so

we're just going to give you a brief

rundown of what defi is what you can do

with it and some of the most popular

apps out there so first to get started

we can use this site called defi Lama to

get a snapshot of what's going on in the

defi world right now the total value

locked in defi some of the dominant apps

and what the dominant Protocols are

doing for me we can look at some of

these top five for now too L is a liquid

staking platform which I'm not going to

go into right now makeer da is a CDP or

a collateralized debt position protocol

for making stable coins which is what

we're going to be building a is a

borrowing lending protocol like an open-

Source decentralized Bank curve Finance

is a decentralized exchange more

specifically for working with these

stable coins and then Unis swap is a

general purpose exchange for swapping

tokens and different types of assets to

me if you understand some of these top

ones as you go down the list you can get

more and more intricate or more and more

specific different types of defi

protocols the beauty of Defi and

decentralized finance is that you get

access to sophisticated Financial

products and instruments in a

decentralized context if you're not

super familiar with financial

terminology

some of this might be a little bit

difficult to grasp but it is a

phenomenal Rabbit Hole to go down and it

is a absolute ton of fun there's so many

cool things you can do in Defi and in my

mind defi is one of if not the most

interesting and most important

industries and applications that smart

contracts enable so I highly recommend

you get used to some def some great

places to learn about defi are going to

be places like bankless which has a

podcast that I listen to again like I

said metamask learn to learn more

specifically about wallets and safety

about wallets and honestly so many more

most Concepts that you've learned in web

2 or traditional Finance translate over

to defi really well one of my favorite

things to tell people to do is to try

out a and Unis swap to really see how

some of these protocols work so if we

scroll down here we can go to the

website same thing with this one scroll

down we can go to the website here in a

we can even launch the app and we can

see

what this app even looks like let's go

ahead connect our wallet here I am going

to switch to I'm going to check my chain

that I'm on we're on too testnet if you

look up at the top one thing that's

really cool is you can see this little

ipfs thing here this little ipfs thing

only happens with brave but it means

that this site is also hosted on ipfs

right web 3 all about decentral but if

we scroll down we can see we can supply

different assets and get an interest

rate on those assets we Supply them for

example if we were to supply usdc which

is a United States dollar Peg stable

coin we'd get 2.45% interest similar

exactly to how a bank account works the

reason that we get this interest is

because there are other people who are

borrowing these assets again similar to

a bank and they get charged in interest

rate for borrowing these assets so if

you supply assets you get given an

interest rate and if you borrow assets

you get you have to pay some interest

rate this is why this protocol is so

cool it's permissionless banking

permissionless borrowing and lending of

assets Unis swap is another really cool

application where you can very easily

swap tokens between each other for

example let's if I were to switch to

ethereum mainnet I could choose

something like eth and swap to and asset

the a governance token and it's a

permissionless decentralized exchange

and really enables access to financial

markets in a much more transparent more

accountable and fair way and I just get

absolutely excited about working with

these for those of you looking to get

started here I definitely recommend

trying to use some of these on test Nets

unfortunately not all of these work on

test Nets but I have a couple videos

that shows actually working with some of

these that we can that we can go ahead

and actually watch such as leverage

trading in defi become a defi Quant

flash loans with a which is an advanced

defi tool and a couple of more and when

working with these I don't recommend

doing this on the eum main chain I would

recommend doing something like polygon

optimism or arbitrum where it's going to

be a lot cheaper to make transactions

ethereum fees right now are too high and

that's why we have scaling with layer

twos like arbitrum and optimism one

other thing that I should absolutely

mention now that we're getting into defi

is that there's this topic that we're

not going to have time to go over called

meev M or minor extractable value or

maximal extractable value depending on

who you ask is something something that

plagues the defi industry and something

that a lot of eth cord devs and

protocols like flash Bots are working on

right now basically the concept is if

you are the validator who gets to order

the transactions in a block you can

order those transactions in such a way

that benefit you there are a lot of

different protocols working on

mitigating me and preventing me in the

future or making it more fair and

there's all types of opinions on me I

100% recommend that if you're looking to

go more into really deep meev more into

really deep defi stuff you check out

this flash.net new to me repo and check

out some of these videos and blogs they

are absolutely astonishing to read they

are a ton of fun to read and also show a

terrifying side to the ethereum world as

well but in any case the project that

we're going to be building in this

course is going to be a stable coin now

the concept of stable coins is a bit of

an advanced topic believe it or not

maybe you've heard some stuff about it

maybe haven't in any case we're going to

watch a video that I made previously

about stable coins and what they really

are and what a lot of mainstream media

actually gets wrong about them and by

doing this we as developers are going to

have a much better understanding of what

these stable coins really are and how

they actually work under the hood this

is going to be a tough lesson and I'm

going to say this straight up it's going

to be very difficult there's a lot going

on here I want you to be absolutely sure

to go to chat gbt and ask chat gbt

questions absolutely in the GitHub repo

associated with this course be sure to

use this discussion Tab and ask a lot of

questions in fact if you want you can

even browse around the makerd Forum

which is the protocol behind the die

token which is what our project that

we're going to build is very roughly

based off of and kind of read what

people in the industry are actually

working with and actually doing like I

said there is a lot to defy and this

project that we're making I'm actually

planning on getting audited after we

release this course and this is easily

going to be our most advanced project in

the course hands down even though we

have a couple lessons after this

upgrades governance and introduction to

security this Foundry stable coin

project is the most advanced product

we're working with hands down if you're

able to go through this and understand

everything in this lesson you should be

incredibly proud of yourself and

Incredibly excited to move forward

because this is a hard project and

that's okay take your time don't

overburden yourself there's a lot to go

through here if you've never understood

defi take some time and look into defi

if we go to Google we look up like learn

defi we get a to coin Telegraph article

get some medium

articles maybe even Udi coinbase

coinbase actually has a great article on

this there's a lot of places to learn

about D5 so yes I do recommend if you're

completely unfamiliar with D5

pause the video now take at least 15 20

minutes just to do some Google searching

around right any knowledge that primes

you for this next session is great and

there's really just so much to defi the

main thing is that defi is

permissionless open-source finance and

to me it is the absolute best thing

about smart contracts with defi we can

actually move away from financial

institutions and products that have no

transparency that don't help you that

have centralization risk in the last 20

years have been a history lesson on why

we need defi to take over the world so

definitely want you to do a little bit

of research here so let's do a walk

through the code and then let's walk

through this video on what stable coins

actually

are so here's our codebase if we go into

SRC we see two main files we have

decentralized stable coin. soul and if

we look at into here it's a real

minimalistic very basic is erc20 we've

got some more interesting more advanced

Imports such as erc20 burnable and

ownable but here it looks real similar

to an erc20 right we've got a

Constructor with erc20 we have a burn

function where we can actually burn

tokens remove tokens and we have a mint

function where we can mint and print new

tokens but the main contract is this DSC

engine. soul so this decentralized

stable coin is controlled by this DSC

engine and this has a ton of stuff in

here so of the main functionality in

here is going to be where we deposit

collateral and mint DSC so this stable

coin is going to work because it's going

to be backed by collaterals that have

monetary value we'll talk about more

about that in a minute you can redeem

your collateral remove your collateral

look at all this natat spec by the way

look at all these these comments we we

can burn DSC we can burn our

decentralized stable coin people can get

liquidated what the heck is liquidation

we'll talk about that later they can

mint DSC if they have enough collateral

and we'll talk about collateral soon

deposit collateral redeem collateral Etc

but there's a whole bunch of collateral

stuff and we'll explain that in a little

bit we have this test folder where we

have our unit tests where we go over

engine where we test the engine the

stable coin and also this Oracle lib

thing we have mocks which we know mocks

are and then we have this thing that we

kind of briefly went over which is fuzz

test and we have this invariant thing

that what is this invariant thing and we

have this new type of invariant

underscore test which we're going to go

over and we're going to explain these

invariant tests separate these invariant

tests in my mind separate mediocre

solidity developers from incredibly

powerful incredibly Advanced solidity

developers we've got our scripts as well

real minimal here we mainly just deploy

the stable coin we're going to be using

chain link price feeds to measure the

price of the underlying collateral again

we'll talk about that soon but this is

really the the highle walkthrough and

you can find all the code and all the

information you need on this repo like I

said this is going to be an advanced

section take your time with it be sure

to ask questions use all the tools you

have at your disposal to code along and

understand what we're doing but the

other reason why I wanted to make a

stable coin here is because I strongly

believe stable coin coins are going to

be one of the most important D5

Primitives or D5 products that web 3 has

to offer and in my opinion right now the

current Solutions aren't good enough so

hopefully this inspires some of you to

go out and build a better one but let's

go ahead let's go into this video let's

learn about stable coins and take your

time learning this all right let's watch

this

video when you research stable coins

today you get a lot of misleading

information and that's what we're here

to clarify today in this video we're

going to teach you everything you need

to know about stable coins but actually

what are stable coins why we care

categories and properties designs of top

stable coins and then the real reason

behind what they do what stable coins

really do this video is for both

everybody Technical and non-technical

and we're going to correct a lot of the

misleading information out there there's

going to be a lot of information here

for people less familiar with defo so as

always don't be discouraged if something

doesn't make sense the first time you

buckle up buckle up dum dum we're in for

a volatile ride about stability a stable

coin is a nonvolatile crypto asset

that's it fleshed out we could rephrase

it to a stable coin is a crypto asset

whose buying power fluctuates very

little relative to the rest of the

market and this is the first place where

we disagree with traditional media if

you Google what is a stablecoin you'll

see something like this response

everywhere stable coins are

cryptocurrencies the value which is

pegged or tied to that of of another

currency commodity or financial

instrument and to that I disagree I

think that's an easy initial way to

understand them but not the whole story

a stable coin is a crypto asset whose

buying power stays relatively stable a

good example of buying power would be an

Apple Market if you want to a market to

buy apples with Bitcoin 6 months ago the

number of apples you could buy would be

drastically different than the number of

apples you could buy today that's an

example of buying power changing and not

being very stable however someone buying

apples with do

would probably be able to buy the same

amount of apples 6 months ago to now

that's an example of buying power

staying relatively the same since we

could buy the same amount of apples

today than 6 months ago a dollar would

be considered a more stable asset

whereas Bitcoin would be much less

stable this is what we mean by buying

power an asset whose price fluctuates

rapidly all the time is a poor example

of stable buying power oh it went to

zero this for example would not be a

stable asset now a stable crypto asset

is just a stable asset that's a

cryptocurrency most cryptocurrencies by

Nature aren't stable but we will give

examples of stable coins so summary here

a stable coin is a crypto asset whose

buying power stays relatively the same

and if that's all you take from this

video Perfect great let's keep going now

why do we care about stable coins

because money is

important but not like I Love Money type

of important in everyday Society we need

some type of low volatility AKA stable

currency to fulfill the three functions

of money and for web 3 we need a crypto

version of this the three functions of

money are storage of value unit of

account and medium of exchange storage

of value is a way for us to keep the

value and wealth we've generated putting

dollars in your bank account or buying

stocks cryptocurrencies is a good

example of storing your value apples

would make for a poor storage value

since they would rot over time and lose

their value unit of account is a way to

measure how valuable something is when

you go shopping you see prices being

listed in terms of dollars this is an

example of the dollar being used as a

unit of account pricing something in

Bitcoin would be a poor unit of account

since the prices would change all the

time medium of exchange is an agreed

upon method to transact with each other

buying groceries with dollars is a good

example of using dollars as a medium of

exchange buying groceries with car tires

would make for a poor medium of exchange

since car tires are hard to transact

with in order for our everyday lives to

be efficient we need money to do all

these three things and like I said in

web 3 we need a web 3 money we need to

be able to know the value of stuff in

web 3 be able to pay for things without

prices going crazy and we need to be

able to store our wealth in web 3 in a

decentralized world we need a

decentralized money assets like ethereum

work great as a storage of value and

medium of exchange but fall a little bit

on their unit of account due to their

buying power of volatility however maybe

in the future as ethereum BEC more

adapted it'll become stable and and we

won't even need stable coins but right

now it's a little too volatile and yet

I'll still tell you it's ultrasound

money since I do think it's an amazing

store value but that's a conversation

for another time banket don't kill me

I'd love your content also if you're

here be sure to like And subscribe

because we're just cooking the fire up

and we are about to pop off anyways okay

so now we know what a stable coin is why

we care let's talk about the different

categories of stable coins and here is

the second place I strongly disagree

with traditional media if you search for

types of stable coins you'll get some

that pulls them into categories like

this Fiat collateralized crypto

collateralized commodity collateralized

and then algorithmic now this isn't too

bad of a categorization it does make it

easier for new people to understand but

I think it paints a in acccurate picture

so let's categorize stable coins but

actually the categorizations that I like

are relative stability stability method

and collateral type so what are these

categorizations let's start with

relative stability when we talk about

stability something is stable only

relative to something else the most

popular type of stable coins is pegging

or anchored stable coins and these are

stable coins that are pegged or anchored

to another asset like the US dollar

tether D and usdc are all examples of US

dollar pegged stable coins they Follow

The Narrative of one of these coins

equals $1 and that's how they stay

stable it's stable because they track

the price of another asset that we think

is stable

and most of these stable coins have some

type of mechanism to make them almost

interchangeable with their pegged asset

for example usdc says that for every

usdc token printed or minted there is a

dollar or a bunch of assets that equal a

dollar in some bank account somewhere so

the way it keeps its value is that at

any time you should be able to swap your

usdc for the dollar or at least

hypothetically so something like d on

the other hand uses a permissionless

over collateral ization to maintain its

Peg but we'll get to understanding that

a little later however a stable coin

doesn't have to be pegged to another

asset it can be floating remember to be

considered a stable coin its buying

power just has to stay relatively the

same over time so a floating stable coin

is floating because its buying power

stays the same and it's not tied down to

any other asset with this mechanism you

could hypothetically have a stable coin

that's even more stable than an anchored

or pegged stable coin let's look at an

example let's say I can buy 10 apples

for $10 today but in five years I can

only buy five apples with $10 so it

would cost me $20 to buy 10 apples this

isn't an unheard of phenomenon to happen

and it's commonly just referred to as

inflation now let's introduce a stable

coin whose buying power floats up and

down with the market for now let's just

pretend it does so magically and let's

call it Apple coin today you can buy 10

apples with 10 Apple coins and in 10

years you can also buy 10 apples with 10

Apple coins which one of these assets

would you say is more stable yes the

Apple coin's buying power stayed the

same over the 5-year period so we'd say

it's a more stable asset even though

it's not pegged to something like a

dollar and Yes stable coins like this do

exist and they use a lot of clever

algorithms to do this one such example

is the Ry stable coin by reflexor Labs

how Ry Works might be its own video but

we've left some links in the description

for you if you want to learn more about

how it works because this concept can be

a little hard to grasp to further

explain it let's go through another

analogy let's look at the anchor and the

buoy in this image which of these do you

think is more stable the anchor or the

buoy well it depends on what you're

comparing them to compared to sea level

the buoy is more stable since it'll

always be at sea level as the water

level rises and Falls the distance

between the anchor and the sea level is

constantly changing the buoy is an

example of a floating stable coin now if

we compare these two to the ocean floor

though the anchor is more stable of the

two since it'll always be right on the

ocean floor this is analogous to a

pegged SL anchored stable coin now if

we're going to be really serious with

this analogy then the question might be

well what happens when a storm comes or

what happens when the water's crazy or

the Tide's crazy or something and to

that I'd say you're right and a stable

coin needs to take extra precautions to

take these into account and maybe get

the average sea level over the course of

time and most popular floating stable

coins have some mechanism to account for

turbulence like that summary Peg stable

coins are tied to that of another asset

while floating stable coins use

different mechanisms to keep the same

buying power over time number two

stability method the stability method is

this mechanism that keeps the coin

stable if it's a peg stable coin what is

the pegging mechanism if it's a floating

stable coin well what is the floating

mechanism and it typically revolves

around minting and burning the stable

coins in very specific ways and usually

refers to who or what is doing the

minting and burning these are on a

spectrum of governed to algorithmic in a

governed stable coin there is a

governing body or a centralized body

that is minting and burning the stable

coins you can imagine the maximumly

governed and least algorithmic coin

would be a single person/ entity minting

new stable coins promising that the

coins are not volatile but it could also

be an organization like a government or

even a dow choosing to Mint and burn new

coins these govern coins are typically

considered centralized since there is a

singular body that is controlling the

minting and burning you can make them

more decentralized by introducing a dow

and that kind of makes them more

algorithmic but we'll get more into that

later coins like usdc usdt and TUSD are

examples of governed stable coins on the

other hand an algorithmic stable coin is

a stable coin whose stability is

maintained by a permissionless algorithm

with no human intervention and this is

the third place where I disagree with

traditional media a coin like dy I would

consider much more algorithmic than

govern because uses a permissionless

algorithm to Mint and burn tokens

whereas traditional media might say an

algorithmic stable coin is always under

collateralized or follow senior in

shares or something like that but an

algorithmic stable coin is just when a

set of autonomous code or algorithm

dictates the minting and burning there

are zero meddling humans would have been

mine if it hadn't been to those meddling

kids examples of algorithmic stable

coins are going to be die frax Ry and

yes the $40 billion

disaster us yes we're going to talk a

little bit more about classic us and

Luna now a token can have algorithmic

and governed properties in the same way

that it can be somewhere in the middle

of being floating and pegged D for

example does have an autonomous set of

code that dictates the minting and

burning but it does also have a dow

where they can vote on different

interest rates and what can be

collateral types and different things

like that so technically it is a hybrid

system it has some governance mechanisms

and also some algorithmic ones usdc C

would fall purely in the governed

category because it's controlled by a

centralized body us and Luna would fall

almost purely in algorithmic the dirt

roads Blog has some amazing takes on

these pieces and a wonderful

visualization of where on a spectrum of

coins that are more algorithmic or

govern they use dumb as the opposite of

algorithmic instead of govern which

probably isn't wrong most classically

categorized Fiat collateralized stable

coin almost all fall into the Govern or

dumb section since they are dealing with

fiat currency and you need a centralized

entity to onboard that Fiat to the

blockchain you'll also notice on this

chart they have anchored versus

reflexive on the x-axis that's referring

to how the collateral type affects the

stable coin and collateral type is what

we're going to cover next so the summary

here though is algorithmic stable coins

use some sort of autonomous

permissionless code to Mint and burn

tokens whereas a govern stable coin have

some human interaction that mints and

burns the coins and keeps them stable

now before we go into to our final

category let's look at this chart again

we could replace the word anchored with

exogenous and reflexive with endogenous

and we'd have a chart that shows

collateral type versus stability

mechanism which brings us to number

three collateral type now when we say

collateral we mean the stuff backing our

stable coins and giving it value for

example usdc has the dollar as its

collateral and it's the dollar that

gives the usdc token its value because

you hypothetically can swap one usdc for

$1 die is collateralized by many assets

for example you could deposit eth and

get minted dye in return and US was in a

roundabout way collateralized by Luna

exogenous collateral is collateral that

originates from outside the protocol and

endogenous collateral originates from

inside the protocol so one of the easier

ways to Define what type of collateral

protocol is using is to ask this

question if the stable coin fails does

the underlying collateral also fail if

yes it's endogenous if no it's exogenous

if usdc fails the protocol does the

underlying collateral the dollar failed

no so the protocol has exogenous

collateral if the usdc stable coin fails

the dollar is going to keep being the

dollar if die the stable coin fails does

the underlying collateral eth also fail

no so the die system is exogenous the

value of eth isn't dependent on the

value of Dy if us fails does the

underlying collateral Luna Tera fail yes

absolutely and this is exactly what

happened that caused the system to lose

40 billion dollars in what seemed like a

day exogenous collateral originates from

outside the protocol endogenous

collateral originates from inside the

protocol two other good tests that you

can ask are was the collateral created

with the sole purpose of being

collateral or does the protocol own the

issuance of the underlying collateral if

the answer is yes to either one of those

then it's endogenous collateral now the

traditional media usually says that

algorithmic stable coins are to blame

but I think what they're really

referring to is endogenously

collateralized table coins it makes

sense that they can be scary and

potentially dangerous because their

value kind of comes from nothing

exogenously collateralized stable coins

are typically over collateralized

meaning there's more value of collateral

than there is of the stable coins here

we have another image from dirt roads

comparing different stable coins the

exogenous versus endogenous collateral

of the protocol calls and how much they

have maker d/ diey has almost all

exogenous collateral frax which is

another stable coin we haven't really

spoken about too much has a mix of

exogenous and endogenous collateral and

the old teral Luna and US system had

mainly endogenous collateral which is

how the system was able to crumble so

quickly so yeah endogenously

collateralized stable coins don't have a

great track record so why would you want

to make one well the answer is scale and

often times people also say Capital

efficiency with exogenously

collateralized stable coins the only way

you can mint more stable coins is by

onboarding more collateral you can only

have a stable coin market cap that is

high or as high as that is the value of

all your collateral so if you want to

have $68 billion in stable coins that

that means you need to have $68 billion

worth of collateral and that's a lot of

money that you would need to onboard to

your system if you have an endogenously

collateralized stable coin you can have

$0 worth of collateral meaning it's much

easier to become massive faster now I

agree with the dirt roads publication

when they say that exha usly

collateralized stable coins can't scale

and I talk more about that in the blog

associated with this video so if you're

interested be sure to check that out

after the rest of this video but watch

the rest of this video cuz we're just

getting started in the blog we also talk

more about seniorage shares and shelling

coin logic which if you're interested in

that stuff definitely check it out most

of these endogenous coins can be traced

back to a paper written by a man named

Robert Sam

where he talks about how to build an

endogenously collateralized stable coin

using a seniorage shares model which

again I'm not going to go into but I

wanted to mention it because it's

probably one of the most influential

papers when it comes to these

endogenously collateralized stable coins

endogenously collateralized stable coins

there a lot of words now there's more

information on the endogenous collateral

debate in the blog but let's do a

thought experiment that I do think is

compelling for endogenous collateralized

stable coins endogenously collateralized

stable coins imagine you have a currency

and it's collateralized 100% by gold and

you run a bank and it's open 24/7 to

allow people to exchange your generic

coin for gold in your vaults people love

the convenience of our stable coin

instead of having to Lug around their

gold so they treat our stable coin as if

it was gold because they know that at

any time they can exchange it at the

bank this is an example of our generic

coin being exogenously collateralized by

gold pegged to its price and governed by

By Us by Me by our entity since we own

the issuance and burning of the coin you

come to our bank we'll issue this coin

or we'll burn it once you redeem your

gold and since you can always exchange

our coin for gold our coin keeps its

value now let's say the bank is only

open 5 days a week does our coin lose

its value now that you can't always

exchange it for gold well probably not

the market probably won't even care now

let's say you need to close the bank for

a week for renovations does our coin

lose its value now well let's say we

close the bank for a month or a year or

a decade forever if we get to the point

where you could never actually exchange

our coin for gold or the underlying

collateral again maybe do people just

use the coin as its currency backed by

nothing in a way now it's moved from

being exogenous to now being endogenous

since it's now backed by well itself

this is why dirt roads has reflexive on

their chart one of our coins is no

longer equal to some amount of gold it

now equals one of

itself okay I know there's a lot here

and there's even more in the blog so if

some of this confused you don't be

discouraged you can always come back

there's a ton of supporting documents

and blogs and links that I personally

watch to learn a lot of this as well so

be sure to use that if you get confused

but now let's look at some of the top

stable coins what their properties are

and then we're going to get to some

really interesting stuff we're not going

to go too deep into the architectures of

the stable coins we are going to go over

d a little bit more though because the

die/ maker di system is a pretty

standard model for what a stable coin

could look like and it was one of the

most influential stable coins ever

created so there's that and it's

important that we go through these so we

can understand what's currently out

there and why they're currently out

there and then we can

reveal why they're really out there why

there's so many stable coins what are

the incentives for people to Mint them

and it may just blow your mind so let's

start with Dy as we've mentioned before

Dy is a pegged algorithmic and

exogenously collateralized stable coin

it's one of the most influential di

projects ever created and was a huge

factor in supercharging the dii space

roughly the way it works is you deposit

eth or some other crypto collateral into

the smart contract that has this die

algorithm code and based off the current

collateral to US dollar or eth to US

dollar price it'll me you some amount of

die you can only mint less dye than the

total value of collateral or eat that

you have this way the system always has

more collateral then they'd have minted

dye additionally every year or so you'll

get charged something called a stability

fee usually around like 2% and now

you're free to do whatever you want with

your die if you want to get your eth

back you have to give your die back to

the smart contract which will then burn

your diey it'll use the current price of

e to figure out how much money it should

give back to you it's because of this

stability fee and collateralized E that

people often refer to this system as a

collateralized debt position since we

technically owe D back to the protocol

at some point so yes all the Dy that's

in existence somebody minted from the

maker protocol and needs to pay it back

at some point if you can't pay your

stability fees or the price of e tanks

and now the value of our collateral is

less than the value of the die that we

minted people can liquidate us which

means they can take our collateral

protocol always needs to have more

collateral than men to die so this is

sort of your punishment for not keeping

the collateral up and a way to save the

system from becoming under

collateralized and then there's also a

maker token that's used to vote for

stuff now the reason I give this

overview is I want your brain to be

asking the question hey uh I get charged

to Mint a stable coin all the die in the

world somebody's being charged to have

it out there someone could take my

collateral if I don't monitor the

balance and most importantly why would I

spend money to Mint this stable coin why

would I be the one to do that great

question that is the fundamental

question and we'll get to that usdc usdc

is a classic pegged governed exogenously

collateralized stable coin it's backed

by real world dollars in a bank account

not much else to say here USD and Luna

the classic old USD and Luna we know it

collapsed but we can learn from what

happened to hopefully prevent it in the

future us was a stable coin pegged to

the dollar algorithmic and endogenous

and it imploded on itself using what we

know about stable coins can you guess

why well since the system was endogenous

once Us lost its Peg Luna became less

attractive to hold since people weren't

holding Luna the price fell and it made

it harder to keep the peg of us which

made Luna's price fall which makes us

harder to hold its bag which makes you

see the pattern people still want to try

using these endogenously collateralized

stable coins because they do scale so

quickly so protocols like frax have come

a long way to do some type of hybrid

between endogenous and exogenously

collateralized stable coin Rye Ry is one

of the few floating stable coins where

it's not pegged to any other asset it's

focused on minimal governance being

floating and using only ethereum as

their type of collateral with a nearly

purely algorithmic stability mechanism

in a way one could argue that because

their collateral is only e the price of

Ry will always be somewhat pegged to the

price of eth but that might be a longer

argument due to the it's floating

algorithmic and exogenously

collateralized now they use some really

cool supply and demand mechanisms to

keep the price stable and nonvolatile

but it's not really important how it

works for the purpose of this video so

once again I'm going to leave some links

in the description if you want to learn

more about Ry the video on screen right

now I think is particularly good at

explaining exactly how it works and

explaining why it's such a good stable

coin for normal average people to have

so now that we've gone over some stable

coins we've gone over the categories why

why we care what is a stable coin let's

talk about what they really do we can

start by asking the question okay which

one of these is the best stable coin and

to that I need to ask the best stable

coin for who centralized govern coins

obviously have the issue of centrality

which sort of defeats the purpose of

being in web 3 so maybe we want some

flavors of algorithmic stable coins

maybe that's probably what we want for

web 3 but these algorithmic coins might

feel untested to non- crypto people and

the fees ass associated with them might

be a little bit scary for me personally

like I said I really love the idea of Ry

the idea is to have stable buying power

as opposed to being pegged to some other

asset and it's algorithmic nature as

opposed to being centralized so it's a

decentralized stable coin that's what we

want but every coin has their trade-offs

and I'd argue there is definitely no

best coin right now the stable coin

that's best for the average person might

matter much less it's the stable coin

that's best for Rich whales might be

what's more important here yes the

stable coins the whales like might be

what's more important now for most

algorithmic stable coins you'll see this

some sort of fee associated with minting

the coins protocols do make money off of

the stable coin systems which I think is

good sometimes they need money for

maintenance incentives for the stability

of the coin or money for improvements so

I do think these fees are good and we

need stable coins for the three

functions of money storage of value unit

of account and medium of exchange but

are you going to be the one to pay these

fees to Mint them and keep them in

circulation someone has to pay to Mint

these coins and often keep paying the

market cap for some of these stable

coins is in the billions if there is a

1% fee on these and the market cap is 1

billion we're talking about $10 million

our average people going to collectively

pay $10 million a year to keep these in

circulation no so average people aren't

printing these for the three functions

of money well then who is minting these

so let's play a little thought

experiment let's say I have eth as an

investment and I've bought up all the e

I've sold my house I've sold everything

I own and I've used everything I have to

buy ethereum but I want more what can I

do I can put my eth into one of these

stable coin protocols get the minted

stable coin and then sell the stable

coin for more eth you might have heard

Concepts like Leverage investing or

margin trading and this is essentially

the web 3 equivalent it's kind of funny

why are stable coins good well because

we need those three functions of money

but why are stable coins minted well

because investors want to make leveraged

bets in fact most stable coin platforms

have this as one of the biggest reasons

to minth their stable coin to multiply

exposure or to maximize your position on

some crypto asset now for sophisticated

investors this isn't new information at

all this is like investing 101 however

it does feel weird that we need stable

coins for the three functions money but

that's not why they're minted so even

though I said I really like Ry as a

stable coin for the people a reason D

might be higher market cap is that

investors like The Leverage opportunity

much more than they like the leverage

opportunity that Ry offers it could be

something else but that might be a big

reason how much stable coins are minted

are based off of how much investors

think they can use that stable coin to

get more exposure to assets that they

really want so I know we've gone over a

lot here and the rabbit hole really

doesn't end there curve. Finance being

one of the most important protocols for

stable coins is a really interesting

story as well my friend Garrett who

teaches about technology and finance has

a fantastic example as to why a stable

coin exchange might be so important you

might wonder how a stable coin exchange

ever got off the ground is there really

any demand out there to trade $1 for $1

then I think back to my university days

one weekend my laundry pile grew so

disgusting I was desperate to use the

washing machine immediately but the

laundry machine took quarters and I only

had dollar bills quarters were in such

short supply around the dorm room that I

was willing to pay more than $1 for four

quarters in this urgent moment I had

specific utility in mind and that

changed my personal equation for this

and a and curve both looking to launch

their own stable coins soon is going to

be really interesting as well so we'll

just have to see how these unfold I do

think though that we are going to get

better and better at creating these

stable coins because we do need they are

important and for you developers

watching who want to build one of these

we have some minimal stable coin

contract examples in our def minimal

repo Link in the description so if

you're looking to tackle this problem

definitely be sure to get started there

I'm really excited for the future of

Defi and for the future of stable coins

as I think they are a wildly important

primitive for Defi and I know that this

was a long video but I hope you all

learned something and I hope this gives

you a better idea of what stable coins

really are and how they're created if

you learned something leave a comment in

the comment section if you didn't learn

something leave a comment in the comment

section or if I got something wrong

leave a comment there thank you all for

watching and I'll see you next

time all right we have now learned a ton

about Defi and hopefully I piqu your

Curiosity on how much more there is

still to learn but now we're going to

move on to creating our own stable coin

here so again you can follow along with

all the code that we're going we're

going to be going over in this Foundry

defi stablecoin f23 section of this

course and like I said I'm planning on

getting this code actually audited so be

sure if you have your GitHub repo be

sure to watch this repo and look for

updates I will be posting the audit

reports in this as well I've got a

couple videos on what smart contract

audits are and why they're so important

and I'll leave a couple links in the get

AO associated with this course for those

of you looking to go down the security

track definitely be sure to watch this

video but our right we are finally in

our GitHub repo let's build this stable

coin mkdir foundary defi stablecoin

f23 let's open this up with code or you

know the drill file open folder we're

going to be going a little faster this

lesson because a lot of what we're doing

is just going to be drilling in

information that you already know we

have a couple of new things to go over

such as stateless fuzzing which we'll

talk about in a bit but a lot of the

coding aspect of this you already know

all right we're in our folder Forge nit

clear let's make a little read me over

here and talk about the design of our

protocol so we're going to make a stable

coin but if you watch that stable coin

video we're going to make a stable coin

that is one anchored so when we're

talking about the relative stability

it's going be anchored or pegged to the

US dollar so this means we're going to

have to put some code in here to make

sure that our stable coin is always

worth $1 number two the stability

stability mechanism or the way we do

minting is going to be

algorithmic this means that this is

going to be a decentralized stable coin

there's not going to be any centralized

entity that's going to Mint or burn or

maintain the price this is going to be

100% onchain And algorithmic which is

ideally what we have for the future of

stable coins there's no controlling

entity that controls our stable coins so

this is great A Better stable coin for

web 3 probably isn't anchored or pegged

it's probably floating but that's a much

harder mechanism to do so we're going to

go ahead with the anchor to Peg for the

moment and then finally the collateral

type is going to be you guessed it

exogenous and it's going to be crypto

collateral we're going to use

cryptocurrencies as collateral for for

this currency we're going to use

ethereum and Bitcoin as the collateral

for our system here so with this being

our architecture we're going to keep

this in mind okay how can we actually

make sure that this is always Peg to a

dollar and one way we can do this is

with a chain link price feed so with a

chain link price feed we get the price

feed and we set a function to exchange

eth and Bitcoin or whatever their dollar

equivalent is and this way if right in

our contract we have this exchange set

up price of this stable coin should

hypothetically always be around a dollar

to make the stability mechanism

algorithmic we're going to say people

can only mint stable coin with enough

collateral and that's going to be CED

directly into our protocol and the

collateral type being exogenous of

course we're only going to allow these

two types of cryptocurrencies to be

deposited specifically we're going to

use wrapped eth and wrapped Bitcoin so

the erc20 version of eth and the erc20

version of Bitcoin some might argue that

this wrapped Bitcoin is a little bit

centralized depending on who is

onboarding the Bitcoin into ethereum but

that's another conversation so over

collateralized stablecoin with we and

Bitcoin as the collat for this let's do

this so the first thing we're going to

do is is we're going to well we're going

to get rid of all these goodbye goodbye

goodbye delete and now we're going to

create our two main contracts new file

D

centralized table coin do a capital c.

soul and this is just going to be the

actual token so I'm actually going to

copy paste my layout of functions

because I like them I like to have this

and at the top of course spdx

license identifier MIT if you want you

can just copy this directly from GitHub

repo associated with this course

SRC right here copy this layout here I

like to have it as a reference then you

already know pragma solidity

0.818 and we'll do contract

decentralized

stable coin boom like this and now this

is going to be one of the main

differences between this code writing

here and all the other products that

we've done we're going to be very

verbose with our code documentation and

the reason for this is is when it comes

to Security Professionals who are going

to review this code we're going to make

their lives so much easier if we have a

ton of text explaining what our code is

doing additionally if you work with AIS

AIS are fantastic at reading and

understanding language so the more

language that we have to explain what

our code should do the better off our

code can be sent through some AI model

to make sure that it doesn't have issues

so we're going to go ahead add a little

bit of npec here right from the get-go

at Title

dentra by stable coin all one word at

author Patrick Collins or put your name

here Yep this is open source MIT license

you can do whatever the heck you want

with it I'm even going to say collateral

exogenous eth and BTC

minting or the stability mechanism is

going to be

aloric meaning it's decentralized

relative stability is going to be pegged

to USD then I'm going to say under here

this is the contract meant to be

governed by

DSC engine this contract is just the I'm

going to toggle word rep here ear T20

implementation of our stable coin system

so that's what this is going to be this

decentralized stable coin is purely

going to be an erc20 with minting and

burning and stuff right it's not going

to be it's not going to have any of the

logic the logic is going to be in a

separate contract so let's go ahead and

let's make this so first Constructor

boom and we're going to use open

Zeppelin to get this kick started so

right at the top import well actually

before we even do that Forge install

open Zeppelin slopen Zeppelin D

contracts D- no- commit and we go ahead

we went ahead and installed that now

we're going to open up our Foundry dotl

we're going to add some remappings in

here so REM mappings equals at open

Zeppelin SLC contracts equals lib slopen

Zeppelin slash contracts slash contracts

that looks pretty good right up at at

the top of this now import little named

import

erc20 we're going to import this erc20

burnable contract I'll explain this in a

second and then also erc20 from atop

Zeppelin contracts toen

erc20

extensions erc20 burnable dossou did I

spell this right looks like that that's

right so what did I oh oops looks like I

spelled contracts wrong let's spell it

right okay cool that looks good now what

we're going to say is that our

decentralized stable coin let me even

zoom out a little bit Yep this is going

to be a big one so we're going to zoom

out a little bit here hopefully you all

can see this is ec20 burnable okay and

the reason that we're going to use this

contract if we command clicking it or

just look it up is it has this burn

function and we want this burn function

because this is going to help us

maintain the peg price we're going to be

burning a lot of these tokens you'll

understand that in a bit now same as an

erc20 so the erc20 burnable contract is

an erc20 which is why we can import the

erc20 contract from it as well and the

erc20 burnable Constructor is an erc20

which means we have to use the erc20

Constructor as well which takes a name

where we're going to call ours

decentralized stable coin and DSC like

this and that's it this is going to be

our whole Constructor we're not going to

touch it that's all we're going to do

let me zoom in a little bit I'm going to

keep zooming in and out hopefully it's

not too crazy now we want this coin to

be 100% governed by our engine and our

engine is going to have all this stuff

about what collaterals to use how to use

it what to Peg it to Etc this is purely

just going to be the token so since we

want this token to be 100% controlled by

our logic we're going to make this

ownable as well which means we're going

to have only owner modifiers where the

owner is going to be that immutable

logic we're going to create so open

Zeppelin has a package for that too so

we're going to do import ownable from

atop Zeppelin contracts

access ownable doso I'm going to copy

this so our contract is going to be

erc20 burnable and it's going to be

ownable and there's going to be two

major functions that we want our engine

to own those functions are going to be

function burn where it takes in a un

256 uncore amount public we're going to

override the burn function in burnable

this is going to be only owner so that

only the engine only the logic that we

give it can mint and burn and we're

going to say U 256 balance equals

balance of message. sender and we're

going to make sure that somebody when

somebody tries to burn some token they

at least have that much token so we're

first all going to say if the amount is

less than or equal to zero then they

can't burn right we don't want people to

try burning zero that's silly so we're

going to revert with an error put all of

our errors right up at the top here

error de centralized stable coin

underscore underscore must be more than

zero like this so we're going to revert

with this error and then we're also

going to say if the user's balance is

less than the amount that they're trying

to burn then we're going to revert with

another custom error I'm just going to

copy paste and I'm just going to say

burn amount exceeds balance boom paste

that in like this and then finally we're

going to do this thing called super. bur

which we haven't talked about yet so

this super keyword basically says hey

use the burn function from the parent

class which in this case is the erc20

burnable so all this code is going to

run it's going to hit this line it's

going to say hey go to the Super class

and use the burn function there so our

codee's going to go oh okay well ec20

burnable that's the super class or the

parent class ah just use the burn

function in here which calls the burn

function here in the ec20 so which does

all this stuff in here so that's what

the super keyword does only owner only

engine's going to add this now we're

going to do this function mint this is

going to be an address 2 and a uent

256 amount this is going to be public

excuse me this is actually going to be

external also only owner this one

probably could be external as well but

that'll come out in the audit external

only owner and this is actually going to

return a Boolean when you do mint you

want to have a return a Boolean here

when you do a mint we're going to return

true if it actually works but we're

going to say if 2 equals equals address

zero we're going to do a little

sanitization of the inputs here then

we're going to revert revert with a new

error error to centralized stable coin

not zero address we're not going to let

people accidentally mint to the zero

address because that happens kind of a

lot and we're going to say if the amount

is less than or equal to zero then we're

also going to revert with this more than

zero error here boom and then finally

we're going to return true oh and then

obviously we should run

mintor 2 Comm amount so we're not

overriding any functions in here right

we're just calling the mint function

over here we had to do super because

we're overriding the burn function and

we're saying hey do all this stuff and

then do the regular burn there is no

mint function there's an underscore mint

function that we're going to be calling

and guess what that's it this contract's

done we're not doing any more here Forge

build cool and then we probably want to

write some tests for this write a deploy

script but we're going to do all that in

a little

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

going to build the engine the engine to

the car the main components of this

contract you want to take a break and be

proud of you yourself right here go for

it if you want to even pause the video

start writing some of your own tests

write your own deploy scripts go for it

but let's go ahead and start building

this engine we're going to be building

this a little bit different than some of

the other projects we might even be

testing some of this along the way to

make sure we get things right so I'm

going to go ahead create a new file d c

n g. Soul centralize stable coin engine

and let's build this in engine to this

car all right let's go back to let me

grab I'm just going to copy paste this

beginning part let's come to the engine

paste that in we have spdx layout of

contracts

prag contract

DSC

engine this let's give this a lot of

natat speec all right title DSC engine I

don't want that at author a

or metrick Collins the system is

designed to be as minimal as possible

and have the tokens maintain a

$1 maintain a one token equals equals $1

Peg toggle the word WP this stable coin

has the properties Jus collateral dollar

pegged Alor

algorithm stable it is similar to D if D

had no governance no fees and was only

backed by wrapped eth and wrapped

Bitcoin at notice this contract is the

core of the

DSC system it handles all the logic for

minting and redeeming DC as well as

depositing and drawing collateral at

notice this contract is very Loosely

based on die on the maker Dow DSS die

system you might be asking Patrick

that's a lot of text here yes we want a

lot of text when people read our code

our code should be readable remember

your code is going to be written once

read hundreds of thousands of times I

have read the A and maker code so many

times and so many other people have as

well you want your code to be very

verbose so that other people can come

and understand what's going on so let's

begin so let's think about what are the

main functions that our project should

have what are the main things that we

should do right before we start even

start coding anything and often times a

lot of people will take this step and

will actually create an interface for

their code they'll create an interface

and say hey here's all the functions

that I want this to do and then they'll

say hey our contract is that interface

so that they don't forget any of those

functions for us I'm just going to go

ahead and write them out here so I want

one function to be function deposit

collateral and mint DSC I want people to

be able to deposit their die or their

Bitcoin and mint are DSC token I want

people to redeem their collateral or DSC

right when people are done with doing

whatever they want with the stable coin

they can turn the stable coin the the

DSC decentralized stable coin back in

for whatever collateral they originally

used I want people to be able to

function burn their DSC and the reason

for this is if they're nervous that they

have too much stable coin and not enough

collateral and they want just a quick

way to have more collateral than DSC

they can quickly burn stuff which is

another part of the system we should

even put a point in here our DSC should

our DSC system should always be over

collateralized at no point should the

value of all collateral be less than or

equal to the value of all the DSC

or the dollar backed value of all the

DSC we should always have more

collateral than DSE in the system at all

times and we need to code in such a way

so burn DSC is a function that will make

more sense in a little bit we should

have a function called liquidate and

this is going to be a really important

function the reason that we're always

going to have more collateral if the

value of their collateral drops too much

let's say let's say I put in $100 worth

of eth and I minted $50 worth of DSC I

have more collateral than DSC that's

good what if the eth price tanks to $40

40 eth now we are under collateralized

right now we have less eth than we have

DSC and keep and this user should get

what's called liquidated they shouldn't

be allowed to hold a position in our

system system anymore so ideally we set

some threshold that's too low maybe it's

maybe it's 20% and if you hold $60 worth

of eth and $50 worth of D DSC you should

get kicked out of the system because

you're way too close to being under

collateralized this liquidate function

is going to be the function that other

users can call to remove people's

positions to save the protocol and we'll

talk about that a little bit more very

soon and we're going to want a function

Health Factor this should be an external

view function or excuse me get health

factor and this will allow to see how

healthy people are so let's go back up

to this example here so if if the price

of eth dumps to $40 we're now $10 under

collateralized right and that's not good

that's really bad we never want this to

happen so what we can do is we can set a

threshold to let's say for this example

50% or

150% so if you have $50 in the system

you need to have at least 75 eth at all

times this way there's a little bit of a

buffer that way we can never be under

collateralized if the price tanks here

if you go to

$74 now what we can do is we can

liquidate and we can say hey if someone

liquid if someone pays back your borrow

your minted

DSC they can have all your collateral or

a discount so maybe we say hey somebody

pay back this 50 DSC and you can have

this $74 worth of eth somebody's going

to be very incentivized to do this

because they're going to make 20

$24 so we'll set some threshold maybe

150% and we'll we'll say hey anybody who

liquidates your position if you're under

the threshold they can have as a reward

some of your extra collateral this will

incentivize people to always have extra

collateral otherwise they're going to

lose way more money than they borrowed

that didn't make sense so one more time

let's do that example so if I mint so if

I put down $100 worth of eth as

collateral and I mint $50 worth of DSC

now I'm going to go off and do whatever

I want with DSC price of my eth tanks to

$75 or better yet let's say $74 so other

user is going to going to see oh my God

under collateralized and we're going to

let people liquidate their positions if

they become under collateralized based

off the threshold some other users going

to see that and they're going to say

okay I'll pay back the $50 of DSC I'll

pay back the $50 of DC so now this

person has zero debt and in return get

all your collateral so now this person

has $0 worth of eth and this user got

the

$74 and all they to do was pay $50 of

DSC to get $74 of eth so this person is

now up just made $25 or

$24 by liquidating you they're

incentivized to make money and this is

your punishment for letting your

collateral get too low so hopefully that

makes sense if this system of

liquidations doesn't make sense to you

you know where to go come to the GitHub

repos with this course and start joining

the discussion all right so hopefully

this made sense if it doesn't use the

discussions tab of course now these are

kind of this combination function we're

probably going to want a function just

called deposit this deposit collateral

external we're probably going to want a

function

redeem collateral external and then

we're probably going to want along with

a burn DSC we're probably going to want

a function mint DSC external and these

look like these are probably going to be

the majority of what a protocol does and

what a lot of people even do is

sometimes they'll even write tests right

now describing what each one of these

should actually do to the system right

we're not going to do that but we may

actually write some tests as we go along

here and I like to write my deploy

script kind of early and you'll see me

do that here that way I can write tests

using my deploy script so let's go ahead

though where is the best place to start

tackling this well to me the the easiest

place to start is actually with the

depositing right because that's the

first thing people are realistically

going to do with this protocol is

actually deposit the collateral so I'm

going to start there so for this deposit

collateral function what are they going

to want to do here well we're going to

need to let them pick what collateral

they want to deposit so we'll say

address token collateral address and

then also the unit 256 amount collateral

we're going to do a little toggle word

WP all right cool so deposit coll the

token collateral address and then the

amount that they're going to want to do

so already we can see that there's going

to be a whole bunch of stuff that we're

going to want to do here so let's even

doce a little bit of natspec bit of

natspec here we'll say at pram we'll

just explain what the prams are and this

is where get up co-pilot is really

helpful because often times it's really

good with docs so we're going to say Pam

RM so both of those look good token clat

all address the amount of token to

deposit as collateral amount collateral

the amount of collateral to deposit

right real simple so we're going to want

a couple of things here we're going to

want to sanitize this a little bit so

the amount collateral we're definitely

going to want this to be more than zero

so we're probably going to want a

modifier called more than zero that we

can use throughout these functions

sometimes people might accidentally send

a zero transaction we want to

automatically revert those so we scroll

up to the top here we see our modifiers

come before our

functions so we're going to create our

modifiers here and we're even going to

add like a little little section A whole

bunch of these

here boom

modifiers like this cool and we'll say

modifier more than zero and this

modifier will take a un

256 amount and we'll just say if mount

mount equals equals z then we're going

to go ahead and revert with a new error

where do errors go let's scroll to the

top errors

go right underneath Imports actually

it's not quite right they're going to go

right underneath the contract so we're

going to do we're going to copy this

whole

section say errors we're going to go

here we're going to say error DSC engine

uncore uncore what do we want to call

that just needs more than zero needs

more than zero this and we're going to

revert with needs more than zero and of

course add the little underscore here

cool so now we have a more than zero

modifier so we can make this external

more than zero and we'll pass the amount

collateral and boom okay cool we're

doing a little sanitization here what

else should we do you know let's even

copy this we'll paste this here we'll

say

functions and we're going to have a

Constructor

so I'm just going to put this here for

now Constructor should spell Constructor

right and then we're going to have a

section after functions like a

subsection we're going to call it

external

functions this external functions cool

CU we want to go receive and fallback

we're not going to have those but then

external and public so external function

first anyways okay more than zero got

that and we don't want people to use any

collateral right we probably only want

them to use certain collateral that we

allow so we're going to have to create a

new modifier called is allowed token so

we're going to do modifier is allowed

token this is going to take a address

token basically we're going to say if

the token not allowed the token isn't

allowed then revert right however at the

moment we don't have like a token allow

list so let's create that this is

probably going to be a state mapping so

let's scroll to the top where do state

variables go so errors type Declaration

state variables okay errors great let's

put it here State

variables okay and let's do our let's

create an allowed list of mapping so

we'll do

mapping address to BU you know private

sore token to allow and we could do this

however I already know that we're going

to need price feeds so instead what I'm

going to do is I'm not going to do an

address to Bull I'm going to do an

address to address and this is going to

be our price feed mapping so this is

going to be sore price feeds and

normally I do the syntax token to price

feed right well for this we're just

going to call this price feeds and we're

going to use the newer solidity named

mappings to make this a little bit

clearer so I'm going to say address

token maps to address price feed now

this is S price feed and anybody can

look up and go ah okay so this is token

to price feed cool so we're going to

have this list of price feeds and where

should we probably set this well we're

probably going to want to set this up

right in the Constructor right right

when we deploy this contract that's when

we're going to say okay okay these are

going to be the allowed tokens these are

the price feeds and that way it's going

to be like that forever right we're

never going to be able to change this so

what we'll do is in our Constructor now

we'll take in the the allowed tokens and

their price feeds right because in order

for this system to work go to like data.

chain. Link in order for this entire

system to work if we want to know how

much value our ethereum that people

deposit in here is worth we need to have

the pricing right the only way for us to

know if we're over collateralized if we

know the value of our eth in our Bitcoin

so we're going to use these two price

feeds to to maintain that because these

price feeds are going to be on different

addresses on different chains you

already know that we got to parameter

tize it so we'll do an address

array

memory token addresses comma address

array memory price feed addresses as

input parameters

and we're going to say token address

zero maps to price feed zero token

address one maps to price feed one Etc

and while we're in here I already know

that our DSC engine is going to need to

know about our decentralized table coin

why because our DC engine is going to

need to know to call burn and mint so in

here in the Constructor this is also

where we're going to pass the address

DSC address decentralized stable coin

address and so in here let's do some

vanity checks on this we'll say if the

token addresses. length does not equal

the price feed addresses price feed

address is price feed address is length

we have an issue right because if

there's more tokens or more price feeds

that means we mess something up so we're

going to go ahead and revert with a new

error go to our errors here we'll say

error DC engine uncore uncore token

address is and price feed addresses must

be same length a massive error I know

but I like being verose like I've told

you before so if those don't match we're

going to go ahead and revert then we're

going to Loop through the token

addresses and update our mapping that we

just created here to say okay the token

address is map to the price feed address

now in order for us to get a pricing

we're going to have to use the US D

price feeds and everything every price

feed that we're going to have to use is

going to be the USD back price feed so

for example it's going to be eth USD BTC

USD mkr USD Etc okay so we're going to

Loop through we're going to say four U

and 256 I equals z i is less than hen

addresses. length

i++ so we're going to Loop through this

token addresses array

and we're going to say sore price

feeds of token

addresses I is going to equal to price

feed addresses of I so we're going to

set up this price feed so whatever the

token so the token of I is going to

equal the price feed of I and that's how

we're going to set up what tokens are

allowed on our platform if they have a

price feed they're allowed if they don't

they're not allowed and then I know

we're we're going to do a lot of stuff

with our DSC so this is where this is

definitely going to be an immutable

variable so we can scroll up make a a

mutable variable we'll say so we'll say

decentralized stable coin private iore

DSC because we're going to make this

immutable and since we're using

decentralized stable coin we're going to

have to go ahead and import

this so let's go to the top here do

import decentralized stable coin from

decentralized stablecoin Soul so now

decentralized stable coin private idsc

you can now do oh excuse me this is

going to be private

mutable go bit down to the Constructor

we're just going to say idsc equals

decentralized stable coin DSC address

like that again using GitHub copilot if

you don't have GitHub co-pilot that's

okay there's a lot of other free AIS

that you can use as well Okay cool so we

set up our Constructor we're going back

down down to deposit collateral whole

reason we were doing this is we're

saying okay we should only allow certain

kinds of collateral on our platform so

now we can create a new modifier called

is allowed token where we can just say

if sore price feeds of token equals

equals address Zer then we can go ahead

and revert with a new oh that looks like

a good one DSC engine token not allowed

I'm just going to copy that go to the

top and thanks get up copilot just

autofilled it in for me okay great and

then of course we need to do this down

here Co so is token allowed more than

zero is allowed excuse me is allowed

token

token

collateral address like this all right

cool and then additionally I'm going to

add a non reentrant modifier here as

well we're going to grab this from open

Zeppelin whenever we're working with

external contracts it might be a good

idea consider making your function

non-reentrant

re-entrancy

and to be honest sometimes I'll just rip

a non-reentrant modifier even if I'm

pretty certain it's not vulnerable to

re-entrancy attack I feel like to be

honest most functions should be non-

reentered by default but especially when

working with external contracts it's a

good idea to maybe put this modifier

here now this might go to audit and we

might say hey well we don't need this

non-reentrant modifier and maybe we get

rid of it but maybe we don't the

trade-off is it's a little bit more gas

intensive to have this here but it's

also safer so I'm just going to stick it

in here even if I'm pretty certain I

don't need it we're going to get this

from open Zeppelin has a non- reentrance

a nonreentrant

modifier from their re-entrancy guard so

we'll import actually my GI co-pilot

automatically had it reeny Guard from

open Zeppelin contracts security

reentrancy guard. Soul yep that's

actually exactly correct and then what

we can do is scroll down and we see our

DSC engine is re-entrancy guard by doing

this we now have access to this

non-reentrant modifier and now this

function is non-reentrant which is what

we want okay cool now we can finally

start doing some collateral stuff so

we're going to go ahead and deposit this

collateral first first thing we're going

to need to do is a way to track how much

collateral somebody has actually

deposited so what's that look like well

that probably looks like a mapping to me

so let's go to the top we'll create a

mapping of address user

to mapping of an address token to un 256

amount private

sore

colateral the

posited so this is a mapping to a

mapping crazy right so we're going to

map the user's balances to a mapping of

tokens which is going to get mapped to

the amount of each token that they have

all right so let's scroll back down to

our deposit collateral function so now

we have a collateral deposited mapping

so we can do s collateral deposited of

message. sender of this token collateral

address now that we know it is an

allowed collateral address it's going to

be plus equal to the amount collateral

right and and I'm actually run into an

issue here where when I do Forge format

formats the code look like this but

right now when I'm saving it's

reformatting it a different way so what

I'm going to do is it looks like it's

using a different formatter that I don't

like so I'm going to go to the

extensions solity hard hat hit the

settings here extension settings and

we're going to change this from prettier

to forge because I want to use the forge

format settings now if I hit save okay

great it saves and formats the way I

wanted to okay great so as you can see

here we're updating State and what

should we do when we update State we

should emit an event so we're going to

emit

collateral deposited we're going to have

it be the message. sender who is

depositing the token collateral address

and the amount collateral as well which

means that that we have our first event

all right so let's go on up here Zoom

back out scroll all the way up to the

layout where do events go events go

after the state variables okay so I'm

going to copy this it go right after the

state variables before the modifier so

we're going to say events we're going to

go here we're going to say

event and get up co-pilot automatically

filled it in for me awesome address

index user address index token un 256

amount we don't really need to index

that maybe we do why not let's just

index it all right cool and just to know

a keyboard shortcut that I use a lot is

control back or control minus which

allows you to go back to the last spot

you were in your code if you do control

shift minus it'll go forward and I use

this all the time so for example if I'm

way down here in my code and I hit

control back I'll just go right back to

the last place my cruiser was and I use

this all the time I'm not sure what the

keyboard shortcut on Windows or linuxes

but on a Mac it is control back and

control shift back and I use it all the

time anyways so we are in deposit

collateral we have this emit here we

finally have the event and Okay cool so

we're updating the collateral internal

recordkeeping we're admitting a vent now

of course we should actually get the

tokens right and you can see here we're

following CI right so you do a little

notice follow follows CI checks effects

interactions so all the checks are

happening in our modifiers here these

are all the checks our effects are right

here and then finally our external

interactions so this is where we're

going to do that transfer from and we're

going to need to wrap our collateral as

an erc20 so we're going to need to call

transfer from on it so I'm going to go

ahead and import

ic20 from at open zeppin contracts SL

token

erc20 erc20 doou contrl minus to go

right back down to here isn't that nice

and we can finally do ic20 of the token

collateral address do transfer from

message. sender to address

this

amount all like this and we'll say so

this function actually returns a Boolean

full success and we want to make sure

that this is actually being true so we

want to say if not success we'll just

revert DC

engine uncore transfer failed like this

what's this an error you bet it is so

we're going to put this at the top erir

DSC engine transfer failed and I'm going

to hit control minus to go right back

down to the code that I was working with

Okay cool so this function look looks

pretty good to me I'm able to deposit

collateral in here and update our

mappings now might be a good time for us

to start writing some tests for this

right and we could do something similar

to what we did before where we just kind

of threw together a real quick setup in

our unit tests and then had our

integration tests be what our deploy

script actually uses well let's write a

couple more functions first and then we

can go ahead and and do all that

work so we have a way to deposit the

collateral okay awesome what should we

do next well the next thing that we

should do is have a way to Mint our DSC

token right once they deposit the

collateral they should be able to Mint

the DSC token and then the combination

of those two will be this function

deposit collateral and mint DSC so let's

go ahead and actually create this mint

DSC function because now that they have

some collateral we should be able to

Mint some DSC and now this is actually

going to be a surprisingly involved

method right cuz in order to Mint DS C

we need to check if the collateral value

is greater than the DSC amount and this

is obviously going to involve a number

of things right it's going to involve

price feeds we're going to be checking

values we're be checking a whole lot of

stuff okay so this is actually going to

be a little bit more of an in-depth

function here so let's create this mint

DSC function and we'll have this get

passed in a un 256 amount DSC to Mint

people can pick how much DSA they want

to Mint so let's say for example someone

deposits $200 worth of eth maybe they

only want to Mint $20 worth of DSC right

so they can pick how much they want to

Mint here so amount to Mint here and

let's add some checks here we should

have the mint more than zero Mount DSC

to Mint this what else we probably want

this to be non-reentrant even though we

probably don't need this to be non

reentrant because it's our C token but

let's put it in here anyways it's

probably all we need for now we probably

want to do

some looks like get up co-pilot even

gave me some some follows CI yes oh

that's wrong amount DEC to Mint amount D

to Mint the amount of

decentralized stable coin to Mint at

notice they must have more collateral

value than the minimum threshold we're

going to figure out what that means in a

second so mint DSC we'll need to keep

track of how much everybody has minted

right so whenever they're minting DSC

they're in a way they're minting debt

right so we're going to need to keep

track of that where can we do that well

we can do that as a state variable so

we'll do mapping of an address user

mapped to their U 256 which is going to

be an address user map to the u u

256 Mount DSC minted it's going to be

private

sore DSC minted this now I can go back

down here this new mapping SDC minted

message. sender plus equals amount DSC

to Mint so we're going to keep track of

all that they minted again this is going

to follow CI

so now we want to do a little check here

if they minted too much for example like

they minted $150 or $150 worth of DSC

but they only have $100 worth of eth

that's going to be way too much we

should 100% revert if that happened so

I'm actually going to make a function

going to make an internal function

called revert if Health factor is broken

with the message. sender being sent so

we're going to create this new internal

function so up here we have external

functions we're going scroll down here

we're going to make

this private and internal

functions this this and we're only going

to be able to call this if we're only

going to be able to call this internally

right so we're going to create this

function function revert if Health

factor is broken address User it's going

to be an internal View

function and we're going to basically

one check Health factor which is

basically do they have enough collateral

right and then revert if they don't have

a good health Factor so this health

factor is actually a term that I

borrowed from the a documentation reach

wallet these risk parameters enable the

calculation of Health factor and you can

see a little bit of an image here that

shows it so additionally we're going to

need to make a function that checks the

health Factor actually these are going

to be private and internal view

functions so first we need to make a

function that can get the health Factor

so we're going to make another function

here called function underscore Health

Factor we're going to take an address

user and you see we have this leading

underscore to tell us as developers that

this is an internal function so let's

actually give this in underscore as well

function

oops Factor this will be a private view

going to return a u into 256 so what

this health Factor thing is going to do

give it a little bit of Nat speec yeah

we can say this is going to returns how

close to liquidation a user is say if a

user goes below one then they can get

liquidated so we're going to figure out

what the ratio of collateral to DSC

minted that users can have with this

health Factor function we're going to be

building a lot of stuff here so in order

to figure this out what do we need well

we're going to need to get both their

total DSC minted right and we're going

to need to get their total

collateral value right not just the

total collateral we're going to need to

get the total collateral value make sure

the value is greater than the total DSC

minted

so we're going to have to make another

function we're going to need to get the

UN 256 total DSC minted and the UN 256

collateral value in USD we're going to

create a new function called get count

information from that user so we're

going to do another one boom function

uncore get account information like this

we're going take an address user this

will be a private View and we're going

to

return two things U and 256 total DSC

minted and U into

256 collateral value in USD two

functions here to get the total USD

that's easy right we just do total DSC

minted equals this array this excuse me

this mapping that we just created right

we're keeping track of this exactly so

all we got to do is this to get the

total collateral value in USD we're

going to need to do some more math so

I'm going to say collateral value in USD

equals get account

collateral value and we're going to pass

some user so this is going to be a

different function and we're going to

make this a public function so that

anybody can call this function

themselves so we're actually going to

copy this private and view internal

functions public internal View and then

we're we're going to do View and pure

public and external functions all the

way at the bottom we'll say private

instead of we'll say public and external

view functions we'll do function get

account bilateral value address of the

user this will be a public view so that

anybody can call it returns a uint 256

stay with me I know we're kind of going

down this tree stay with me here we're

about to go even further now to get the

actual value what do we need to do well

we need to Loop through each collateral

token get the amount they have

deposited and map it to price to get the

USD value so we're going to need to Loop

through all the collateral tokens uhoh

do we have a way we can do that let's

scroll to the top well we have a mapping

of price feeds but we don't have a way

to Loop through them so what we can do

is we could just have like you know

address we and then address address

wrapped BTC we could just have two

tokens like this we would have to Loop

through anything we're going to make

this system a little bit agnostic so

that you could deploy this with any

amount of stable coins any amount of

collaterals so we're going to make a new

state variable it's going to be an

address array private sore collateral

tokens and what we're going to do is

right in our Constructor when we update

our price feeds with the token and the

price feed we're also going to add the

tokens addresses of I to this array now

we have this array of collateral tokens

that we can Loop through and that way we

can calculate how much value people have

based off of all of the tokens so get

account collateral value we're going to

say four U and 256 I equals z I is less

than S collateral tokens. length i++

address token equals s collateral tokens

of I and we'll get the amount so this is

the token that we're working with we'll

get the amount by un 256 amount that is

deposited by this user by sore

collateral

deposited user token like this then

total

collateral value in USD plus equals

uh-oh now that we have the amount we're

going to need to get the USD value of

this and this is probably a function

that we're going to want to have public

so that other people can use this as

well so create a function get USD value

where somebody passes in an address

token U and 256 amount this will be a

public view returns U 56 and this is

where we're going to do some price feed

stuff some stuff that's very familiar so

we're going to need to get the price

feed for the token and then times the

amount by the price so we're going have

to work with aggregator V3 interface

again that chain link data feeds so

import and I know we've worked with this

before

aggregator V3

interface

from it looks like get up co-pilots got

my back at chain link contracts blah

blah blah this means we're going to have

to install that remember we can install

the smaller one with Forge install Smart

contract kit SL chainlink brownie

contracts at

0.6.1 D- no

dashit this chain Le brownie

contracts awesome then we're going to

have to go to our founder.

add some remappings in here so we're

going to put a little comma we're going

to say at chain link SL contracts equals

lib slash chain link brownie contracts

SL contracts like that so now we have

the aggregator V3 interface scroll down

to the bottom get USD value I know we've

done this before I know this is familiar

to a lot of you but we're going to say

aggregator V3 interface price Fe

equals aggregator V3 interface of sore

price feeds of the token so we're going

to get the price feed of the token we're

looking to get the value of now we have

the price feed here we're going to do

this WOW get a co-pilot spot on we're

going to get the price by calling Price

feed. latest round data and this is

where we're going to do a little bit of

math right let's say 1 eth equals

$1,000 The Returned value from CL will

be

1000 Time 1 E8 how do I know this well

if I go to docs. chain. link go to data

feeds I can scroll down to price feed

addresses and I can see if I do show

more details for

ethusd eth-usd it has eight decimal

places and I know Bitcoin USD also has

eight decimal places we could add some

code in here so that we make sure we're

getting the right decimals but I'm just

going to go with eight for now and now

we can do a little bit of math here so

we're going to need to do the price

times the amount right but is this all

we need to do turn price times amount no

because the number is going to be way

too big right let's say the price is a

th000 times 1 E8 and now we're

multiplying that by let's say the the

amount is 1,000 times 1 E18 because it's

going to be in way this number is going

to be absolutely massive right so first

we need to multiply this a th by a

number to get this number to match this

one so these need to be the same units

of precision so that's going to be we're

going to have to multiply this first by

1 E10 and because I don't like mic

numbers we're going to scroll to the top

create a new state variable right on

here we're going to do a u 256 private

constant additional feed

Precision equals 1 E10 like this and now

it's not a magic number so instead of

doing this now we're going to say okay

price and we're going to wrap it as a u

into 256 so that everything's down 256

we say the price first needs to be

multiplied by the additional feed

Precision so that now both of these are

U and 256s and they both have 1

E18 but then we're going to have to

divide all of these by 1 E18 as well so

this number doesn't look super wonky so

we're going to have to wrap this whole

thing by 1 E18 and as I hate floating

magic numbers like this so we're going

to scroll back to the top copy paste

this this is now just going to be called

Precision 1 E18 grab Precision divide by

Precision so u56 price times additional

feed Precision Time amount divided by

precision and we should be good to go

here this is where my brain immediately

goes okay definitely need to write some

tests for this so once we finished going

through this we're definitely going to

read we're definitely going to write

some tests at least for get USD value

here so let's go back up through our

massive tree of functions that we just

created that are not complete so let's

go back to get account collateral value

and this is going to be the total us the

total collateral value in USD it's going

to be get the USD value of the current

token we're on

times the amount that we're working with

toal Cal value in USD actually let's put

that there boom and that's it right so

we just Loop through all the tokens in

the token array and we just add up the

value and USD of each one of these

tokens and I know we don't need a return

here but I'm going to add a return here

anyways return this so cool so now we

have a way to get the collateral value

in

USD we needed that way up here oops

let's do collateral value in

USD get clonal value oops let's do this

and awesome so now our get account

information is going to return the total

USD minted the total DSC minted and then

the total value of all the collateral

here okay

great and we can scroll up again we have

this revert if hell factor is broken

which is still busted because this

function doesn't do anything but now we

can actually have it do something

because we have this health Factor here

we're going to update our health Factor

function because now we have the two of

these what we can do is we can just get

the ratio of these two so we could say

flatal value in USD divid by total USD

minted this is what we're going to

return for a health Factor right well

not quite so let's say we minted we have

100 collateral divided 100 DSC right

this is one: one if we go down a we go

down a penny we're going to be under

collateralized right and we don't want

to go under collateralized we always

want to be over

collateralized because if this ever goes

below 100 our system is is bunked up

right so we want to set the threshold to

be like hey if you go under

150 collateral you can get liquidated

right if we go under 100 it's already

too late so we want to say hey we want

you to go at least 150 so we're going to

create a liquidation threshold and we're

going to do this at the top so we're

going to say unit 256 private constant

liquidation threshold equals 50 and this

means you need to be 150 or no this

means you need to be 200% over

collateralized I think might be 150 but

we'll find out in the test so now if we

go back down to where we were to get our

health Factor we're not just going to

divide these two and even this doesn't

really work because if we have 150 over

100 150 divid 100 is equal to 1.5

decimals don't work in solidity so it

would just be one I guess that would

work but we want we want to know exactly

what the health factor is right with

Precision so first off let's instead of

just doing this let's say U into

256 collateral adjusted or threshold

equals the collateral value in USD times

liquidation threshold and then we should

divide by 100 right because the

liquidation threshold has is multiplying

it's making our number much bigger so we

should divide by 100 as I don't like

floating numbers so we'll do U into 256

private constant

liquidation Precision equals 100 so

we'll go back back down divided by the

liquidation Precision so now we have

this collateral amount adjusted for this

this threshold right so now you can kind

of think of it as instead of say we have

$150 of eth divided by $100 of DSC right

this would be 1.5 but now they need to

multiply by 50 as well but now this

collateral value is multiplied by

essentially 1 over5 right let's let's do

the math here right if we had say $1,000

of eth we just times that by 50 which

gets us to ,000 but then we divided by

that by about 100 which equals 500 so if

we had $1,000 of eth * 50 was this

divided 100 is 500 same thing with this

this example down here if we had $150

worth of each eth we say 150 * 50 equal

75 / 100 equal 75 and then if we do 75

ID 100 that is going to be definitely

less than one right so we we're

basically saying with this 50 threshold

50 over 100 is essentially 1 over two

we're saying you need to have double the

collateral in here so yeah so now that

I'm talking it out loud this 50%

liquidation threshold means we need to

be 200% over collateralized right we

need to have double the collateral that

we have the mint

DSC anyways so whole bunch of math

hopefully this makes sense if not

definitely work with your AI to make

sure this makes sense or ask questions

in the discussion right I know some of

this math can get a little bit tricky

here so collateral adjusted for

threshold and now we can return the

collateral adjusted oops this collateral

adjusted for threshold times Precision

divided by that total DSC minted now

this will give us our true Health factor

and if this is less than one you can get

liquidated now this is one example right

let's look at another example let's say

I guess this is two examples so let's

say they have $1,000 worth of eth and

100 DSC right so let's do the math here

1,00 * 50 equal 50 1 2 3 ID 100 is equal

to 500 500 divid 100 which is definitely

greater than one right 500 divid 100 is

5 so this person with $1,000 of e

deposited and 100 DSC minted would have

a health factor of 500 nice so now that

we have a health Factor we can actually

finally do this revert if Health factor

is broken function where we say we can

even put this above this as kind of like

a pseudo natspec we could say U into 256

Health Factor

equals underscore Health factor of the

user and we say if the user excuse me

actually let's do user Health factor and

if the user Health factor is less than

the some Min Health factor which is

going to be one Health Factor so let's

go ahead and create this let's go to the

top because we hate floating numbers you

into 256 private constant Min Health

Factor equals 1 if the user Health

factor is like than the Min Health

Factor then we're going to go ahead and

revert I don't love this we're going to

do DSC

engine underscore underscore breaks

Health Factor we're going to pass in

this health factor that we break with

boom new air scroll the top Air engine

breaks Health Factor un 256 Health

Factor looks like we still have some red

here what did I forget okay revert of

Health factor is broken underscore like

this boom now it looks like nothing's

red let's just make sure Forge

build successful

nice okay where were we mint DSC okay

mint DSC so we added some more DSC

minted and if adding this DSC breaks the

health Factor because breaks the health

Factor we should revert we should not

let anybody mint DSC if they're going to

cause themselves to get liquidated I

mean we could go ahead and let them do

it but like let's not because that's not

a very good user experience now what we

want to do is we want to actually mint

the DSC so this is where the DSC has

this mint function that's only owner and

the owner of this is going to be the DSC

engine now we could say and if we look

at this mint function it returns a

Boolean so we'll say bull minted

equals iore DSC mint and what does it

take for parameters address 2 and amount

so address two is going to be message.

sender and amount is going to be amount

DSC to Mint and then we'll say if not

minted we'll just say revert DSC engine

uncore uncore mint failed which is a new

error scroll up to the top error DC mint

failed yeah

Co so now we have a mint function and we

have a deposit function so we can

deposit collateral we can mint DSC but

additionally we can get account

information we can calculate someone's

Health Factor we can calculate the USD

value of these different tokens so at

this point I'm like o I have no idea if

what I'm doing makes any sort of sense I

want to make make sure I write some

tests here so this is where we could go

ahead and create a new folder unit tests

and if you wanted to you could skip

writing the scripts and just kind of

deploy in your unit tests and then do

some integration tests but I'm just

going to have my unit tests also be my

integration test for this one so let's

go ahead let's write a script deploy

DSC s.o you already know the drill for

this

spdx like since I even zoom in a little

bit identifier MIT contract deploy DSC

is script import script from Forge

STD script. Soul like that pragma

solidity

0.818 it's good in here we're going to

have our function run external we've

done this a 100 times exter

n and this is going to returns a couple

of things it's going to both return the

DS

decentralized stable coin and the DSC

engine and it's going to return

something else but I'm not going to put

it in quite yet so to do that we're

going to have to

import centralized

stablecoin from

slsrc centralized stable coin. we're

going to close and reopen my vs code

it's being really weird right now

there we go all fixed so the two of

these what are we going to do well we're

going to do vm. start broadcast this.

stop

broadcast this oh and we need the DSC

engine import DSC engine from srcds

engine. Soul and in here we're going to

deploy both of these so we'll say

centralized stable coin DSC equals

new decentralized stable coin does our

decentralized stable coin have any

parameters it does not we're also going

to deploy our

dsce our DSC engine engine equals new BC

engine this takes a whole bunch of stuff

right this is going to take go to the

Constructor token addresses price feed

addresses if we toggle oops tle the word

wrap addresses price feed addresses and

the DSC address so we have the DSC

address boom it's going to be this one

where do we get the price feed addresses

and you guessed it we're going to make a

helper config so what does this DSC

engine need Constructor an array of

token addresses an array of price feeds

and then the DSC address so where are we

going to get those addresses from you

guessed it a helper config so new file

helper configs do Soul

spdx license identifier MIT pragma

solidity

0.818 contract helper config is script

import

script from Forge

script. soul for now let's do this on

the sepolia Chain so we'll do

struct Network config do we need in here

we're going to need an well we're going

to need we and wrapped Bitcoin those

price feed addresses and those DSC

addresses address we USD price

feed address wrapped Bitcoin USD price

feed again we is the erc20 version of

ethereum I've got a example we token

contract on zolia and if you look at it

right here go write contract it's got

this function deposit where you deposit

eth and it'll return to you an erc20

version of eth to your metams called we

then whenever you're done with it you

just withdraw your eth and burn your we

WRA Bitcoin is something similar but

with Bitcoin the difference is since

Bitcoin doesn't originate on the eth

blockchain there is some risk in

bridging it over but I'm not going to go

into that that's something for you to

look up so we're also going to need the

address of the we token itself we're

going to need the address of the wrapped

Bitcoin itself and we're going to need a

un 256 deployer deployer key kind of

like what we did in one of our previous

lessons we're going to have Network

config public Active network config and

then we're going to have

Constructor like here we're going to

have a function get sepolia e

config public view returns Network

config memory this and then we're going

to return Network config we're going to

have we USD price feed B let's go to

docs. chain. link let's go to theia

zolia where's

ebtc eth excuse me e USD right here copy

that paste

we're going to need W Bitcoin USD price

feed on seoa bitcoin USD right here grab

that need the we contract address which

I have here this is one that I deployed

we here we're going to need wrapped

Bitcoin and if you're looking for all of

these and you want to just copy them out

of the GitHub repo associated with this

you can go to

SRC you can go to script upper config

and they're all in here if you if you

want just copy paste by the way but also

wrapped Bitcoin which I guess is this

address thought I had a different one

well whatever we're going to use this

one and if it doesn't work that's fine

we're going to use this one then of

course player key bm. EMV unit private

key like this okay and then we're going

to do function get or create envil eth

config public

turns Network config

memory and we're going to do a little

bit of mock deployments here but we're

going to say if Active network config do

wusd price feed does not equal to the

zero address then we've already set it

turn Active network e config we're going

to do some broadcasting so we're going

to need a couple of couple of mocks in

here we're need some mock price feeds

and some mock ec20 tokens so we're going

to need a mock B3 aggregator which we're

going to go to test folder mocks and I'm

going to copy paste a mock from this

repo if you want to copy paste as well

go for it test

mock mock V3

aggregator

this new file mock V3

agregator doou cool import that import

mock B3

agregator fromt dot slash test

slmm V3 aggregator Doo so we have that

we're also going to need some moach Er

c20s we can get those actually directly

from open Zeppelin so if we do import

irc2 mock

from atop Zeppelin contract slmx

erc20

mocko and if we command click into this

or you open this up you can see there's

a whole bunch of stuff in here like we

can mint as much as we want burn as much

as we want do transfers and stuff we can

do pretty much whatever we want and

that's why it's a mock token good for

testing with so down here vm. start

broadcast we're going to create a mock

B3 aggregator ethusd price feed equals

new Mach V3 aggregator and what does

this take for the Constructor takes

decimals and an and an initial answer so

we're going to scroll up here we're

going to say UN 2 or excuse me U 8

public constant

decimals decimals equals 8 and we'll say

U or not U me int 250 D6 public constant

eth USD price equals

2000 E8 and then we're going to do the

same thing but instead of eth it's going

to be BTC and we'll make this 1,000 to

E8 eth USD scroll down all right new

mock what does it take control click U 8

decimals initial answer control minus to

go back

decimals and then the initial answer

those okay oh and let's do vm. stop

broadcast now we're going to do erc20

mock we mock equals new erc20 mock what

does this one take name symbol initial

account initial balance okay say we we

message. sender

1008 we probably want to do more than we

probably don't want to have these

floating numbers in here but it's just a

mock it's not a big deal I guess now

we're going to copy paste all of this

for

BTC

BTC we're going to say

BTC it's going to be the wrapped

BTC wrapped

BTC wrapped BTC like that stop the

broadcast and then return Network config

we USD price feed is going to be address

oh thanks get up

co-pilot thanks get up copilot thanksg

up co-pilot thanks get up

co-pilot and this is actually going to

be the default Anvil key which if you

want you can just go back to here again

and copy paste it out of here or you

know what we just run Anvil scroll up

boom private key right here cancel that

say U 256 public excuse me int 26 public

default Anvil key equals B that in and

we'll say we just use the default Anvil

key if you're working with Anvil okay

nice so now we have get or create Anvil

get zolia let's update our Constructor

so we'll say if block. chain ID equals

equals 111

55111 then active Active network config

equals get Suppa eth config else to

Active network config equals get or

create eth Anvil config nice so we've

got a little bit of a helper config here

a little semicolon down here this looks

pretty good what's wrong here sorry this

is a

ent6 okay cool so now that we have a

helper config we can go finally back to

our deploy DSC let's import that in here

import helper config from helper config

right at the top we'll say helper config

config equals new upper config and out

of this config we're going to get all

this we Bitcoin we repid coin deploy key

Etc so I'm going to say address with USD

price feed oh I can even just hit Tab

and looks like it has most of it yep W

USD rep Bitcoin we rep Bitcoin deploy

key equals config do Active network

config cool looks good to me I'm going

to toggle word wrap so that it wraps

around okay cool we have all of those

now our DSC engine takes an array of

token addresses an array of price feeds

so we can say right at the top let's

make those arrays we'll say address

array public token

addresses address array public price

feed addresses and we'll say token

addresses equals we and rep

BTC price feed addresses equals we USD

price feed address W Bitcoin USD price

feed okay cool I think that's everything

right yeah so now we can go back to this

line now DC engine engine new DC engine

and it takes the token

addresses price feed addresses and DSC

okay cool and then finally something we

haven't really talked about too much but

this decentralized stable coin like I

said it's ownable but it needs to be

owned by the engine so this ownable

actually has a transfer ownership

function and we're going to call that to

transfer ownership to the engine so

we'll go back to our deploy here oh

sorry this isn't DSC me address DSC so

then we're going to call

dc. transfer ownership to the address

DSC engine now only the engine oops

engine excuse me only the engine can do

anything with it and then we're going to

return all these return DSC and engine

nice oh and the deployer is going to go

here okay cool so the reason we did all

this was because I wanted to write my

unit tests using actual deploy scripts

because I prefer to do that but like I

said it might be a good idea for you to

write unit tests before you write your

deploy scripts and then integration test

with your deploy scripts but in any case

let's go ahead and finally create a test

in here DSC engine test.

T.O remember the whole reason we're

doing all this I know we've been coding

a lot is in the DSC engine we added a

ton of functions in here some of them

like get USD value which we definitely

want to check get collateral account

value we want to make sure minting Works

our Constructor Works depositing Works

Etc so we're just kind of testing as we

go along which like I said when I'm

actually coding this I did write tests

and I did write deploy scripts because I

did want to test as I was going right I

didn't want to have to go back and

refactor and rewrite my code if I made

some glaring mistake right it's really

good to test while you're building as

well and to be honest I I feel like it

makes me go faster because I have more

confidence that what I did was correct

while I'm coding so

spdx

license identifier MIT pragma solidity

0.

8.18 little car here contract DSC engine

test is test import test from Forge STD

test that's all like this all right cool

function

setup public or external we're going to

need to deploy to deploy our contract so

we're going to import deoy DSC from do

script SL deploy dc. s.o deploy DC

deployer we're going to say deployer

equals new deploy DSC like that again

I'm using a lot of tabs here and we're

going to say we're going to need the

import de centralized stablecoin

from SRC decentralized stablecoin doou

we're also going to need to import the

engine the scce from again this is where

get up co-pilot could really make your

life a lot easier just being able to hit

tab here or just whatever AI that you're

working with now we're going to say DSC

let's actually make these we'll say

decentralized table coin

DSC and DSC

engine we'll call

dsce that's confusing you call this like

engine or something I'm going to call M

dsce so now our deploy returns DSC and

the engine so we're going to say return

DSC

dsce equals deployer run okay that looks

pretty good there's a bunch of stuff

more for us to do but at least we have

our tests set up here so one of the

first tests that we want to do is this

price feed test right we want to make

sure this get USD value this math that

we're doing here because we're doing

some weird math stuff we want to make

sure this is actually working correctly

so I'm going to do I'm going to set up a

little price feeds Test Section price

tests like this we're going to say

function do test get USD

value and here we're going to test our

get USD value function so it gets past a

token address and an amount so we're

going to need to get those tokens that

we use to deploy this we can get that

pretty easily from our helper config so

what we can do actually back in our

deploy we can also have this return the

config

and just at the bottom we'll also have a

return

config I'm a config and config will be

the helper config helper config config

import that import helper config from

dot dot

script fig.

s.o cool and now we can get the

we address and we can also get the e USD

so we'll put those up at the top two

we'll say address ethusd price feed and

we'll say address we get this from the

he helper config so those are the first

two so it's eth USD price feed bitcoin

price feed goes here so comma we comma

this is the Bitcoin token comma this is

deployer key equals config

do Active network config

cool we have the price feed and we have

we so now we can finally go down here we

set this function up so we'll say un 256

eth amount equals let's say there's 15

eth right 15 eth if we have 15 eth times

it by

$2,000 per eth equals what

30,000 30,000 e 18 right real simple

simple math so let's do that you 6

expected USD equals 3 301 2 3

$30,000 and we'll say U into 256 actual

USD equals dsce doget USD value we and

eth amount and the reason this should

work is because in our engine we pass

the token and the amount and internally

it uses the price feed associated with

that token calls the price to get the

amount and now we should be able to just

do assert equals expected

USD and actual USD all right I know

there's a lot of setup just to write

this one test but like I said I like

making sure my deploy scripts are part

of my test Suite right from beginning

but it might be a good idea to just do

them as integration test so Forge test-

m test get USD

value and it works now I will point out

the first couple of times that I ran

this test I actually failed miserably I

got a number of things wrong and that's

okay because you will and that's why you

write tests so I also while I'm here

let's also write at least one deposit

collateral test so let me copy this

paste it here because we're going to

write a lot of deposit collateral D

deposit

collateral test make it look a little

bit pretty at least

that we can do some more simple tests

like function test revert reverts if

collateral zero

public uh we'll prank a user so up at

the top we'll do an address public user

equals make ADR

user like this user

Capital

user let say vm. start prank or user now

we'll at least approve the token can go

to the protocol so we'll do erc20 mock W

do we have that imported nope we're

going to have to import that import

erc20 mock from atop Zeppelin SLC

contracts slash what is it MOX slash or

contracts MOX erc20 mock okay ec20 mack.

Soul ec20 mock we do

approve uh address

dce some amount let's do at the top

let's make another U 256 public constant

amount

collateral equals let say 10 ether worth

of

collateral down here we'll approve that

10 collateral and then we'll do vm.

expect

revert with DSC engine dot we're going

to need to use that needs more than zero

in here needs more than

zero do selector and now you guys know

what the selector bit means dsce do

deposit colat

collateral say we zero this and then vm.

stop Rank and actually this might fail

for a different reason but let's go

ahead and try it Forge test DM

oops okay cool and this actually did

pass now if we want to make this a

little bit better of a test we should

also mint our user some weth and we

probably should do that right in the

setup so we don't have to do that for

every single test what I'm going to do

is I'm going to do erc20 mock

we mint user we're going to do a 2 into

256 a constant starting here see

20

balance

balance

equals and let's say this is 10 ether as

well 10 ether starting year20 balance

boom all right cool so now Forge test

all of our tests are passing cool and

like I said I'll do this kind of as a

sanity check to make sure that my

architecture is even making sense right

so we what we probably want to do next

then is have a test for collateral is

being deposited in these data structures

but for now I'm content with these tests

so I'm just going to go back to writing

my contracts like I said there's no one

single process and I don't think I've

ever written a smart contract completely

in one go I'm pretty much always writing

tests as I'm writing the code so it is a

really good idea to to do this yes you

do not have to write the deploy script

as you're writing your code but

something that I like to do and then you

know what while we're writing these

tests let's also do D- Fork URL sepolia

RPC URL let's also do this because this

probably will fail actually because we

can't just mint we at a thin air and we

do indeed fail test get USD value oh

interesting that's the one that fails

test get USD value ah this one fails

because we're hardcoding the expected

USD right here here and of course the

price on sapoia is the actual price as

opposed to kind of this fake price that

we're making up so we should probably

update this test to make it more

agnostic right we probably should update

this test so that instead of just

hardcoding 3,000 in here update this

test to use the price of the actual

price feed for now I'm going to leave it

as is and then I can fix it later for

running those Fork

tests so where are we now okay so we

have a way to deposit collateral we have

a way to Mint we don't really have too

many tests here we're just assuming that

this kind of works for now which is okay

but this is good right we're getting

somewhere so we can mint our debt or our

DSC we can actually now we can get a

whole lot of information as well which

is awesome let's now combine these two

into kind of this main function that

we're thinking a lot of people are going

to call this deposit collateral in mint

USD right the purpose of this protocol

is to Mint this stable coin right

deposit collateral and mint DSC which is

just going to be the combination of

deposit collateral and mint DSC so in

here what this this is going to take

it's going to take similar stuff to

deposit collateral and address token

collateral address a u into 256 amount

collateral and then also a un 256 amount

DSC to Mint

right that and here we're just going to

call so deposit collateral is external

right now we'll make this a public

function so we'll change this to deposit

collateral or we give it the token

collateral address and the amount

collateral and then we'll call Mint DSC

amount DSC to Mint boom so it's all this

function does is just combines the two

of them oh and mint

DSC mint DSC is not defined because it's

external we'll make this public as well

so that our contract can also call it

toggle word rep put that back on okay

and cool so this is going to be one of

our main functions we're thinking so

let's add some Nat spec to it we'll say

at param this is where get co-pilot is

really helpful token collateral address

the address of the token to deposit as

collateral at Pam amount collateral yep

at Pam that looks good too and then

we'll at noce

this function will deposit your

collateral and and mint DSC in one

trans action right because otherwise

we're going to have to have people call

deposit collateral and then mint but

some people they're probably just going

to want to do both at the same time

because that's kind of the purpose of

this

protocol okay great so we have a way to

for people to get money in how do they

get their money out so we're going to

need to write this redeem collateral

right so in order for them to redeem

collateral let's talk about this in

order to redeem collateral they need

what one their health

Factor must be over one after collateral

pulled so we're going to want to put

some checks in here to make sure that

they have enough money in here and

that's kind of the main thing right

that's all we really need to worry about

so let's go ahead start right this so

first we should let them choose which

collateral they want so address token

collateral address and then obviously

the amount amount

collateral and we're going to want to

add this more than zero modifier in here

for the amount collateral we don't want

them to be sending accidental zero

transactions and because we're going to

be moving tokens around we'll just do

non- reentrance better safe than sorry

we can figure out later in kind of like

a gas off it if this is even needed now

I'm going to write this function as if

somebody redeeming collateral is the

only time they actually redeem

collateral however we're going to

refactor this in the future to make our

code much more modular there's this

concept in computer science called dry

don't repeat yourself if you find

yourself coding the same thing that that

should send off a light bulb in your

head going oh maybe what I'm doing isn't

the best practice so we're going to code

this one way and then I'm telling you

right right now we're going to go back

and we're going to refactor this in the

future but I want to code it this one

way first just to show you the process

that you'll probably go through and how

you'll probably refactor it when you

come across this yourself so we're code

this one way now let's do it we're going

to need to pull the collateral out and

we're going to update our internal

accounting so we have this

sore collateral deposited of message.

sender of the token collateral address

right this is the our internal

accounting how much collateral they've

added we're going to do minus equals

amount collateral so this is assuming

we're going to pull it out if they try

to pull out more than what they have

we're relying on the solidity compiler a

little bit to throw an error right if in

their balance they have 100 and they

subtract try to pull out 1,000 right

it'll revert because as of newer

versions of solidity they don't let you

do this unsafe math stuff which is

awesome it saved us a lot of hassle so

and then since we're updating State

we're we're going to emit an event let's

call it

collateral

redeemed we'll say it's message. sender

so from m. sender the amount collateral

uh the token

collateral address like this so we're

going to go to the top we're also going

to refactor this event but you'll

understand why later event collateral

redeemed address indexed user address

indexed token uint 256 indexed amount

like this okay control minus go right

back down to where we were okay amount

collateral oh what's wrong with this oh

these are

backwards okay cool now all we have to

do is return the money well how do we do

this so we want to follow CI right

checks effects interactions checks

effects interactions but we also want to

make sure the health factor is good

after collateral collateral is pulled

and this is where sometimes you'll see

CI be violated when I need to check

something after a token transfer has

happened sometimes you'll see this CI be

violated a little bit and what you could

do is you could do like calculate health

Factor after and then like simulate it

but a lot of people choose to not do

this because this is really gas

inefficient so what a lot of people do

is they just go ahead with the doing the

token transfer first and then checking

this and reverting if this happens and

that's usually fine though because we're

going to revert the transaction if it's

bad right so what we'll do is we'll do

this token transfer and then we'll make

sure the health factor is okay so you

know how to move tokens around so we'll

say bull success

equals ier 20 token collateral

collateral address dot we can just do

transfer instead of transfer from since

transfer is when you transfer from

yourself transfer from is when you

transfer from somebody else so transfer

and we're going to be sending it to

message. sender and we're going to send

amount collateral and then if not

success if if not success we're just

going to go ahead and revert DSC engine

we'll just do transfer failed like this

and then we want to make sure that the

health Factor isn't broken and we have

written a function that does that

already called revert if Health factor

is broken so we can just grab this go

back up to our redeem and just do revert

of Health factors broken for the

message.

sender okay cool like I said we're going

to refactor this very soon okay but it

looks like this is actually pretty good

for redeeming collateral now this

revertive health factor is broken is a

little bit Troublesome with just this

raw redeem collateral let's say I put

$100 in and then I mint let's say $20

worth of DSC put $100 worth of Ethan and

I mint $20 worth of DSC let's say I'm

done like I want to burn all my DSC and

I want to withdraw all of my eth well if

I try to redeem all my eth it'll break

right it'll break my health Factor so

what I need to do first is I need to

First burn back my DSC and then I need

to redeem eth so it's a kind of this two

transaction process here this kind of

stinks so let's turn it into a one

transaction process so we're going to

combine redeeming your collateral with

also burning your DSC which means we're

going to need to create a burn DSC

function and we're also going to

refactor this in a little bit but I'm

just going to write it as if this is the

only burn D function for now so let's

have people burn their DSC right this is

when they they say hey I'm done with

these tokens and this will reduce that

if we scroll up to the top we have this

mapping here SD cemented it'll reduce

this sdsc minted so essentially it'll

reduce their debt in the system so burn

DSC we're going to add some modifiers

here this should be more than zero

amount so we want to do a unit 256

amount so they can burn as much as they

want and then what we're going to want

to do is we're going to say sore DSC

minted of the message. sender is going

to minus equal amount so we're going to

remove that debt remove that DSC minted

then we're going to do a little bu

success equals iore

DSC transfer from

D message. sender to address this amount

and we could also send this to the Zer

address but we're going to just send it

to our address for now because the

decentralized stable coin erc20 burnable

has its own burn function and we're just

going to call the burn function directly

on the token itself but first we're

going to take it from them bring it into

our contract and then we're going to

burn it so if not success then we'll

revert

dsce transfer failed this and this

conditional is kind of hypothetically

unreachable because if the transfer

fails up here we're going to throw the

transfer from fail error but let's say

this DSC token is implemented wrong

great we kind of have this backup but so

they're going to send their DSC token

here then we're going to call IOD DSC do

burn amount now since we're burning DSC

question is do we need to check if this

breaks Health Factor well probably not

right because we're burning DSC we're

burning debt it's highly unlikely that

burning your debt removing your debt is

going to break the health Factor right

we probably don't ever need this but I'm

just going to add this in here for

now just as a backup in a gas audit we

can figure out if we actually need it I

don't think this will would ever hit and

this is where when I do go to an audit

when I do go to a security professional

I can make sure to point this line out

say hey I don't think this line will

ever hit and I'm thinking of pulling it

out what do you think right it's good to

call these out in your comments that

when you do go to a professional who

knows they can help you out figure this

out so for now we're going to put it in

here although it's highly likely we

don't even need this and we're going to

refactor this function pretty soon

anyways so we have this burn DSC fun

function we're going to make it public

because we're going to be burning DSC

and redeeming collateral at the same

time so now we have redeem collateral we

have burn DSC now we can write this

redeem collateral for DSC where we send

DSC and redeem collateral at the same

time and so in here we're going to say

address token

colateral

address U

256 amount

collateral U 56 amount DSC to burn we'll

have this be external so then we're

going to call burn DSC with the amount

of DSC to burn we're also going to call

redeem collateral so we're going to burn

the DSC first then we're going to redeem

their collateral with the

token collateral address and the amount

collateral redeem

collateral oh this is external let's

make this public let's go back and then

of course of course we should revert if

Health factor is broken but if we look

our redeemed collateral function

currently does this already so we don't

need to do that here so I'm just going

to put this comment redeem

collateral already checks Health Factor

right here then we'll add a little bit

of natspec here so at Pam boom that's

not even the right Pam collateral

address the

collateral address to red

RAM amount collateral the the amount

collateral to redeem RAM amount DC to

burn the amount of DSC to burn this

function Burns DC and redeems underlying

collateral in one

transaction okay cool are we going to

refactor these two functions soon yes

absolutely but I want you to understand

why we're going to reactor them so we're

going to leave them in as they are for

now

Okay cool so this is looking pretty good

so we have a lot of stuff in here uh we

have deposit collateral and mint DSC so

people can mint our stable coin by

depositing collateral people can just

straight up deposit collateral people

can then redeem their collateral for the

US for the DSC that they minted they can

just straight up redeem collateral they

can just straight up mint DSC so long as

they didn't break the health Factor they

can burn DSC to to go help their health

factor and I don't think this line will

ever hit we've got to do a couple of

more things here most importantly we got

to do this liquidate function so this

liquidate function is kind of the the

key thing that holds this whole system

together if we do start nearing under

collateralization we need someone to

start liquidating positions removing

those positions we need somebody to

basically call redeem and burn for you

if your health Factor becomes too poor

right because the worst thing that would

happen is let's say there's $10000 worth

of eth backing $50 worth of DSC and then

the price of eth Tanks to $20 right $20

of eth backing $50 of DC well now the

DSC isn't worth $1 right the DSC then is

going to be worth you know whatever 20

over 50 is so we can't let this happen

right we need to make sure we liquidate

people's positions we remov people's

positions in the system if the price of

the collateral tanks okay and this is

where liquidation comes in so we say if

someone is almost under

collateralized we will pay you to

liquidate them we have kind of this

gamified incentive system here where

people can get basically free money for

removing other people's positions in the

protocol so in this situation up here as

the price is going down let's say the

price goes down to $75 backing $50 of

DSC this is way lower than our 50%

threshold so what we're going to do is

we're going to let Liquidator Liquidator

take this $75 backing takes the $75

backing and pays off the $50 DSC and

Burns Burns off the 50 DSC so we're

going to have somebody able to take

their money in exchange for them making

sure our protocol stays collateralized

so that's what this liquida function is

going to do so first off they're going

to be able to choose the

collateral the user that they want to

liquidate and the UN 256 debt to cover

and they'll be able to track the users

and their positions by listening to

these events that we've been emitting

which is exciting we're going to

definitely going to want a lot of n spec

for this app Pam

collateral is going to be the collateral

to liquidate or better yet the

rc20 address collateral address to

liquidate from the user at Pam user the

user who has broken the health Factor

their health Factor should be below Min

Health Factor at Pam

debt to cover is going to be the amount

of DSC you want to burn to improve the

users Health Factor okay we're going to

add a lot of at notices here at

notice you can

partially or liquidate a user just so as

so long as you improve their health

Factor that's all we care about at

notice you will get a liquidation bonus

for taking the users funds right we want

to incentivize them to to actually do

this right if we say okay cool you'll

get the $50 back for paying off the $50

debt it's going to be hard to

incentivize people to do that but if we

say you get all $75 and all you have to

do is pay back 50 then that's going to

be a bonus that they should be able to

take to incentivize them to do this at

notice this function

working assumes the protocol protocol

will be roughly 200 100% over

collateralized in order for this to work

why well because in this scenario if

this drops down to $20 backing $50 of

DSC and if I pay back the 50 DSC and I

get $20 well then I I'm not going to do

that I'm not going to pay $50 to get

back 20 so this whole system only works

if the system is always over

collateralized the only way we can give

liquidation bonuses is if we're over

collateralized so the only way we can

incentivize people to liquidate poor

users is if we are over collateralized

so we could say at notice a known bug

would be if the protocol were

100% or less

collateralized then we wouldn't be able

to

incentivize the

Liquidators and then we would just say

like for example if the price of the

collateral plummeted before anyone could

be liquidated so hopefully this makes a

lot of sense if this doesn't make sense

you know what to do ask chat chbt ask in

the discussions Forum Google it use the

resources that you have to your advance

AG yes yes okay good so debt to cover we

probably want to do more than zero very

lame if they did just zero so we're

going to do more than zero here we're

going to be moving tokens around so

we're going to do non reenen as well

maybe we'll do some more modifiers but

that looks pretty good to me right now

so now what do we need to do well we

need to do a bunch of stuff here well we

first need to check Health factor of the

user right is this user even liquid

datable right remember we want to do

follows

CI checks effects

interactions right we always want to

follow CI so we should do some more

checks here because we should only

liquidate people who are liquidable so

first thing we should do U into 256

starting user Health Factor equals

underscore Health factor of the user

right because we have this health Factor

function which gets that Health Factor

factor and what we can say and let's put

this above now we'll say if the starting

user Health

factor is greater than or equal to the

Min Health factor which what's our Min

Health Factor again one actually it

should be 1 E18 and we're definitely

going to write some tests to make sure

this is correct so 1 E18 because we're

using our Precision here what else are

we doing Health Factor why didn't we

write test elsewhere revert if Health

factor is broken oh I guess we haven't

tested this yet well I guess we're going

to be testing it very soon make sure

that that Health Factor bid is right so

the starting user Health factor is

greater than or equal to the health

Factor then we revert right revert DSC

engine uncore underscore Health Factor

okay right Health factor is fine got a

new error let's go to the top scroll

down error Health Factor o back back

cool back down here remember I'm doing

control minus to go back might be

something else depending on your setup

so let's do some thinking so now we have

their starting Health Factor what do we

want to do we want to burn their DSC

debt right we want to reduce the amount

of DSC they have and take their

collateral we want to remove them from

the system basically right so how do we

do that let's say they have 140

$140 of eth deposited and $100 of DSC

with a setup like this their health

Factor should be below what it currently

is what we could do is we can say okay

we're going to cover so this is what bad

user this dis bad user has that means we

could cover we could say okay we're

going to cover debt to cover is going to

equal that $100 and we need to pay back

$100 so we're going to have to get a u

256 collateral or token amount from debt

covered covered cover covered so we need

to figure out okay if we're covering

$100 of debt $100 of DSC equals how much

eth so we're going to pay back $100 of

debt and how much eth is that okay how

much e eth is that so we're going to get

the token amount of De color the eth

basically equals and we're going to have

to do some pricing stuff we're have to

say it equals get token amount from USD

so we're going to add the collateral and

the debt to cover so we're going to

figure out okay how much of this token

are we going to get right we're going to

cover $100 worth of debt how much in eth

or whatever collateral token is $100

worth of debt so we're going to create a

new function get token amount from USD

this is going to be a public view

function so we're going to scroll all

the way down here public and external

view functions

function get token amount from USD and

we're going to pass an address token or

collateral unit 256 USD amount in way

this will be a public view returns

256 and we're going to have to do some

price feed stuff so we're going to need

what are we going to need to do we're

going to need to get the price of eth or

the token and then we're going to have

to say Okay so if the pricing is dollar

per eth and we have eth how do we get

the dollar well if we do some math here

let's say it's $2,000 of eth and we have

$1,000 right how much eth is that we're

going to do the 1,000 divided 2,000

which is going to equal 0.5 eth right so

we're going to do this number divided by

this number the amount the USD amount in

way divided by the price and that's how

we're going to get get this token or

collateral amount from the USD amount so

we'll say agregator V3 interface price

feed equals aggregator V3 interface of S

price feed of token oh wow it

even build in a lot of this for me

that's great yes this looks right so

we're going to get the price feed of the

token and get called latest round data

on it to get the price here and then

we're just going to do this right here

so we're going to say the amount USD in

way divided by the price or unit 56

price is this the full story no

absolutely not because we should always

multiply first so we're going to do this

times our pre cision then we can divide

by the price but is that the whole story

no because the price has eight decimal

places and we needed to have 18 so we're

going to do additional feed Precision

like this

is Alec right so if we have let's say we

have 10

E18 for Mountain way we're timesing that

by 1

E18 like this we're saying divide that

by the price let's say the price is

$2,000 $2,000

E8 times the 1 E10 the additional piece

here this looks pretty correct do we

need anything else let's see just pull

out the calculator right so 10 1 2 3 4 5

6 7 8 1 2 3 4 5 6 7 8 9 10 * 1 1 2 3 4 5

6 7 8 1 2 3 4 5 6 7 8 9 10 divided by 2

1 2 3 2000 1 2 3 4 5 6 7 8 9 10 1 2 3 4

5 6 7 8 equals this number which is

probably a half right 1 2 1 2 3 4 5 6 7

8 9 10 11 12 13 14 15 that right 1 2 2 3

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

9

89 0 point is that right oh because it's

$10 thoughh yes this is right I was like

I thought we did $1,000 but this is $10

yes okay cool that looks good to me

great and then obviously we're going to

test this soon to make sure that is

right so we have this function where we

get the token amount from the USD so

we're saying hey we're going to cover

$100 of your debt or something like that

how much eth is $100 worth of your debt

maybe it's if the price is $2,000 we

obviously we would do 100 divid by 2,000

0.05 right there right this is going to

be something like 0.05 eth or whatever

it is right cool so we have how much eth

we need to take away from their

collateral as a reward for paying back

this DSC but additionally we also want

to

and give them a 10% bonus right because

we want to incentivize them if they're

just if it's just a one for one they're

not going to want to do this so let's

say we're going to give them a 10% bonus

so we are giving the liquid dator

$110 of weth for 100 dsse whatever $110

of we is going to be we should Implement

a feature to liquid dat in the event the

protocol protocol is

insolvent we're not going to add that in

yet though but we should probably add

something like that and then and sweep

extra amounts into a treasury but we're

not going to add either one of those so

don't worry if that's confusing don't

worry about that we're not even going to

implement that anyways so we'll say you

256 bonus colateral equals this token

amount debt covered times some liquid

ation bonus that we haven't defined yet

although we're going to do 10% divided

by 100 but I hate these floating numbers

so we're going to do something better

than 100 we're going to do Liquidator

Precision which is 100 we'll do unit to

256 private

constant liquid dator bonus equals Shan

bonus it's going to be 10 be like this

means a 10% bonus and since it's going

to be 10/ div by 100 that's going to be

10% let's go back down liquidation bonus

divided by

liquidation Precision so the bonus

collateral is going to be 10% so let's

say it was 0.5 0.05 eth we're going to

multiply that by 0.1 right because we're

going to multiply first and then divide

to get

0.05 eth so as a total or that's not

quite right it's going to be 0.5

0.05 time

0.1 equals yes so that means they're

going to get

0.05 five is that right I think that's

right why why am I being bad at math I'm

one yes okay cool great so that's what

they're going to get this bonus

collateral we got to add the bonus

collateral to the actual collateral

we're going to say like you went to 256

total collateral collateral

to redeem equals token amount from

covered plus bonus collateral like that

and so and now we need to redeem this

amount of collateral for whatever's

calling the liquidate function right we

need to redeem that collateral and then

we also need to burn the DSC from this

user as well so we need to give them the

collateral and burn the DSC that they're

covering with their debt to

cover now though if if we look at our

redeem collateral redeem

collateral function which is public

right now we can see as inputs it takes

token collateral address and amount

collateral right and it is hardcoded to

message. Sender our third party user

isn't the one with the bad debt right we

need to redeem a random person's

collateral so what we can do is we can

refactor this code so that there's an

internal redeem collateral function that

can redeem collateral from anybody right

and only very permissioned functions can

call redeem collateral so what we're

going to do is actually we're going to

take all of this code and we're going to

change it and we're going to delete it

and we're going to put it into a

different function all the way down the

in private and internal functions here

we're going to make a function

underscore redeem

collateral and this is going to be an

internal function where we can actually

redeem collateral from anybody and as

input this is going to take address

token collateral address same as the

regular redeem collateral also the unit

256 amount collateral but we're going to

add address from and an address to so

this way and this is going to be private

so this way somebody can liquidate an

address from and then get the rewards to

and this is where I'm going to paste all

that code we got from above and I think

this looks good yeah we're just going to

paste that code exactly like this

instead of doing doing message. sender

this is just going to be from and emit

collateral redeemed we're going to

update our collateral

redeemed to redeemed from we'll do

address redeemed from address redeemed

to we'll do token and then we'll have

amount not be indexed so from to token

and amount so now we got to refactor

some of these collaterals so from when

we do just the regular redeem collateral

we'll update this in a minute actually

yeah we'll update that in a minute so in

this internal function it's going to be

from from to address collateral and then

we're going to transfer we're going to

transfer the tokens to whoever the two

is so this is going to be like the

Liquidator Mount collateral and do that

and now we're going to use this internal

function up in our regular redeem

collateral function that we created

right uh up here oh no up this one up

here we're going to dump all this and

just use this underscore redeem

collateral and for here we're just going

to say message. sender so from message.

sender to message. Sender token

collateral address amount collateral and

now that we have this internal function

we can use this redeem collateral bit

down in our liquidate which is down here

we can now just say redeem collateral

from from the user that's being

liquidated so from user to whoever's

calling liquidate here so it's going to

be message. sender the collateral token

that we're liquidating and then finally

the total collateral to redeem so this

is why I said we were going to do a

little bit of refactoring soon right we

generally only want to redeem collateral

from into the same person however when

we're doing a liquidate we're going to

redeem to whoever's calling the liid dat

so they're going to get that reward the

total collateral to redeem is that total

amount debt to cover plus some bonus

here and now we actually need to yeah we

need to burn the DSC now so right now if

we look up burn burn DSC we have this

public function which just does the same

thing it just does it just burns from

message. sender we're going to have to

do the same here we're going to want to

make an internal burn DSC function that

allows us to burn from anybody right so

if we scroll down to where we're doing

those private functions or scroll up so

we have this internal redeem collateral

we also are going to need an internal

burn DSC function uncore burn DSC unit

256 amount DSC to burn address on be

half of like whose DSC are we burning

for whose debt are we paying down and

then address DSC from where are we

getting the DSC from we a private and we

can go back to the burn DSC this burn

DSC function right and same thing we can

just copy all of this go back to our

internal burn DSC function paste this in

here we're going to want to update this

right instead of message. sender this is

going to be on be half of we're going to

B we're going to take away their debt

we're still going to do this but instead

of message. sender it's going to be ESC

from and it's going to be amount DSC to

burn this is still fine this just needs

to be a amount DSC to burn and we don't

need to check Health Factor yet because

this is going to be our internal

function so we might even say like in

the comments here low level internal

function or at Dev low-level internal

function do not call unless the function

calling

it is checking for health factors being

broken so now we have this burn DSC we

can go back up to our burn DSC function

we can just swap delete all of this call

burn DSC and this going to be message.

sender message. sender amount right

somebody calls burn DSC thems great

we'll just have them call this burn DC

amount to burn on behalf of themselves

from themselves oh looks like got this

backwards amount should be the first one

okay and now we have this burn DSC

function we can go down to look

liquidate and we can call burn DSC what

are the uh amount on behalf of from so

the amount is going to be this debt to

cover amount on behalf of is going to be

the user and the one who's going to be

paying this is going to be message.

sender right because it's the whoever's

the Liquidator whoever's calling

liquidate is going to be the one who's

paying down the debt to cover right

paying back that minted DSC and now

since we're doing these internal calls

that don't have checks we absolutely

need to make sure we're checking this

health factor is okay right so we're

going to do un 256 ending user Health

Factor equals underscore Health factor

of the user and if the ending Health

factor is less than or equal to the

starting Health Factor right if we

didn't improve the health Factor we

should revert DSC engine underscore

Health Factor not improved copy this go

to the top we'll do error DSC engine

Health Factor not improved go back down

so if we don't improve the health Factor

we should 100% revert and then also if

calling this liquidate function if

paying down some debt and doing all this

stuff actually hurts the liquidator's

health Factor we should also revert

right so we should also call revert if

Health factor is broken for the message.

sender right if this process ruined

their health Factor we shouldn't let

them do this okay so we're following

checks effects interactions here the

most part these two functions are making

external calls to external contracts

right and then we're doing kind of like

a check afterwards again this is a bit

of a trade-off we could calculate before

and then run this but that's kind of gas

inefficient we're just going to check

after we do all this hey just make sure

that the health factor is okay make sure

that we didn't break anyone's Health

Factor so now we have this liquidation

function which is incredibly powerful

and kind of what ties this whole thing

together right there's an incentive here

for people to call liquidate so that our

protocol is never insolvent right and I

know I've been kind of throwing around a

lot of these financial terms but our

protocol always has more collateral than

it has minted DSC the value of the

collateral should always be more than

the minted DSC always incredibly

powerful function we're obviously going

to be testing the living hell out of

this right because we want to make sure

it actually

workso okay what do we need now oh looks

like we broke some stuff oh this needs a

semicolon what else do we break there's

a little red thing down here let's go

fix it amount this should be amount DC

to burn got a couple more red things

redeem collateral user message as sender

redeem collateral uh oops we did these

backwards I'm going to copy these

put these at the front okay oh looks

like that fixed pretty much most of this

I don't see any more red stuff on the

side here so we're going to go ahead and

run Forge build make sure everything's

at least

compiling awesome maybe we'll even run

Forge test I don't think this would have

broken any tests looks like those are

working fine but all right we're doing

some fantastic work and like I

said at this point I probably would be

any test with this but we're almost done

with all of our code here so we're just

going to keep going right and this code

is starting to look pretty darn good

right we've got these amazing natspec

comments in here we've got comments all

over the place maybe these probably

should be cleaned up a little bit but

that's fine we've got a little this

little Dev thing a shout out saying hey

don't let anybody call burn DSC without

checking the health Factor right this is

really good to tell Auditors and

Security Professionals about this right

it's really good to call this out we've

now have this internal redeemed

collateral function so it can be used

for the liquidate or the redeem

collateral Health Factor it looks like

pretty much all the functions that we

originally wrote are working in here

right and the reason again that this all

works is because when we mint DSC we can

only mint as much as we have collateral

in the system we're setting this

exchange rate essentially for our

protocol hey cool you have a $100 you

have $150 worth of eth deposited great

you can mint $100 worth of DSC

so it's this exchange rate that we're

setting which is maintaining the price

let's just double check that we have

kind of most of the functions that we

want here and let's also check that

they're in the right place so we go to

the top here got a whole bunch of Errors

that's great got a whole bunch of

constants because we hate magic numbers

we have a mapping of price feeds a

mapping of collateral deposited from

user to token to the amount they have

deposited we have their debt or their

DSC minted collateral tokens the idsc

token we've got some events in here

couple modifiers some

functions we've got a way to deposit

collateral and mint DSC in one

transaction we've got a way to calculate

health Factor I'm going to tell you

right now there's actually a bug in here

ho not going to tell you what that bug

is yet though maybe you can figure it

out we've got some view functions down

below we're probably going to add more

as we write tests but this is looking

pretty darn

good now like I said there's at least

one big bug and there might even be and

there's likely more but there's at least

one big bug in here so that would be a

good time to take a break because after

this we're going to go deep into writing

tests for this protocol we're going to

write some new tests and we're going to

show you some really Advanced testing

methodologies so take that break go for

a walk and I'll see you in a few

all right so let's pull up our terminal

here

Forge

coverage oh we got some work to do all

right well no time like the present

let's get into it so we have some price

feed tests over here we probably also

want to set up some Constructor tests

right we want to make sure that stuff is

being initialized correctly so let's

copy that we'll do

constuctor structor test like that we'll

fix this so our ADHD doesn't go crazy

and we'll do function test something

what are we testing uh let's go down to

the instructor here and what should we

be testing okay well we're doing this

revert here so we should make sure we

actually are reverting correctly when

the lengths aren't the same so function

test reverts if token length doesn't

match price feeds

feeds public zoom in zoom in we're going

to be in here a while so function this

now we're going to do we're going to

create some address arrays address array

public token addresses address

array public price price feed

addresses we're going to say token

addresses. push we're going to push we

into here feed addresses

add. push

FUSD price feed and we're going to push

two in here oh cool BTC do we have I

guess we should pull BTC USD price feed

get this too so FUSD BTC USD price feed

okay oops price feed addresses price

feed addresses so we'll push the two of

those in there now we'll do

vm. expect revert DSC engine dot what's

the name of the error copy

this boom do selector selector like that

doing some toggle word wrap now X spect

reverts now we call a new DSC Engine

with the token addresses and the price

feed addresses oh what else goes in the

DSC oh we also need the address DSC

right address DSC so this should revert

let's see for test

DM nice okay that's passing all right

cool price feed tests we're testing

getting the USD

value I think we had another one down

here right we had something like get

token amount from USD we sure did this

is a public view so let's test this one

as well do function test and I usually

just like to paste the function names

especially when they're like this

public so we're going to do basically

the opposite of this this got the USD

value of some eth amount we're going to

do un 256

USD amount right equals we'll say 100 e

100 ether and then

256

expected we do a little bit of math here

if we have if it's

$2,000 per eth and we have $100 we're

going to do 100 divid 2,000 so 100 divid

2,000 0.05 so we can say expect a we is

0.05 ether now we'll do U into 256

actual we equals dsce do this function

with the lowercase pass in we and then

the USD amount assert equal

expected X expected weth and the actual

we the two of them should be the same

Let's test it out Forge test

DM nice that passed all right let's keep

going POS a collateral test yes test

revert of collateral zero that's good

what else let's go to this deposit

collateral deposit

collateral function okay we should also

revert here we're basically just going

to go through this whole function and

kind of test each line we just tested

this one let's tested this one so this

will be something like function test

reverts with

unapproved collateral

public we'll make an erc2 mock some Rand

token right we'll just make some silly

token new erc2 mock ran will be the name

ran will be the token do we have a user

in here think we do have a user right

okay yeah we do have a user let's give

this money to a user and then we'll give

him some starting amount I think we have

starting erc20 balance or amount

collateral yeah we'll do amount

collateral give them the amount

collateral we'll do

vm. start prank this user who has this

token and they're going to try to

deposit this collateral and we're going

to expect it to revert so vm. expect

revert and this error here is allowed

token right now doesn't take any

parameters so that's easy enough for us

let's just copy this we'll do DSC

engine. this. selector and then we'll do

we'll call the deposit collateral so dc.

deposit collateral address of that Rand

token right Rand token or random token

we'll do amount collateral as well so

it'll just be that whole amount and then

we can do vm. stop prank and that should

work Forge test-

M see if that's correct

yep looking good all right let's keep

going what else what's next deposit

collateral not that one okay did this

did this non- reentrant we could be go

ahead and test re-entrant I'm going to

skip doing that for now but we probably

do want to do some re-entrance the test

at some point but yeah I'm going to skip

them for now and all right cool so then

we can start testing some of this so if

they deposit collateral we should see

that they actually do this we should see

that they emit an event let's go ahead

and do that so let's do function test

canit

collateral leral and get account info

because once they deposit we have this

get account

info oh it's private right now so let's

actually go to the bottom let's create a

public version of that so we'll do

function get account in for

this will be uh external external view

returns return this can't address user

returns these two I'm going to copy this

go back

down uh external view

returns these two things and we're going

to say total DSC minted comma B value in

usdc equals this internal function and

that should be good right oh we're going

to do instead of message. sender we'll

do address user this paste the user in

here so now we can get the total DS

minted and their collateral value in USD

from an external view function we should

be able to get that information so let's

have them actually deposit collateral in

here and since we're going to be doing a

lot of deposited collaterals we know we

can actually make a modifier I'll

deposited collateral

this bm. start prank

userc 20 mock weth in order to deposit

weth we need to approve address

esce comma amount

collateral we're going to do dsce

deposit collateral we amount

collateral. stop prank. stop prank

underscore like this

modifier right and we'll have this can

deposit collateral and get account info

we'll have them deposit collateral and

we'll now get that account information

so we'll say U into

256 total DSC minted

256

later lateral value in USD equals dsce

do get account

information the user oh from the user

and now what we're going to say we're

going to make sure these two numbers are

correct the total DSC minted and the

collateral value in USD they should have

minted no DSC so un 256 expected

expected total DC minted yep equals zero

un 256

expected colateral value in USD equals

this is going to be that dsce doget

token amount from USD with collateral

value in USD so expected collateral

value should just be this function then

we can say assert

equal total DSC minted should be this

expected total DC minted and then we can

do assert equal feral value in USD it's

going to be this expected collateral

value in USD all right clear Forge test

DM all right we have a fail you know

what to do we're going to run it again

Dash VV VV see what we messed up

here says the assertion failed left is

this number and right is a much smaller

number this is why it's not cool to do

two types of asserts but I know it's the

second one so we're saying the clal

value in USD is this but the right side

side is expected collateral value is

going to be this so let's see what's

wrong here 1 2 3 4 5 6 7 8 9 10 1 2 3 4

5 6 7 8 so it's

saying collateral value in USD is 20

grand does that make sense well it's 10

ether time

$2,000 equals 20 grand right so that is

so

the collateral value in USD is right it

looks like my right is wrong

collateral expected collateral value in

USD dc. from token amount we oh what the

heck why am I doing that 1 2 3 4 5 6 7 8

9 10 1 2 3 4 5 6 7 8 so it's saying that

$20,000 is equal to 10 e so I don't know

why I'm calling this oh this is actually

expected expected deposit amount and we

shouldn't be comparing these two to this

should be compared to the

amount collateral right so 10 is how

much collateral we're putting in here

and then collateral value in USD yeah

that's correct so we're getting we're

using this collateral value in USD to

get the expected deposit amount that

looks more correct okay cool Forge test-

M and this is one of the kind of weird

Parts about writing test right okay cool

we fixed it sometimes your test is wrong

like what we just showed here I wrote my

test wrong but sometimes your code is

wrong and that's what these tests really

should be testing hey when is the code

actually wrong making some progress

Forge

coverage not a whole lot of great

coverage here let's keep going so

instead of me just kind of walking you

through the rest of these tests you know

how to write these tests in this file

I'm not really going to show you any

more unique tests right but like I said

there is at least one glaring issue in

our DSC engine. Soul there's a big issue

in here right we definitely need some

more getter functions as well so write

getter functions as you test but there's

at least one giant issue so what I'm

going to do now is instead of me

literally walking you through the rest

of these tests I mean it's you can see

all the tests in here is I'm going to

challenge you to write these tests

yourself to get this for for coverage up

remember you can do Forge coverage to

obviously see what's going on we're

focusing on this one right now you can

also do Forge coverage D- report to see

oh D- report debug to actually see the

exact lines that are missing right and

all these things are just kind of line

items line items whatever IC doesn't

matter scroll scroll scroll scroll

scroll okay these are the ones that are

actually issues right what which one's

this oh that's that is the decentralized

stable coin we want to write test for

that as well but let's just focus on

this massive list up here DSC engine

focus on this list and write some tests

for this because yeah the rest of these

unit tests or staging tests we're not

going to learn anything new this is just

one of these things that you got to do

that you got to get good at that you got

to write now you don't have to get to

100% if you get it to like 85 90 that's

pretty good some of these tests are

actually very difficult to write but you

should writing these tests should find a

glaring bug in at least one of these

functions and maybe if you find more

than one glaring bug that's great make a

PR make an issue to the repo but I want

you to pause the video and take some

time right it might be an hour it might

be two hours it might be 30 minutes

right depends on how quick your AI buddy

is how quick you are and write some more

tests and sometimes actually you can

even come to your contracts

and you can do something like grab this

go over to your chat GTP say hey this is

one of my solidity functions can you

write some tests for it for it in

Foundry and because it doesn't know what

Foundry is it's going to totally bunk it

up but you could use chat PT to help you

write some tests as well help you get

your coverage up but there's definitely

one major issue in here you might even

need to go back and refactor some code

right I'm going to say keep that to a

minimum though but there are some spots

where maybe you need to refactor your

code to make writing tests easier maybe

you need to write some more helper

functions right take this time to

experiment and tinker and think what

should I do how can I make sure my code

is safe and importantly how can I write

enough tests to find this bug that

Patrick is talking about right maybe you

do some refactoring now don't write any

fuzz tests yet we are going to go over

fuzz tests in a little bit but yeah just

try to write the rest of these unit

tests rest of these pseudo integration

tests and I'll see you when you come out

the other side but when you finish

writing the tests take a break take a

minute I want this to sink in this is

one this is the most advanced lesson

that you're going to take in this course

and to be honest probably it's going to

be one of the most advanced courses

you'll ever take in solidity okay so I

want you to take your time with this I

want you to understand what's going on

sometimes it might even make sense for

you to go oh well what is maker Dow do

how can I learn more about stable coins

where else can I go maybe I can ask chat

gbt for questions right those of you who

are going ah I really don't want to do

that you can 100% just copy paste mine

but I recommend you go through this

exercise okay lock off some time and

I'll see you soon

all right welcome back did you find the

bug how your test looking if you run

Forge coverage did it look something at

least like this do they look better do

they look worse so I copy pasted a whole

bunch of my tests and we're looking

pretty good here we definitely should be

increasing the test coverage of our

branches and we can definitely get these

a little bit higher but for at least the

DSC engine

we have a much better code coverage

going on here and I hope your code

coverage looks looks like this too now

additionally I did a little bit of

refactoring writing these codes one of

the main things that I added was I added

this calculate health Factor function

reason I added this calculate health

Factor internal function was so that I

could have this public calculate health

Factor function and then in my test what

I could do is have an expected Health

factor and that way when function breaks

Health factor I can pass it into the

expected Health Factor error revert here

in one of my tests right when we're

testing to expect an event I added this

new function to do that and having a

public function like calculate health

Factor might make it easier for people

to see what their health Factor might be

if they make some change right so that

was one of the big ones I made and the

bug was in the health Factor as well or

at least the bug that I planned to be in

there so in my calculate health factor

which instead of in our underscore

Health Factor function I'm just calling

this calculate health Factor function

right I'm getting the account

information and then just passing it to

this calculate health factor and in this

we needed to add a checker for if the

total DS cemented was zero and if it's

zero then we said okay cool your health

factor is going to be the max U and 256

or something like that right and the

reason that we need this is if someone

deposits a ton of collateral but has no

dsed well their health factor is going

to divide by zero which we can't have so

calculating someone's Health Factor

after they deposit collateral would

result in an issue we'd Break Stuff we

don't want to break stuff and then the

final piece that I did was I added a ton

of external view functions just to make

it easier to read and interact with this

protocol so those are some of the

refactors that I did and then obviously

we added a ton of tests there's nothing

nothing really new in here it's just you

got to write the test right everything

in here you've learned you can do and if

you wrote some tests and you got this to

a high level of coverage around 90% you

should be incredibly proud of yourself

this is hard to write test for this is

very difficult project so you should be

incredibly proud of yourself for just

getting this far but guess what we're

not even done because we want to make

this code so freaking amazing we need to

think a little bit about security and

we're not going to go too deep into

security however we should ask ourselves

some questions right when we're working

with a code base we want to say hm we

should always always ask what are our

invariant /properties what are the

invariance slopies of the system and

that way we can write some stateful and

stateless fuz tests now I know we

briefly went over one form of fuzz

testing but now we're going to go a

little bit deeper and I made a video on

state less and stateful fuzz testing

recently and we're going to go ahead and

watch that so you can have a better

understanding of what stat less and

stateful fuzz testing is and why it's so

important especially for a project like

this that has potentially a lot of money

moving around so let's understand what

fuzz testing is let's watch this video

all right contracts are written and

tested can I ship my code no I can

easily break this with a flash loan

attack a crap I didn't think about that

let me fix all right how about

now if I make a flash loan on a I can

use that loan to lock up a cdb on Faker

Dow and I can exploit the Oracle by

re-entering your dinner reservation at

Chili's causing a bridge malfunction on

the flux capacitor bypassing the

possibility media I can exploit your

contract I exploit your contract

most of the time hacks will come from a

scenario that you didn't think about or

write a test for but what if I told you

that you could write a test that cannot

check for just one scenario but every

scenario let's get froggy fuzz testing

or fuzzing is when you supply random

data to your system in an attempt to

break it so if this balloon is our

system/ code it's us doing random stuff

and attempt to break it this is chain

link now why would we want to do all

that let's say we have this function

called do stuff it takes an integer as

an input parameter and we know that no

matter what we give it as an input our

variable should always be zero should

always be zero the fact that this

variable should always be zero is known

as our invariant or our property of the

system that should always hold in our

balloon example if we Market our balloon

as indestructible or unbreakable or

unpoppable the invariant that would hold

would this balloon cannot be broken and

unlike this balloon in real life we can

write a test that will call the do stuff

function many times with random data and

check to see that our should always be

zero variable is always zero now a

normal unit test for our code might look

like this we pass a single data point we

call the function and then we do our

assertion to make sure that should

always be zero is in fact zero and with

this we might think our code is covered

but if we look back at our do stuff

function a little bit closer we can

clearly see that if our data input is

two should always be zero will end up

being one this would break our invariant

should always be zero will not be zero

now this may seem obvious for this

function but sometimes you'll have a

function that looks like this

[Music]

it would be insane to write a test case

for every single possible integer or

scenario so we need a programmatic way

to find this scenario now in our code we

also see a second exploit but we'll get

to that in a minute now there are two

popular methodologies to find these Ed

cases fuzz test/ invariant tests and

symbolic execution SL formal

verification we'll save the ladder for

another video if we were writing our

code in Foundry this would be our unit

test writing a fuzz test in Foundry

where we do all this random inputting is

going to be really similar instead of us

manually selecting our data right in our

test parameter we'll add our variable

comment out this line and that's it now

when we run a Foundry test here Foundry

will automatically randomized data run

through a code with a ton of different

examples this is as if they run with

data equals 0 data equals 1 data equals

this number that's a t but whatever you

get the picture now if I run my unit

test you'll see that the unit test

actually passes however if we run this

fuzz test you'll see it actually gives

us an output where it says assertion

violated counter example gives us the

call data and the arguments it was able

to find out by randomly throwing data at

our function call that two breaks our

invariant AKA it makes a such that

should always be zero is not zero now

it's really doing semi- random data

instead of purely random data and the

way your fuzzer picks the random data

matters it won't be able to go over

every single possible un 256 so

understanding how your fuzzers pick the

random data is an advanced thing that

you should learn later on at the moment

I think the trailer bits a kidna SL

optic integration is probably the best

fuzzer out there and it easily has the

best logo of all time but ripped Jesus

is a solid second so now that we have

our counter example here we can use this

to go back into our contract find out ah

okay so we are doing this wrong delete

this line and then run our test again

and see that it does indeed pass what's

important is this number down here the

number of runs so this did 256 different

random inputs to make our test run in

Foundry you can change the number of

runs in your Foundry Tomo file by just

adding a section like this rerunning

your test and now you'll see it did a

thousand different examples the number

number of runs is really important

obviously because more runs is more

random inputs more use cases more chance

that you'll actually catch the issue and

now congrats that's the basic of fuss

testing let's just do a little recap

here before going further the first

thing you need to do is understand our

invariant or property of the system that

must always hold and our example should

always be zero was our invariant

understand your invariant and then write

a test that would input random data to

try to break that invariant now if we go

back to our example contract though

you'll see with our fuzz test we were

able to find this first use case case

however it didn't find this second

scenario where should always be zero was

set to one if hidden value was seven in

order for this to revert hidden value

would need to be seven and the only way

to set hidden value to seven would be to

First Call do stuff with seven which

would set hidden value down here and

then call do stuff again with anything

our fuzz test as written would never be

able to find this that's because this

fuzz test is known as a stateless fuzz

test which is where the state of the

previous run is discarded for the next

run if we go back to our balloon example

stateless fuzzy would be doing something

to the balloon for one fuzz run then

discarding that balloon and blowing up a

new balloon for each fuzz run however

instead of doing State less fuzzing we

could do state full fuzzing stateful

fuzzing is where the ending state of our

previous fuzz run is the starting state

of the next fuzz run or example instead

of blowing up a new balloon for each one

of these runs we just use the same

balloon to do multiple random things to

it combined is considered one fuzz run

so a single fuzz run on a stateless fuzz

run would be having data be7 calling do

stuff just using the same contract that

we just called do stuff on and then call

another function on it if this was a

unit test we had we would of course see

this get violated but as you can see

with sufficiently complicated code

coming with these very specific

scenarios are going to be missed to

write a stateful fuzz test in Foundry

you need to use the invariant keyword

and it requires a little bit of setup

and don't get too confused by the

invariant keyword here yes it's being a

little overloaded right invariant test

in Foundry we first need to import this

STD invariant contract and inherit it in

our test contract then we need to tell

Foundry which contract to call random

functions on since we only have one

contract with one function we're going

to tell Foundry that my contract should

be called and it's allowed to call any

of the functions in my contract so we'd

say hey the Target contract for you is

going to be the address of example

contract Foundry is smart enough to know

okay it's going to grab any and all of

the functions from my contract and call

them in random orders with random data

so it's going to call do stuff with

random data and then it's going to call

do stuff with random data and then it's

going to call do stuff with random data

since do stuff is the only function fun

now we can write our invariant by saying

function invariant test always is zero

public and we can just add our resert

cert our example contract that should

always be zero is zero so it'll run do

stuff with some random data if it

happens across seven it'll set hidden

value to7 and then it'll call do stuff

again with hidden values starting at

seven which will trigger this

conditional so now if we run this test

we can see it does indeed find a

sequence where our invariant or our

assertion or our property is broken we

can see first on my contract it's going

to call do stuff with an argument of

seven and then it's going to call my

contract with an argument of some random

number because it doesn't matter what

the input is after it sets it to seven

so now that we have that we can go back

to our code remove this come back to our

test rerun our test and we'll find that

our code is now safe and sound because

our invariants hold up now an important

aside on the term invariant founder uses

the term invari variant to describe this

stateful fuzzing stat less fuzzing is

when you give random data to an input to

a function to see if it breaks some

invariant State full fuzzing is when you

give random data and random function

calls to a system to see if it breaks

some invariant in Foundry fuzzing is

stateless fuzzing and invariance are

stateful fuzzing so when people are

talking about invariance in Foundry

they're usually talking about stateful

fuzzing if they talk about fuzzing in

Foundry they're talking about State less

fuzzing even though they're both

technically fuzzing there's an issue on

the repo to potentially change the name

but I digress so in a real smart

contract your invariant won't be that a

balloon shouldn't pop or some function

should always be zero it might be

something like new tokens minted is less

than the inflation rate there should

only be one winner in a random Lottery

someone shouldn't be able to take more

money out of the protocol than they' put

in and let me tell you what at this

point congratulations you've learn the

basics of fuzzing this is something that

even some of the top protocols in this

space don't use and this is something

that we in cphon use to find High

severity vulnerabilities in smart

contracts hey I'm Alex ran co-founder at

cyphon we use invariant tests during our

audits to identify vulnerabilities that

are often difficult to catch purely with

manual reviews that's not to say they're

a silver bullet they are in no way a

replacement for experts manual review

but they certainly can Aid in the audit

process this needs to be the new floor

for security in web 3 if you're working

with a protocol that isn't doing

stateful fuzzing or invariant or fuzz

test red flag get them to use it make a

PR number one understand what the and

variants are number two write functions

that can execute them do not go to audit

without these don't let your Auditors

let you get away with not having them so

this video was just to give you the

basics and if you want to learn the

advanced fuzzing strategies on how to

fuzz look Pro be sure to watch our next

video on the topic is that'll give you

the keys to write professional fuzz and

professional invariant tests come on

gang let's make web three better and

I'll see you next time

[Music]

all right so now we've learned a little

bit about invariant tests or fuzzing

tests and why they are so absolutely

crucial especially for a project like

this so we're going to write some

stateful fuzz tests or invariant tests

in foundaries so we can have some more

confidence that our code actually does

what we want it to do and the method

that we saw in that video that we just

watched is kind of the most basic

methodology out there and if we go to

The Foundry docs we can go on the left

side go all the way down to fuzz testing

or excuse me go all the way down to this

invariant testing which invariant

testing like I said is stateful fuzz

testing and we can read more about some

of the more advanced ways to do these

fuzz tests or these invariant tests

we're still going to do the target

contracts but what we saw in the video

was a type of open testing right where

we just have function in variant a and

then the assert and what this does is it

just calls calls all the functions on

this contract to try to break that

invariant now this is good this is great

for an initial run of the code however

we want to do for more advanced systems

like ours Handler based testing

sufficiently complex Protocols are going

to have so many different random

intricacies that we want to narrow down

the random call so that we can have a

higher likelihood of getting and

catching actual errors so we're going to

do this Handler based type of testing in

this example here in this open testing

it just calls any of the functions in

the contract in any order and Handler B

based testing if we scroll down we can

kind of see this example here where we

create a contract called Handler where

we only call functions in specific ways

for example when depositing tokens we

need to make sure an approve happens

beforehand if you just call deposit

without approving that token that's kind

of a wasted fuzz run and if we only have

200 fuzz runs and we're wasting them on

failed fuzz runs well we're the chance

of us actually finding a bug becomes

smaller so if you think of the open fuzz

testing like this where you have Foundry

you call a whole bunch of functions on

the protocol with the asserts Handler is

going to call functions in specific ways

to the functions so that we have a

higher likelihood of calling functions

in orders that we want so we're going to

learn about this Handler based

methodology and we're going to build an

incredibly verbose Buzz testing or

invariant testing setup now

in our founder. toal to work with these

fuzz or these invariant tests we can do

this in variant section here we can say

the number of runs we'll say is 128 we

can also say the depth which is the

number of calls in a single run which we

might do 128 and then one of the most

important keywords you're going to run

into is this fail on revert so let's

talk about this fail on revert keyword

and setting so to create some invariant

tests let's create a new folder or Buzz

test called or invariant or whatever you

want to call it and in here we're going

to need to actually create two different

files we're going to do invariance

invariance test. T.O and then handler.

T.O this invariance file is going to

have have our invariance AKA our

properties of the system that should

always hold right that we just learned

for that video and this Handler this

Handler is going to narrow down the way

that we call functions this way we don't

waste runs like I was saying again if we

call deposit collateral in our stable

coin without approving that stable coin

that's kind of a wasted run and we don't

want to waste runs so this Handler is

going to set our code up set our

contracts up so that we don't waste

these runs and we're going to come back

to this fail and revert in a second for

now let's actually set this to false and

we'll set it to True soon but so the

first thing we always want to do when

writing in variant test when working

with this just want to ask the question

what are our invariant what are the

properties of the system that should

always hold well we can think of some

right well one the total supply of

DSC should be less than the total value

of Catal follow the word wrap which the

total supply of DC which is essentially

the debt should always be less than the

total value of collateral great we have

an invariant that we can test and we

should throw a ton of random function

calls to try to break this one okay what

else what other invariants should we

have maybe our getter functions our

getter view

functions should never revert and this

is actually sort of an

evergreen invariant most protocols can

and should probably just have an

invariant that looks like this getter

view function should never revert now we

can probably think of more but because

because doing these invariant tests can

be a little bit time intensive we're

just going to focus on these two for now

these are going to be the two invariants

that we focus on we try to work with so

let's begin working and writing our

invariant tests and then we're also

going to write our Handler to help make

sure all the function calls that we're

working with actually do what we want

them to do okay let's do it so this is

going to be another test file so spdx

license identifier MIT pragma so oh oh

that's nice that kind of just

automatically added it for me let's put

this to the top

0.

8.18 a little carrot here contract

invariance test like this and to do this

we're going to say we're going have to

import some stuff we're going to import

test from Forge TD test. soul and import

STD in variant from Forge STD STD

invariant Soul contract invariant test

and then we're going to say this is STD

invariant and it's test so this STD

invariant contract if we click into it

it has all this stuff that we're going

to need to work with the invariant one

of the most important functions that it

gives us is this Target contract where

it says hey this is the contract I want

you to call all these random functions

on okay great now just like our normal

tests we're going to have a function

setup external like this and we're going

to set up some stuff right a lot of this

is going to look similar to our unit

test so we're going to have to import

Ploy

DSC

from do do do do script deoy DSC

dos. import DS C engine from do

slsrc SL

DC engine. Soul like this and we'll say

deoy DSC deployer

deployer deployer equals new deoy DSC

and then of course DC engine dsce dce

equals deployer do run and this actually

returns a whole bunch of stuff Central

stable coin dce and helper config so

this is going to be we also need a DSC

so we're going to import that import the

centralized stable coin from dot do do

do SRC decentralized stable coin. Soul

so we're going to do decentralized

stablecoin

DSC and let's get the helper config as

well import helper config config from

do do script slh helper config dos. Soul

helper config config right and so this

turns the DSC dsce and config equals

deployer run great and now if we were

doing this open testing methodology

right if we go back to the docs here

we're doing this open testing

methodology we could kind of finish this

right now what we would do we we would

say Target contract address dce like

this paste this in here and then just by

adding this we're telling Foundry hey go

ahead go wild on this right go

absolutely Wild on this and actually

let's even rename this call this open

invariant test. T.O open invariant test.

T.O we'll say absolutely Go Buck Wild on

this and now we can add our invariant

right we'll say function invariant

variant underscore protocol must must

have more value than total Supply and

this will be a view function and what we

can just say is we want to get the value

of the of all the collateral in the

protocol compare it to all the debt or

the DSC so we can do that pretty easily

by using the collaterals itself right

using our helper config we'll say helper

config do activ Network config we can

get the what does this one do again

let's open up the helber config we can

get these two tokens and just say okay

well what's the balance of these two

tokens in our DSC engine and then what's

their value right so we'll just get

those two tokens we're going to do

nothing nothing we Bitcoin nothing so

we'll do blank blank we BTC nothing and

then those are ERC 20s so we'll import

import I

erc20

from all right cool that looks

good so we'll say erc20 we ic20 BTC this

is wrapped BTC wrapped BTC oops sorry

this is config Active network config we

need to wrap this erc20

20 like this what am I messing up oh

let's do do address we then address we

address BTC like this all right cool so

we're getting we and Bitcoin EXC me

wrapped eth and wrapped Bitcoin and now

what we can do is first we'll say unit

256 total Supply equals DSC do total

Supply so this is the total supply of

all DSC in the entire world right and we

know the only way to mint DSC is through

the DSC engine so through people

depositing and withdrawing collateral

now what we can do is we can say okay

let's get the uint

256 total total we

deposited equals and this is where we

can do

ic20 with balance of address DSC so this

is going to be the total amount of we

deposited into that contract or just the

total amount of we sent to that contract

then we're going to say un 256 total BTC

deposited equals ic20 wrapped BTC dot

balance of address DSC so we have the

total we total Bitcoin now we can get

those values we can say un 256 we value

equals we have a function here called

get USD value where we can get the USD

value of any token of any amount so

we're just going to use that

we value is going to be dsce doget USD

value we and the total we deposited un

256 wrapped BTC value same thing get USD

value WRA BTC total BTC deposited and

now what we can do is we can

do assert the we Value Plus the wrapped

Bitcoin value is greater than the total

Supply and this

is all we would need to do for this open

testing this open invariance that's it

we're done boom and this is why this is

the easiest type of invariant test but

you'll see running this we won't get

great results so let's do Forge testm

and now what this is going to do is it's

going to call all types of functions on

our dsce and try to break this invariant

so it looks like it was able to break

this really easily so let's clear this

and we'll add our Dash BV

BV we'll see what's

up yep yep assertion violated we're

having a hard time actually seeing the

numbers so we're going to import console

in here test

console and we're just going to say

console. log we value so me call

W value or that's w w BTC we we W BTC

value

console.log total Supply total Supply

let's run this again now what do we

get well we got our first issue is that

these are all zeros right and if they're

all zeros then this doesn't hold so we

can do greater than or equal to this is

kind of a bit of a copout right because

if they're equal that makes us nervous

but it's fine right we should always at

least have more collateral in the system

than total Supply so now let's try again

run this test again run successful and

we get hey you pass there's no way for

us to make it such that the total Supply

is lower so this is awesome right well

it's not that awesome we didn't find any

issues we're looking to find issues so

maybe we need to bump up the number of

runs may we need to bump it up to

2000 and let's run this again now you're

going to see this is going to take a lot

longer CU before I was doing 100 runs at

128 depth now it's was doing a th000

runs and each one of these runs has 128

so it took a lot longer and you can see

that it took 14 seconds as opposed to

what it do before with 128 we run

that it did it in 1 and half seconds but

if we look up here on this line this

line is incredibly important we have

calls and we have reverts so this made

16,384 calls and reverted

16,384 times so basically it wasn't even

able to do anything right so what if we

bump this up to a th000 clear run this

we're going to have to wait a few more

seconds

again

oh so it did this many calls and it also

reverted this many times and the reason

that this is still saying pass though is

because we have this fail on revert

equals false and this fail on revert

equals false has some pros and it has

some cons the pro a fail on reverse

equals false is that we can very quickly

write open testing functions like this

and we can very quickly write minimal

Handler functions that aren't perfect

but the downside is it's hard for for us

to make sure that all the calls we're

making actually make sense right because

this could be calling on our on our

engine maybe it's just trying to to

deposit collateral but it keeps using

random collateral out addresses that

don't make any sense so maybe it's

calling this

128,000 times with 128 different

collateral addresses but only two work

right so doing like this is cool for

kind of some sanity check and maybe

it'll catch something but seems like

it's not actually catch anything right

and that's not a very good use of this

so revert on false is fantastic for

quick tests and often if I'm doing a

competitive audit which you can learn

more about in the security course coming

out soon hopefully if I'm doing

competitive audit a lot of times I will

have revert on false be false just so I

can write up inv variant test quickly I

will also write handlers as well like

mini handlers just so I don't have to

get every nook and cranny but I still

will write a Handler so I can narrow

down some of the functions but this open

inv variance seems to have this major

flaw where it's probably making a bunch

of silly calls so this is great for very

small contracts but the more complex you

get like our system here this open inv

variant system it probably doesn't make

sense for us to do because it's not

going to catch anything it's just going

to keep breaking now if we set this to

true we open this back up we run this

again you'll see

exactly one of the calls it makes that

breaks so it looks like it called redeem

collateral for you for DSC this is the

first function call it made which

obviously doesn't make any sense because

you can't redeem any collateral unless

you have deposited collateral and and

you can see the args it put in it put in

some random address some random amount a

random amount and then another random

number right and you'll see we can call

this many times and it'll keep giving us

different that it ran into issues when

we say revert on false is true this can

give us some peace of mind knowing that

if this test passes that means all of

the transactions that went through

actually went through and it didn't make

a bunch of really dumb calls here right

so here fail on revert was false we

called liquidate first which obviously

doesn't make any sense with this with

some horrible random address some

horrible random address some random

amount right none of these make any

sense we call it again we failed again

it called deposit collateral mint DSC

which is good all right so we're trying

to deposit collateral but it used some

random address that isn't approved some

horrible amounts here and it just keeps

failing right so we want to try to

prevent and you can see here in the call

summary it made one run one call and

that call reverted right so we want to

narrow this down to say to try to point

our fuzz our random runs in a direction

that makes a lot more sense right so

this is cool not great opening variance

I'm just now going to comment out this

whole page because we're not going to

use this anymore okay we're I'm going to

leave the file in here though we're

going to create a new file though we're

going to call this

invariance t. soul I am going to copy

this whole invariance thing paste it in

here and uncommon it and we're going to

level this up so that this invariance

file actually let's just call this

invariance so that this new one is using

this Handler method it's using this

Handler method to narrow down the

function

calls and we'll do a mix of setting this

to true and false and you'll see where

some of the advantages and disadvantages

are so we have our invariance file we

have our Target contract here but we

want to make sure we call this in a

sensical order for example hey don't

call redeem collateral unless there is

collateral to redeem

right maybe we want to set this up so

we're going to create a Handler which is

going to handle the way we actually make

calls to the dce so it's basically going

to instead of us just randomly calling

redeem collateral we're only going to be

able to call redeem collateral if there

is collateral to redeem right because

otherwise the transaction is just going

to revert and that's a waste of function

call so now we're going to create this

Handler and instead of our Target

contract being the dsce our Target

contract is going to be this Handler

which handles the way we make those

calls okay so we're going to do spdx

license identifier MIT as you already

know fragma Z solidity

0.88 a little carrot contract Handler

like this and then we're going to say

this contract Handler is going to be

test as well and this is definitely some

Advanced code here so don't get too

discouraged if it doesn't make sense or

if it's hard the first time okay so

we're going to inut report test from

forg STD test. Soul remember to ask

questions and use the forms so what's

one of the first things you want to do

hey don't call redeem collateral unless

there is even collateral to redeem right

we want to make sure that that's this is

a valid run he only call redeem

collateral when there is collateral in

there so this function this contract is

going to do that for us we do need to

make a Constructor though so that this

Handler contract knows what the DSC

engine even is right because it's going

to be the one making the calls to it so

we do need to import the DSC engine from

do do

slsrc DSC engine. we also need to import

the decentralized stable coin from the

decentralized stable coin. Soul

Constructor and these are going to be

the main functions these are going to be

the main contracts that our Handler is

going to call so we're going to say DSN

and dce

and then we're going to say

decentralized stable coin DSC and in the

Constructor here we're going to say DSC

engine uncore DSC

engine decentralized stable coin _ DSC

and then we're just going to say oh cool

I already added it dsce DSC engine and

DSC isore DSC so because these are the

contracts that we want the Handler to

handle making the calls to Great makes

sense so let's talk about this redeemed

collateral right let's just focus on on

making this not revert so we're going to

say okay call this when you have

collateral so the first thing we

probably need to do is what probably

deposit collateral right so we'll create

a function called

deposit

collateral and this function is going to

look a little different than the deposit

collateral in the DSC engine right if

we're look in here this is what it does

we're going to set this deposit

collateral function up in our Handler so

that this transaction always goes

through right it doesn't revert but we

do want to keep the randomization right

we wanted to deposit random collaterals

that are valid collaterals so what we

can do is we can create a unit 256

collateral seed and a un 256 amount

collateral collateral and this is

actually really similar to the fuzz

tests so in your handlers whatever

parameters you have are going to be

randomized so we're going to pick a

random one of the valid collaterals to

deposit and we're going to pick a random

amount of collateral now I'm going to

write this function without any guard

rails and it's going to break and that's

okay we're going to fix it as we go

along but if we were to just not have

any guard rails on this at all we would

just say dsce do deposit

collateral

ceral and we would do you know

collateral and an amount collat Al we

could actually just have this be

address collateral and amount collateral

and we'd say deposit this collateral and

amount collateral and this of course is

probably going to break a lot right

because the collateral we're going to

pass is going to be wrong this is a

random address there are so many

addresses and the amount of collateral

could also break because deposit

collateral reverts on zero right but I

do want to show you what we're actually

going to do in our actual contract here

instead of having our Target contract be

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

going to say Handler is we're going to

import this Handler so we're going to do

import Handler

from handler. T.O Handler Handler we're

going to say Handler equals new

Handler dsce and DSC and now we're going

to say our Target contract is just the

Handler okay excuse me the address

Handler now with this the Handler only

has this one function so we're going to

call deposit collateral through the

Handler which is going to call our

engine and since this is the only

function for it to call this is all

we're going to see if we see our

invariance break so if I do Forge test

DM paste this in we're going to see it

break almost

instantly with an issue but it's only

going to be deposit collateral because

it's the only function that we have

right we run it again it's still going

to be deposit collateral cuz the only

function the Handler has yes makes sense

okay cool hopefully it makes sense in

our Foundry doomo we could say fail on

revert is false we could run this again

let's make this a little bit lower 128

and let's see if we get any valid runs

right let's see if we pick miraculously

a valid address and we get success but

oh it looks like we did do some valid

ones but we've got a ton of reverts here

we've got so many reverts here that

almost half of these runs almost half of

these calls were bad that's not a great

use of our and this isn't really super

helpful because of course of course our

invariant here is going to hold because

the only thing we've allowed our system

to do is deposit collateral right

ridiculous so if we turn this back to

true we run this again we're a course

going to break now because some of these

deposits are going to fail right so it

looks like if we call deposit collateral

with some horrible address

it fails right so that's one of the

first things we want to to have our

handler do we want to say hey you're

only allowed to deposit valid collateral

so what we can do in our Handler is we

can set that up hey you're only allowed

to deposit valid collateral instead of

passing any address as collateral we'll

say U 256

collateral seed okay and what we're

going to do with this seed is we're

going to have it pick from our two coll

lals we're going to have it randomly

pick either we or BTC so we're actually

going to create a function helper

functions we're going to say function

underscore get collateral collat from

seed un 256 collateral seed and we're

going to make this a private view

function it's going to return an ER an I

erc20 actually we're going to do an

erc20 Mock and I'll explain why in a bit

we got to import that import rc20 mock

from at open Zeppelin contracts mocks

slash what is it mock ERC

noc2

mo. cool and so what we're going to do

instead of this line is we're going to

use this line this function to do it

we're going to say if collateral collat

all seed modulo 2 cuz we're only we only

have two collaterals equals equals zero

then return we we can get we by sticking

at the top we'll say erc20 mock we ERC

20 mock WFT

Bitcoin and right in our Constructor we

can get all of our collateral tokens the

I made a function way down at the bottom

here called get collateral tokens which

returns the full array of collateral

tokens if you don't have this feel free

to pause and implement this what we can

do we can say address array memory

collateral collateral tokens equals dsce

doget collateral tokens like this and we

can say we is zero and R BTC is one

that's how we can get those collateral

tokens so we R BTC if collateral C

divided by 2 is z return We otherwise

return wrapped BTC so now we have a

function where we can only get a

valid collateral type so instead of just

depositing any collateral type we can

say uh erc20 mock colateral equals get

collateral from seed collateral seed and

now we're still depositing a random

collateral but this is oh it's got to be

address but this is a valid collateral

address so we're probably more likely to

actually pass a transaction that will

actually go through making us have more

solid more good random calls so let's

try to run this function

now great successful but we ran into an

error right let's see what the error is

so deposited collateral you U and 256 U

and

256 with this huge collateral

seed uh and

nothing looks like we failed here it's

clear let's rerun it with- vvvv so we

can see a little bit output of why we

actually failed okay we ran we still the

only function we're calling is deposit

collateral looks like this failed again

we called deposit collateral with some

weird args we can scroll up and see

exactly why we failed oh we ran to this

DSC engine needs more than zero so it

looks like we tried to deposit zero

collateral Mount collateral was Zero yep

okay yep so we tried to call was zero so

amount collateral was zero so we know

that this is going to fail so how can we

make it so that this doesn't fail or

maybe you're like hey like sometimes it

will be zero like whatever I I just want

a sanity check you can make fail and

revert false right and we can run this

again and now we'll see how often this

actually fails hopefully we cut down on

the amount of times it failed oops let's

remove those

V's great it actually it does look like

we cut down on the amount of reverts we

got not a lot but we we did cut down the

amount of reverts at least by adding

this bounding of the collateral types

but let's keep cutting down on these

reverts and potentially even have revert

on false be true right you're not always

going to have revert on false be able to

be true and sometimes it's quicker just

to have it false and write all your

invariance and stuff but if you want

kind of but is good to aim for this now

the downside of always aiming for this

is that if you make your handle too

specific maybe you'll actually narrow it

down and remove edge cases that would

break the system that are valid right so

it's kind of this balancing game you

have to play with these fuzzing tests

and whether fail and revert to be true

or false there's definitely a little bit

of an art to this so the more you do it

the better you'll get but in any case

collateral seed amount collateral we

need to now change it so that this

amount collateral is bounded between one

and some Max number right so we don't

want this to be able to be zero so what

we can do then instead is we can

actually we actually can bound this so

that in the same way we got a valid

collateral let's get a valid amount

collateral so we can say amount

collateral equals bound this is a

function that actually comes with STD

utils and it bounds the result to an

amount so we want to say okay this

amount collateral we're going to bound

our amount collateral to being between

one we don't want to be zero and then

some like really really big number what

I like to do is up here in the state

variables I'll do U 256 Max deposit size

equals and I'll do type uint

96.

Max and this allows us to get the max

uent 96 value why are we not doing the

max U 256 well if we do the max U 256

and we try to deposit more collateral

later if you do the max6 plus one you'll

get a revert so this is going to give us

a really really really big number but

we're at least not going to hit the

absolute top of amount of deposits we

can deposit so we're going to say we're

going to bound this amount collateral

between one and Max deposit size Okay

cool so let's put this back to false

let's run this test again and let's see

if we cut down on the reverse some more

aha a couple more right only a few

hundred but we did cut down on the

amount of reverts why because we're

passing valid well okay that one didn't

go so well but we are cutting down on

the amount of reverts piece by piece

we're able to bound the collateral but

there's more if we do failon revert back

to true we can see exactly why it's

failing right we'll do- vvv VV we can

see an examp example that is indeed

failing and who these are getting more

intricate right before it was just a

single call was breaking it oh okay a

single call still is breaking it but

they are getting a little bit more

intricate so looks like this one failed

because what we called deposit

collateral we scroll up we're getting

this insufficient allowance okay so

that's why we actually weren't cutting

down on the reverts at all because we're

getting insufficient allowance of course

we need to approve the protocol to

deposit this collateral so of course

this is breaking this is always going to

break so let's do a little prank so

we'll do vm. start prank we'll just do

message. sender and we H will allow this

message sender to Mint some of this

collateral so that they can actually

deposit it right so we can set this up

so that whoever's calling deposit

collateral actually has the collateral

and actually will approve to deposit the

collateral so and this is why I'm using

this erc20 mock so that we can actually

mint some of this collateral so we'll do

collateral. mint message. sender amount

collateral we'll do collateral

collateral. approve address

dsce for the amount collateral then we

can deposit it and then we'll do vm.

stop prank okay now let's clear this

let's have revert on false to be false

and let's see now if we cut down on the

amount of reverts that we get

oh and I added too many V's let's get

rid of those let's run this

again and yep there will be some brief

delays in here of course whoa we cut the

amount of reverts down to zero now all

of our function calls are passing which

means every single run was a valid run

meaning we're using our runs much more

wisely we're not wasting runs on failed

reverts so now I can even set this to

true run this again and we'll see this

passes and none of our runs failed right

so this means what does this mean from a

security standpoint it means that no

matter how often we call deposit

collateral no matter how much we deposit

our collateral we will never make this

invariant false which isn't saying too

much because of course we're not even

the total Supply is always zero of

course holds so this makes a lot of

sense so let's actually keep writing

more functions to do more with the

system but set them up so that whenever

we call them they're always going to be

valid calls

okay so now we're talking about redeem

collateral right okay cool so now

there's actually now we actually have a

function a valid function to deposit

collateral now let's actually have a

valid function to redeem collateral so

we're going to do the same thing

function

redeem

collateral

collateral we're going to do the same

thing it's going to take a un26

collateral seed for which collateral to

redeem un 256 amount

collateral so be a public and we're

going to do something very similar here

we're going to say we're only going to

choose a valid collateral by saying

erc20 mock collateral equals underscore

get collateral from seed collateral seed

and now we should only allow people to

redeem the maximum amount they have in

the system right so we're going to say

un 256 Max collateral collateral to

redeem equals DSC engine

engine dot get

total get

collateral balance of user do we have

this

function DSC

engine so this is one that I added in

it's going to get the collateral balance

of a user if you passing the user in the

token so if you want to pause and add

this in feel free to do so get

collateral balance of user where we add

the address of the

collateral and the message. sender so

it's going to get the total balance of a

user oh and this should be

dsce and then we're going to bounce the

amount collateral to this max amount

that they have to make these always

valid they should only be redeeming as

much as they put in the system amount

collateral equals

bound amount

collateral uh we're going to say redeem

between one and the max collateral to

redeem because we don't want them to

redeem zero of course and then we're

going to say it's going to be public

then we're going to say dsce do redeem

collateral address collateral and amount

collateral right so now we have two

functions to randomly call so we're

going to be depositing collateral and

redeeming collateral let's run this

invariant it only has two functions it

could call go to the found. toml fail

and revert is true oh and it looks like

we found an edge case so now we can read

this and see what it's doing so it's

depositing some collateral 1 38 1 and 82

and then it's Redeeming the collateral H

not actually sure what's going on so

let's add

this Dash

vvvv to see more into the actual

transaction that's failing oh my

goodness we got an even bigger one here

so what are we saying oh Max is less

than the min oh looks like I'm messing

up with my bounding so it's not even

really an issue so if we go back to the

Handler bound M collateral One Max

collateral Al to redeem ah okay so if

Max collateral to redeem is zero this

will break so we actually do need to

keep zero in here and then we can just

say if you know amount collateral equals

equals z we could say if it's zero

return or what we could do is we could

use this keyword called assume like vm.

assume which will say if the Boolean

expression evaluates to false the fuzzer

will discard the current fuzz inputs and

start a new fuzz run so we're going to

do if the amount collateral zero just

return don't call this function right

cuz this is going to fail so let's go

ahead and run this again now compiler

run

successful well would you look at that

we are now passing again so people can

if we go back to the Handler people can

now redeem collateral and all of these

redeeming are going to be valid and all

these deposits are going to be valid

right they can only redeem

valid Redemption amounts now here's

where this fail and revert equals true

is can be a little bit deceptive let's

say right now we're only letting you

redeem the max collateral to redeem

let's say there was a bug where a user

can redeem more than they have this fuzz

test wouldn't catch this it's because we

have this fail and revert is true if

this fail on revert was false and we

didn't have this line right and we just

said this is the max deposit size this

is a test where we might actually catch

that bug right and if we run this now oh

and with fail on revert is false we are

going to get a whole bunch of reverts we

are going to get bad transactions

however and you can see we can see the

number reverts over here and it actually

is way less than it was before which is

awesome and if we run it again still way

less than 8,000 which is what it was

before but if we have fail and revert

false we can actually catch this so The

Foundry team is actually working on

allowing some test to be fail in revert

and some test to be not fail in revert

so you can kind of pick which one for

which functions instead of kind of

having to blanket everything so just

keep in mind the dangers here okay of

always defaulting to fail on revert

equals true okay they have their

trade-offs and if you do fail on rever

equals false you can sometimes write

these handlers a lot quicker

but okay so we have some stuff here we

can deposit collateral we can redeem

collateral what else so we probably

should figure out a way to get some

total Supply right so what we're going

to do is now we're going to finally make

our mint function function mint

DSC public like like this and what do we

want to put in here well if we go to the

DSC engine go to Mint DSC go to this

mint DSC function it takes an amount of

DSC to Mint so we'll do the same thing

we'll say uint 256 amount and that's it

we'll mint a random amount so in here of

course we can't have amount be a number

of things right we can't have it be zero

and they would need to not have their

health Factor be broken so we're going

to say amount equals bound amount one

and let's say Max deposit size and then

additionally this amount better be more

than the value of the system right

because we have this revert if Health

factor is broken but maybe I don't even

want to do that narrowing down maybe I

just say screw it I'm going to make

revert on false revert on fail on revert

false and I'm just going to leave it

like that because I'm nervous that I'm

going to narrow it down too much so then

maybe I just go screw it bm. start prank

message. sender and we call in the DSC

engine mint DSC dce do mint DSC and the

amount then bm. stop Rank and this is

where actually you'll see sometimes some

people will have continue on revert and

a fail on revert fail on

revert see people some people can have

two types of folders continue on revert

is going to be the quicker looser test

where it might look like this the fail

on revert is going to going to make sure

that every single transaction that you

run your invariant test sued on is going

to pass I personally think it's good to

have both when I'm writing invariant

tests I actually start with to continue

on revert because they're faster often

times you can find bugs as long as you

narrow down them enough so for now let's

go ahead let's have this be false see if

we can find any issues like this so

we'll go up up so we'll run Forge test-

M just going to run this invariant test

boom let's see if we got any issues here

we'll see how many reverts we get as

well we got a similar amount of reverts

which is good similar amount of calls

which is all right and then actually if

we do- VV we can even see the Conant

that logs at the end it looks like it

hasn't found a way to Mint more tokens

than collateral in the system oh and

even it looks like the last run it ended

with a total supply of zero right but

maybe I'm paranoid let's actually go

back to true and let's just stay true

for the rest of the rest of this but

like I said I think it's good to have

both types of test anyways Handler so

this mint DSC we should only be able to

Mint DC if the amount is less than the

collateral so what we can do is we can

call this get account information which

gets the total collateral value in USD

and total DSC minted and make sure that

we're always going to Mint less than the

collateral value that we have so we can

say we can actually just copy these two

paste it in here equals dsce dot copy

this function paste message. sender so

we're going to get the total DSC minted

B value in USD and what we can do is we

can say we'll just have them always mint

the max DSC they can mint so we'll say

un 256 Max DSC to Mint

equals collateral value in USD we could

say the collateral value in USD / 2

minus the total DS minted better be

greater than zero right better not be a

negative number so we can even do like

an INT

256 and then if this is negative then

we're just going to return otherwise

we're going to say amount we're going to

equals bound this again say

amount Z comma Max D to Mint then we're

also going to say if amount equals zero

we're going to return oops and then

actually we need to grab this start

prank put this down here that's all we

need to do and we should probably just

grab these put them down here we don't

need both of these so we just need this

I think yeah we don't need both of these

we only need one of these so we'll do UN

2 we'll convert this back to un

256 F am out is zero

return this looks pretty good to me

let's see if we made this actually work

let's run this and now we can mint

DSC

successful and bada boom so we have some

calls we have no reverts this is

great but I keep getting total Supply is

zero down here so we plenty of we plenty

of rap Bitcoin are we ever calling this

function

H we keep getting a total supply of zero

down here why is that how could we

figure out if our mint DSC is actually

getting called let's first off see if

this mint dsse is even being called we

can use something called ghost variable

to track this so in here up at the top

we'll make a function called un 256

times mint is

called make this a public variable and

at the bottom of mint DSC we'll do times

mint is called

plus now back in our invariance we do a

console.log times mint called comma

handler. timesm called and then we'll

run our test again oops with-

VV and we can see oh mint is actually

never called how is that possible well

it must be because one of these returns

is hitting and it's not finishing this

call so we could keep moving this up to

figure out where it's actually being

called and to continue to debug this but

I already know how to debug this of

course because I've done this a while if

you want take this as a challenge for

you to answer the question why is this

never being called why is times Min

being called Never being called why is

it never finishing

so feel free to pause the video try to

debug this yourself and find out and

then I'll tell you the technique that I

used to debug this and figure out why

this mint DSC was never being

finished all right welcome back did you

actually pause the video did you

actually try to figure it out if you

didn't I'm giving you a second chance

pause the video go find out pause the

video and take this as your opportunity

to try to debug okay why is this not

getting hit why is this line not

hitting all right welcome back now there

was a couple different ways that I used

to actually debug this one of them was

having this times Min called plus equals

1 and then moving it up so I found the

line that it was breaking on once I

found the line that it was breaking on I

console. loged all the values of the

different variables around one of the

most important variables that I dumped

was going going to be the message.

sender so when you're working with

invariance remember it's going to call

this contract with a ton of different

functions and a ton of different calls

however it's also going to call them

with

random addresses as well so in order for

us to Mint DSC we need to only mint DSC

with an address that has actually

deposited collateral

because it's impossible for someone to

Mint DSC without them depositing

collateral now again if we restrict this

function like this maybe there is a case

where you can mint DSC without

depositing any collateral that we don't

know about this is again why it's

important to have some open invariant

tests some continue on revert and some

fail on revert as well so if we want to

have this be failon Reverb we would need

to only pick a message that sender that

has some deposit collateral so what we

can do is actually keep track of people

who have deposited collateral and then

when we go to Mint we just choose an

address from somebody who already has

deposited so how can we do that well we

can just keep track of an array of

addresses that

have lateral deposited so up at the top

well let's actually keep this times mint

as called we'll put it at the bottom

times M it's called Plus+ and this way

we know how to test this right if times

myth is called increases we've known we

will know that we fixed the actual issue

so times myth is called plus plus but

the top we'll do a address array public

users with collateral

deposited we'll copy this address and

now in deposit

collateral users with collateral

deposited. push message. sender now

there's some caveats here this will

double push obviously some people so

this will double push if the same

addresses push twice but for now let's

just keep it simple and let's go ahead

and just leave it like this we probably

should check to see if someone has

already deposited collateral but

whatever we're going to go with this for

now because simple and then now in our

mint DSC we can do something similar to

what we did with collateral so we'll do

a underscore U into

256 address seed

and instead of bounding to message.

Sender what we can do is we can say

address sender equals users with

collateral deposited it's going to be

the index of the users with collateral

deposited Andress seed mod uses with

collateral

deposited. length and now now instead of

message. sender we're going to use

sender in here same thing with down here

we're going to use send

now let's run this and see if mint is

ever actually

called aha so this was very helpful redo

it let's do- VV

VV ah okay so at least we're getting

something different here right we're

getting an error division or module by

zero ah okay of course we're getting

modu by zero because if the collateral

length is zero then obviously sender is

going to be zero so we can do if uses

with collateral. length equals equals z

then we're going to return we're going

to skip this one so let's run this

again okay so we're getting some stuff

passing let's actually just do a 2vs so

that it's easier to read than all those

events

aha total times mint was called is now

31 and we're getting a total Supply so

our mint DSC function in our Handler is

now actually working we're now

successfully calling mint DSC and it

looks like our protocol is holding up

all right fantastic so we're getting

closer to building this Handler to

actually have a solid Recreation of all

the possible functions we can actually

do in this system something I didn't

show you was we should pretty much much

always use a given invariant called

function invariant Getters should not

revert like this and we just put in here

all of our invariance like dsce do get

liquidation bonus dce do get Precision

Etc put all of our Getters in here and

oh and this could be public View and if

any of these revert then this will fail

this invariant test will call a ton of

different functions on the Handler and

if any of the function combinations

break any of our Getters we know we

broke an invariant this is a layup and

variant that everyone should always 100%

include a way to make sure that you're

including everything is you can run

something called Forge inspect DSC

engine methods and it'll print out all

the different methods that this function

has in addition to its function

collectors so you can kind of use this

as your checklist of all the different

functions you can call on a contract and

you can look for all the view functions

in here this is additionally why it's

great to have get in front of these

words because becomes very easy to

figure out which ones are

Getters but it doesn't reflect the whole

world right one of the other really

fantastic things we can do with the

Handler is we can both handle our DSC

engine but any other contract that we

want to simulate for as well and there's

a lot of things we want to take in mind

when writing these especially the other

contracts that we interact with what are

some of the other contracts that we

interact with well one of them is going

to be the price feed one of them is

going to be the we token the wrapped

Bitcoin token so our Handler should

probably also show people doing random

weird things with we and rap Bitcoin

right because people are going to do

random weird things with both of these

tokens and we want to make sure our

system can work with them appropriately

now I'm actually going to skip them for

now but I am 100% going to do one with

price feeds because price feeds are

definitely a system that can change and

definitely a system that greatly affects

our protocol so we're going to include

price feed updates in our Handler so

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

go ahead and do import a mock V3

aggregator from slash do do slash mock

SL mock V3 agregator doso or where is

this located oh just one this okay and

this mock V3 aggregator has some

functions that allow us to just easily

update and answer right which is what

something that we want to do we want our

protocol to be able to easily update

answers so we'll take this mock V3

aggregator and let's at least get the we

price from our system so so I have a

view function dsce doget collateral

token price feed and I'll pass the

address we

oops and I'll say eth and I'll make

another variable mock V3 agor public eth

USD price feed I'll say eth USD price

feed equals this and we just got to wrap

this up as a Mo V3

aggregator this and great now we have an

ethusd price feed and now we can add a

new function in here so we have mint DSC

deposit collateral redeem collateral we

can add a new one called function update

collateral price we'll do a uent 96 just

so that the number isn't too big new

price and then we could also randomize

the collateral but for now we'll just

have it be the ethusd so

we need to convert EU 96 to an INT 256

new price int equals in 256 new price

because price feeds take in 256s oop

sorry this should be in and to convert a

u 96 to an INT 256 we actually have to

wrap it as u in 256 first and then to n

96 do update answer or set price or

whatever we want to do to this new price

like this boom and now simple as that we

have an update collateral price well an

update eth price anyways so now we can

do three things in our system we can

update the price redeem collateral

deposit collateral and mint DSC so

before we actually run this what do you

think do you think we'll get n what do

you think we'll go on let's run this

oh it looks like it found a sequence it

found an issue the reason assertion

violated which means that our invariant

here was broken the we Value Plus

Bitcoin value now is no longer the total

Supply so let's scroll up let's see what

the issue is here all the way past

everything and if we read the sequence

we can figure out why this broke we see

exactly what happened okay so first it

called deposit collateral Okay cool so

we deposited some collateral and then we

minted some DSC okay cool we minted some

DSC with some stuff here and then we

updated the collateral price to

471 so as we know our Handler update

collateral price if we scroll the way to

the bottom update collateral

price

471 updates the eth collateral from

$2,000 which is

2008

to

471 so this remember is 2 1 2 3 4 5 6 7

8 it went from this to 471 so of course

it reverted right because people minted

a ton of collateral they deposited

collateral they minted a ton of DSC

right look at this input it's massive

and the system broke and if we run this

again with fewer V's right VV we'll be

able to see that total Supply we scroll

up we'll be able to see the we value rep

Bitcoin value and the total Supply here

so actually it looks like in this one it

set the new price to three so obviously

the we value is probably zero or just

about zero it let them mint DC because

originally the collateral was were was

worth something and now it's worth

almost nothing right so this is an

important thing for us to take in mind

in our system hey if the price drops or

spikes quickly our system is screwed our

system is busted and this is something

we would want to know about and

potentially go back in our code and fix

hey what do we do when the price

plummets in a single block right now we

have kind of this assumption in here

where we have this liquidation 10% bonus

and the collateral always needs to be

200% over collateralized with this we're

saying okay between 200%

overcollateralization and 110%

overcollateralization

as long as our system is within this

it's still safe I mean obviously it's

better if it's above this but as long as

our system is within this it's still

safe but if the price plummets of some

collateral and let's say that's the only

collateral maybe we get to 50%

collateralization rate and that would

break our entire system right that would

break our invariant and our system will

be screwed so we go back to the drawing

board figure out how to smooth this out

or we can say this is a known bug if the

price fluctuates or explodes too quickly

or too slowly this protocol becomes

worthless and that's kind of not a great

solution right so these are things we

absolutely want to keep in mind and

these are things that we can find with

invariant tests this is why they're so

important so for now in our Handler I'm

actually just going to even comment this

out because it does break our test Suite

but I'm going to put a little comment

here this breaks our

invariant test suite and this would 100%

be something that shows up in a smart

Contra audit saying hey if the price of

an asset plummets too quickly the

system's breaking because it breaks the

invariant all right great now there's a

few more things I want to teach only a

few and then we're done with this

section we're going to teach one some

proper Oracle use and then two we need

to write more tests which we're not

going to do I'm going to leave that to

you but we have a whole bunch of other

contracts in here like the decentralized

stable coin and then three some smart

contract audit preparedness some smart

contract audit preparation so let's

start with some Oracle proper

use so in our DSC engine we're of course

using an oracle right we're using chain

link price feeds now this is kind of an

assumption that we have in our protocol

right now he price feeds are just going

to work but price feeds are a system

just like anything else and we should

add some checks in our code here just to

make sure that if this breaks or if

something in here breaks our system

isn't broken so what we're going to do

is we're actually use that Library

methodology we made years ago to write

some checks on this price feed so I'm

going to make

a libraries folder and we're going to

make a new contract in here called

oracle. and what we want to do is we

want to check to make sure that these

prices aren't stale if we click on any

one of these prices like eth USD let's

scroll up to show more

details more details you can see they

have this heartbeat where a new price

should show up at least every 3600

seconds I believe what this is right yes

on theoa testnet we want to write some

checks to make sure that this is

actually updating every 3600 seconds and

if it's not we should probably pause the

functionality of our contract so we're

going to make a

spdx

license identifier MIT pragma solidity

like this we're going to do a library

Oracle lib and let's put a little natat

speec to explain what this is going to

do say add title Patrick Collins oops

title Oracle lib at author

Thor Patrick

Collins at notice this library is used

to check the chain

link Oracle for

stale if a price is stale function will

revert and render the dce engine

unusable this is by Design so we're

going to say hey if a CH price feed to

stale just stop don't let anything

happen because if a price is wrong if a

price is bad our whole protocol is kind

of bunked right so we want to just

freeze everything so we want the DSC

engine to freeze if prices become stale

so if the chain link Network explodes

and you have a lot of money locked in

the protocol too bad this is something

that's going to be a known issue right

if the chain link Network blows up and

all the prices become stale H you're

kind of screwed right and maybe this is

something we want to account for but for

now I'm just going to say that's a known

issue and we're going to move on and

this is where you'll see me start to get

more and more par particular about stuff

this is where as we get more and more

advanced this is where the details start

to matter more and more right all those

little little things that I kind of

gloss over they become to they start to

become more and more important as this

Bec comes closer and closer to a real

production product that should go to

audit right so let's create a stale

price check function so we'll create a

function stale price check and we'll

have this stale price check beond an

aggregator V3 interface. Soul so I'm

actually going to copy this paste it in

here toggle the word wrap and so as an

input parameter it's going to take

aggregated V3 interface price feed

this will be a public view which will

returns a uint 80 in

256 U 256 U 256 and a uint 80 the same

return value of the latest round data

function in an aggregator V3 interface

function like this okay cool and in here

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

call Price feed Dot latest latest round

data and I'm even just going to cheat a

little bit we're going to control click

into this we're going to copy this line

paste it here

equals boom just so I don't have to type

as much cool we have all those and what

we're going to say in here and we're

probably not even going to use all these

we're going to have some stale check

right so each one of these price feets

has their own heartbeat so we probably

should ask them what their heartbeat is

but I'm just going to hard codee it for

this one I'm going to say un 256 private

constant timeout equals 3 hours and this

is a constant in solidity it stands for

3 * 60 Minutes time 60 seconds

equals uh this many seconds so looks

like this heartbeat is actually much

longer than the one the chain link

should allow so 360 seconds is 3,600

seconds is just 1 hour right we're going

to give it 3 hours so what we're going

to say in here is we're going to say

first we're going to do a un6 seconds

since equals block. timestamp and then

we'll have uh excuse me

minus updated

app and then we'll say so this will get

the current block timestamp minus this

updated app so this should basically get

us the seconds since this price feed was

updated then we'll say if second since

it's greater than our timeout then we're

going to revert with a new

error

error or

cbor stale price this revert with stale

price and then we're just going to

return all of this stuff so return round

ID answer started at updated at answer

around and I'm going to change this name

to stale check latest round data now

what we can do since this is a library

on our price feed we can use this stale

check latest round data to automatically

check to see if the price is stale so

now in our DSC engine anytime we call

latest round data we just swap it out

for stale check latest round data so

long as at the top we go after our

errors we're going to put our types

after the errors we're going to put

types so this is where we would do using

Oracle lib or

aggregator B3

interface we need to import Oracle lib

let import Oracle lib from there's going

to be libraries

libraries Oracle li. so like this and

now yep any place we use latest round

data we can now use stale check latest

round data where we have this stale

check baked in and cool now we did a ton

of refactoring let's run Forge test just

run this whole test Suite including the

invariant test

Suite okay and stuff's looking good here

and you can see that it even took a lot

of extra time to run this last bit so

cool we've got a little check here great

we're not going to write some more tests

this is something that you should 100%

do we pull up our terminal here we run

Forge coverage what do you think we

get get this which you can see there's a

whole bunch of contracts that we need to

test this Oracle lib could probably use

its own test Suite even though it's

looking like a lot of it's tested we

probably should definitely test this

ourselves we need to write test for this

we probably want to test our uh our DSC

some more for sure so we should

definitely write some more tests I'm

going to leave that to you this little

little finger

here and then finally some smart

contract audit preparation so we talked

a little bit about what a smart contract

audit is and we haven't covered a whole

lot of security stuff yet we're going to

do that later in the course but a solid

place you can look is this audit

Readiness checklist from the nent XYZ

GitHub repo which has a lot of different

things that you should and keep in mind

when running your tests for those of you

looking to be really serious about

actually launching a protocol and really

having the security mindset that you

need as well be sure to get to this last

section in the course about intro to

security because this is where we're

going to give you a lot of that lower

level security stuff at least from a

smart contract developer perspective

we're going to give you all the basics

that you need to be aware of in order to

stay secure so we're not going to talk

about it too much in this one but it is

something that if we were to actually

launch this we would need to keep in

mind so I'll put a little soon Emoji

here for coming very

soon all right so with that all being

said we've done an absolute ton here

this is

1,000% a project you should push up to

your GitHub repo and this is 1,00% a

project that if you made it this far you

should be incredibly proud of yourself

this is the hardest most complicated

most advanced project in this course and

to be honest probably the most advanced

project you'll work on in almost all of

web 3 there's so much going on here we

learned about defi we learned about

advanced

state-of-the-art modern fuzzing

techniques we learned a tiny tiny bit

about security we used Oracles in a

safer way we wrote this crazy amazing

test Suite we wrote deploy scripts for

this we wrote We interacted with a

couple different libraries we learned

about this failon revert runs depths and

variance the only thing we didn't do was

write a proper read me which you 100% %

should write a proper readme and if you

want you can check out The Foundry defi

stablecoin readme to see how it actually

works of course even for me this was a

long difficult project for me to build

because there's just so much to think

about like I said this is a project that

I am planning on getting audited so what

you're going to see in this repo is

you're going to see kind of this main

branch which is what you're going to be

working on but I'm additionally going to

make a new branch called like audited or

post audit or something something like

that and if you want to follow and watch

this GitHub repo you can see the

progress and you can see the audit

reports that come out on here so that

you can be intimately familiar with this

codebase already because you wrote some

of the code and then also see as it

progresses through its security journey

and for those of you who are looking to

actually release production code you

definitely need to be at least aware of

how security works and the security

paths that your code should take but all

right

with all of this being said you know

what time it is it's time for you to get

a break you deserve it you should 100%

go take a lap push this code base up to

GitHub and actually clean it up a little

bit I'm going to be cleaning this up a

little bit before I push the rest of it

to this GitHub repo so you should clean

it up a little bit make it yours make it

the way that you want to make it maybe

even improve on it right we saw with the

invariant test that there is at least

one other glaring issue with this

protocol if the price of the assets

collapse too quickly our protocol

becomes insolvent so maybe you come up

with a method to fix it and then maybe

you launch your own stable coin why not

right in any case good luck to you take

that break we only have we're getting so

close we only have one two three more

lessons and these ones are actually

easier than the one we just did we're

going to learn about upgrades and

proxies we're going to learn about

governance and then we're going to do an

introduction to Smart contract security

these are much easier than everything

you've done so far so take the break

give yourself a pat on the back be

incredibly excited celebrate this win

this is a huge achievement getting this

far and I'll see you very soon three

more

left and as a bonus piece of content

here another one of the reasons that I

absolutely love the a protocol and the a

team is that they're just shipping

protocols and shipping amazing products

and features and services for the web3

community one of those protocols is

something called lens protocol which is

a decentralized social layer or a

decentralized social platform for

building social medias so to give us

some information about this we have the

head of devell for lens protocol and The

A Team Nat dbit to talk a little bit

more about lens hi my name is Nat dbit I

wanted to give you a quick introduction

to lens protocol and why it might be

interesting to you as a smart contractor

solidity engineer lens is the social

layer of web 3 it allows developers to

build social applications or to

implement social features into their

existing applications there are 4.9

billion people in the world today

already using social applications so

these types of apps provide a use case

that people already know understand and

value they also present a wide variety

of value propositions and opportunities

for developers to take advantage of and

build on and with web 3 features like

native payments ownership and

composability also provide a lot of

Primitives to build on that were not

available with traditional social

applications or infrastructure lens

allows developers to extend the core

smart contracts by building out their

own custom modules this would be similar

to as if Twitter Instagram or other

social applications allow developers to

send pull requests into their backends

and apis this this opens the door to a

lot of interesting and Powerful

functionality that we're seeing

developers integrate into their

applications build out new different

ideas but also integrate into other

parts of web 3 like defi in addition to

that you can call lend smart contracts

from other smart contracts so if you'd

like to build out something that is

composable with the web 3 social graph

lens is a great place to integrate if

you want to get started building on lens

check out the docs at docs. lens. XYZ

and be sure to check out how to deploy

the product call on your own so you can

check out the smart contract code and

play around with it and also look at how

to build out and create your own custom

modules thanks for checking this out

all right and welcome to lesson 13

boundary upgrades where we're going to

learn about upgradeable smart contracts

the pros and the cons now I've actually

done a couple different versions of this

type of video in the past so we're going

to go through an old video explaining

the concepts of this then we're going to

move over to remix and we're going to

explain an important subl lesson and

then we're going to go to our vs code

and we're actually going to do all of

this in Foundry upgradeable smart

contracts are something that I'm going

to go ahead and just say right out loud

we should deploy deoy as little as

possible we should not be defaulting to

upgradeable smart contracts it sounds

like a good idea in theory but we've

seen time and time again whenever a

protocol has a centralized control over

contracts issues Happen full stop so

when going through this course and when

learning about this keep this in mind

what are the downsides of upgradable

smart contracts and then you can begin

to ask questions have we seen examples

in real life where these downsides have

come to a fruition and I'll say right

now 100% the answer is yes so keep that

in mind when watching this and use this

knowledge to make yourself be an even

better smart contract Dev so let's

learn now I'm editing this video much

later after I filmed it hence why I have

a beard so I'll be jumping in from time

to time updating some of the sections

when deploying your smart contracts on

chain we all know that those smart

contracts are immutable or unchangeable

but what if I told you that they were

mutable well technically I wouldn't be

correct however smart contracts actually

can change all the time when people

transfer tokens when people stake in a

contract or really do any type of

functionality those 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 Dey deploy them however this can

be an issue if for example we want to

upgrade our smart contract or protocol

to do more things or we want to fix some

glaring bug or issue that we have now

even though we can't change the specific

code that's been deployed to an address

we can actually do a lot more than you

think and in this video we're going to

explain the different methodologies

behind upgrading your smart contracts

and then we're going to show you how to

do it with hard hat and open Zeppelin

huge shout out to a lot of open Zeppelin

and trailer bits articles that help me

put this video together uh and a number

of other sources as well links in the

description so let's get to it now at

first glance you might be thinking if

you can upgrade your smart contracts

then they're not really immutable then

and in a way you'd be right so when

explaining kind of the different

philosophies and patterns that we can

use here we do need to keep in mind the

philosophies and decentralization

implications that each one of these

patterns have as they do all have

different advantages and disadvantages

and yes some of the disadvantages here

are going to affect de centrality so we

need to keep that in mind and this is

why it's so important that before before

you go ahead and jump in and start

deploying upgradeable smart contracts

you understand the trade-offs so we're

going to talk about three different ways

to upgrade your smart contracts the

first one being the not really SLP

parameter ties way to upgrade your smart

contracts the social migration method

and then the method that you probably

have heard about which is proxies which

have a ton of subcategory like

metamorphic contracts transparent

upgradable proxies and Universal

upgradeable proxies so let's talk about

the not really upgrading method or the

parameterization method or whatever you

want to call it this is the simplest way

to think about upgrading your smart

contracts and it really isn't upgrading

our smart contracts because we can't

really change the logic of the smart

contract whatever logic that we've

written is there we also can't add new

storage or state variables so this is

really not really upgrading but it is

something to think about upgrades is

just parameterizing everything whatever

logic that we've deployed is there and

that's what we're interacting with this

function means we just have a whole

bunch of Setter functions and we can

update certain parameters like maybe we

have a reward parameter that gives out a

token at 1% every year or something like

that maybe we have a set of function

that says hey update that to 2% or

update that to 4% it's just a Setter

function that changes some variable now

the advantages here are obviously this

is really simple to implement the

disadvantage is that if you didn't think

of some logic or some functionality the

first time you deployed their smart

contract that's too bad you're stuck

with it you can't update the logic or

really update anything uh with the

parameterization AKA not really method

and the other thing you have to think

about is who the admins are who has

access to these Setter functions to

these updating functions if it's a

single person guess what you 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 AA Used before

you call a function you actually check

some contract Reg indry that is updated

as a parameter by somebody and you get

routed to that contract and you do your

call there again this really doesn't

allow us to have the full functionality

of upgrades here you can argue that this

registry is a mix of one of the later

versions but for all intents and

purposes this doesn't really give us

that flexibility that we want for our

upgrades but some people might even

think that upgrading your smart contract

is ruining the decentral and one of the

things that Mak 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

customers ation or any upgrade ability

you should deploy your contract and then

that's it trb bits 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 forgetting it and

not looking at it again now if I wanted

to upgrade a smart contract with this

philosophy in mind the philosophy that I

do want to keep my smart contracts

immutable we can instead use the social

migration method which I previously

called the Yeet method and now I think

it's less funny so we're just going to

stick with social migration the social

Yeet method or the migration method is

just when you deploy your new contract

not connected to the old contract in any

way and by social convention you tell

everybody hey hey this new contract this

new one that we just deployed yeah this

is the real one now and it's just by

Convention of people migrating and over

into using this new one that the upgrade

is done hence my slang name of social

Yeet because you Yeet the first one out

of the way and you move to the the

second

one I think I'm funny this has the

advantage of truly always saying hey

this is our am mutable smart contract

and this is our new one this is really

the truest definition of a mutable

because since you give it no way of

being upgraded in place then if somebody

calls that contract in 50,000 years in

the future it'll respond exactly the

same another huge disadvantage here is

that you have to have a totally new

contract address so if you're an erc20

token for example you have to go

convince all the exchanges to list your

new contract address as the actual

address keep in mind that when we do

this we do have to move the state of the

first one over to the second one so for

example if you're an ERC token moving to

a new version of that ERC token you do

have to have a way to take all those

mappings from the first contract and

move it to the second one obviously

there are ways to do this since

everything is on chain but if you have a

million transfer calls I don't want to

have to write the script that updates

everyone's balance and figures out what

everyone's balance is just so I can

migrate to my new version of the

contract so there is a ton of social

convention work here to do trailer bits

has actually written a fantastic blog on

upgrading from a V1 to a V2 or Etc with

this Yeet methodology and they give a

lot of steps for moving your storage and

your state variables over to the new

contract so Link in the description if

you want to read that now let's get to

our big ticket item so in order to have

a really robust upgrading mentality or

philosophy we need to have some type of

methodology or framework that can update

our state keep our contract address and

allow us to update any type of logic in

our smart contracts in an easy way which

leads us to our big ticket item the

proxies what's our big ticket

item proxies it's people proxies proxies

are the truest form of upgrades since a

user can keep interacting with the

protocols through these proxies and not

even notice that anything changed or

even got updated now these are also the

places where you can screw up the

easiest proxies use a lot of low-level

functionality and the main one being the

delegate call functionality delegate

call is a low-level function where the

code in the Target contract is executed

in the context of the calling contract

and message. sender and message. value

also don't change so you understand what

delegate call means now right great and

in English this means if I delegate call

a function in contract B from contract a

I will do contracts B's logic in

contract a so if contract B has a

function that says hey store this value

in a variable up top I'm going to store

that variable in contract a this is the

PowerHouse and this combined with the

fall Bank 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 contract and function

calls through the proxy contract and

then some type of admin the admin is the

one who's going to decide when to

upgrade and which contract to point to

in this scenario the other cool thing

about the proxy and delegate call is

that all my storage variabl are going to

be stored in the proxy contract and not

in the implementation contract this way

when I upgrade to a New Logic contract

all of my data will stay on the proxy

contract so whenever I want to update my

logic just point to a new implementation

contract if I want to add a new storage

variable or a new type of storage I just

add it in my logic contract and the

proxy contract will pick it up now using

proxies has a couple of gotas and we're

going to talk about the gachas and then

we're going to talk about the different

proxy contract methodologies because yes

there are many proxy contract

methodologies as well and this is why

tril bits 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 gotas are storage clashes and

function selector clashes now what does

this mean when we use delegate call

remember we do the logic of contract B

inside contract a so if contract B says

we need to set value to two we go ahead

and set value to two but these smart

contracts are actually kind of dumb we

actually set the value of whatever is in

the same 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 4 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 app this

leads to our first out of the three

implementations of the proxy contracts

this is called the transparent proxy

pattern in this methodology admins are

only allowed to call admin functions and

they can't call any functions in the

implementation contract and users can

only call functions in the

implementation contract and not any

admin contracts this way you can't ever

accidentally have one of the two

swapping and having a function selector

clash and you running into a big issue

where you call a function you probably

shouldn't have if you're an admin you're

calling ad functions if you're a user

you're calling implementation functions

so if you're an admin and you build some

crazy awesome di5 protocol you better

come up with a new wallet address

because you can't participate the second

type of proxy we're going to talk about

is the universal upgradeable proxy or

the

[Music]

UPS this version of upgradeable

contracts actually puts all the logic of

upgrading in the implementation itself

this way the solidity compiler will

actually kick out and say hey we got two

functions in here that have the same

function selector this is also

advantageous because we have one less

read that we have to do we no longer

have to check in the proxy contract if

someone is an admin or not this saves on

gas of course and the proxy is also a

little bit smaller because of this the

issue is that if you deploy an

implementation contract without any

upgradeable functionality you're stuck

and it's back to the Yeet method with

you in the last pattern or methodology

that we're going to talk about is the

diamond pattern which does a number of

things but one of the biggest things

that it does it actually allows for

multiple implementation contracts this

addresses a couple different issues for

example if your contract is so big and

it doesn't fit into the one contract

maximum size you can just have multiple

contracts through this multi-

implementation method it also allows you

to make more granular upgrades like you

don't have to always deploy and upgrade

your entire smart contract you can just

upgrade little pieces of it if you've

chunked them out all the proxies

mentioned here have some type of

ethereum improvement proposal and most

of them are in the draft phase and at

the end of this explain we will do a

demo of showing you how the delegate

call function works and the end of the

demo is right now so let's look at

delegate

call now we're going to learn about how

to actually build these proxies how to

build these upgradeable smart contracts

and to do this we first need to learn

about this delegate call function and

it's going to be really similar to the

call function which we learned much

earlier if you haven't seen that be sure

to go back to our hard at nfts we have a

su lesson in there about evm op codes

and coding and calling and will give you

all the context for delegate call like I

said in the explainer it's very similar

to call however the way that I think

about it is one contract says oh I

really like your function I'm going to

borrow it myself and we're going to be

looking at solidity by example I'll

leave a description in the GitHub and

all the code for this will be in the

GitHub associated with this lesson as

well now we have two contracts we have

this contract B that we're going to be

deploying on remix and it looks like a

real minimum istic real simple contract

we have a couple of storage variables

here and then we have a function that

updates our values we have a function

called set bars and updates are ENT

public num now as we learned before

whenever we have some type of contract

with storage variables they get stored

in in this storage data structure that's

index starting from zero right now our

uint public num is at index0 our senders

at index one our values at index 2 Etc

now we're going to deploy a contract a

now this contract is actually going to

use the delegate call function now in

contract a this is going to look a

little bit different but it's still

going to have this set bars functions

except it's going to make a delegate

call function call to our contract B the

difference here is we're doing contract.

delegate call what this call does is

something very similar to call normally

if we did contract. call on this

contract we would just call this we

would just be calling this function set

bars which would update contracts B's

storage but instead we're saying hey

call that set bars function and then

pass this as an input parameter but call

it in our contract call it on contract a

we're kind of borrowing a function for

our contract and so instead what we're

going to do is we're going to borrow

this set bars and run the set bars

function over here now the difference is

instead of num equals num the variables

could be named different than the

variables on contract a so instead of

num equals numb our contract is going to

say hey whatever is that storage of Zero

have that equal to whatever we pass as

an input parameter and if that's a

little bit confusing just stay with me

let's go ahead and let's see this in

remix so I'm going to copy paste this

code into remix here so we can kind of

test and see what this looks like again

there's a link to this in the GitHub

repo associated with this course feel

free to pause the video to grab this

link it's solidity hyphen byy

example.org delegate call or you can

just grab the code directly from Lesson

16 hardhead upgrades so let's compile

this code and let me show you what I

mean so I'm going to compile it and

we'll go to the Run tab and first let's

deploy this contract B we'll hit deploy

we now have a contract num sender and

value or all blank we'll update the

number to something like 777 we'll hit

set vars set vars will change the

storage variable num to 777 and then

we're changing the sender and the value

sender and value is zero now let's

deploy contract a so we'll scroll back

up contract a deploy of course we're on

the JavaScript VM now we have this

contract a with numb value incenter are

also all blank but when we call set bars

it's going to borrow this set bars

function from contract B and run it in

contract a you can almost think of it as

if we're copying set vars and pasting it

into our contract a just for one run and

then immediately deleting it again

that's what this delegate call function

does so when I call set vars I'm going

to pass it this contract address as an

input parameter so it knows to call this

contract set vars function when I pass

it the address and I pass 987 since

we're borrowing the function we're not

going to update this num on contract B

we're going to update the num on

contract a so when I hit set bars we see

num now has 987 we see sender and we see

value still being zero here because

again we're borrowing this function and

running it here now the way that this

works is it actually doesn't look at the

names of our storage variables it looks

at the storage slots so when we borrow

this function using delegate call so we

could have this these variables we named

anything instead of num we could call

this first value sender we could call

something else and then value we could

call woo or whatever you want here and

when we borrow this function using

delegate call instead of us grabbing the

actual names of the variables our

contract will swap out these variable

names with the storage slot so it says

oh okay well in contract B you're

accessing the numb variable which is

which is at storage slot zero so when we

borrow set bars in contract a with

delegate call we'll

say storage

slot Z is going to equal that underscore

num which for this contract storage slot

Z is first value so we'll say first

value equals uncore num something else

is going to be storage Slot 2 so it's

going to say okay storage slot two we're

going to update storage slot two to

mess. Sender okay value here is storage

slot three so whatever's in storage slot

three will update with message. value

like this so that's essentially what's

going on behind the scenes so let's go

ahead let's delete those and

redeploy deploy them so we'll deploy

contract B we'll deploy contract a right

now in B once again if we do 1 2 3 for

set bars we have 1 2 3 and then contract

a now even though these variables have

different names we could grab contract

B's address paste it in do 654 hit set

bars and first value is now 654 so

delegate call allows us to borrow

functions and then just transposes

whatever is in here to the storage

location equivalents and the other thing

that's interesting is even if you don't

have variables it'll still save to

storage slots so in contract a if we

didn't have any of those variable names

storage slots 0 1 and two would still

get updated now here's where things can

get really interesting let's delete our

contract a again and let's change the

type of our contract A's first value to

from a uent to a Boolean let's save that

and now let's deploy contract a

now when we call set vars on our

contract a it's still going to use the

set vars function of contract B which

takes a uint and assigns the first

storage slot that number we pass it but

our first storage slot is now a Boolean

so what do you think's going to happen

now well let's try it out let's copy

contract B's address paste it in here

we'll pass we'll do

222 as our input parameter we'll hit set

bars our transaction actually does go

through and now when we look at first

value it says true huh that's really

weird what if we change set bars to zero

and hit set bars and now first value is

false in storage here when we add a

number with set vars it's going through

because it's just setting the storage

slot of the Boolean to a number and when

solidity reads it it goes oh well first

value is a Boolean so if it's anything

other than zero it's going to be true so

this is how you can actually get some

really weird results if your typings are

different or if your storage varials are

different what if we made this an

address so this is where working with

delegate call can get really weird and

really tricky really

fast all right now with all this being

said let's turn up the heat and let me

show you a small proxy a minimal proxy

example that shows how a contract can be

used as a singular address but the

underlying code can actually change and

all the code we're going to be working

with once again in the hard Hut upgrades

FCC subl lesson small proxy.com

if you want to just move on to learning

how to actually build these proxies

without really understanding what's

going on behind the scenes however it is

still really powerful if you do

understand what's going on behind the

scenes so I have this minimalistic

starting position right here I have

small proxy is proxy and I'm importing

this proxy doou thing from open Zeppelin

open Zeppelin has this minimalistic

proxy contract that we can use to

actually start working with this

delegate call now this contract uses a

lot of assembly or what's something

called Ule and it's an intermediate

language that can be compiled to bite

code for different backends it's a sort

of inline assembly inside solidity and

allows you to write really really lowl

code close to the op codes now we're not

going to go over Ule but I'll leave some

links to the Ule documentation if you

want to learn more even if you're a

really Advanced user you really want to

try to use as little Ule as possible

because since it is so much lower level

it is much easier to screw things up

however like I said for this example we

are going to be using a little bit of

Ule now in this proy that we're going to

be doing we have this delegate function

which inside this inline assembly which

is Ule it does a whole lot of really

lowlevel stuff but the main thing that

it does is it goes ahead and it does

this delegate call functionality if we

look here we can see it's using a

fallback function and a receive function

so whatever it receives a function it

doesn't recognize it'll call fallback

and fallback calls are delegate function

so anytime a proxy contract receives

data for a function it doesn't

recognizes it sends it over to some

implementation to some implementation

contract where it will call it with

delegate call in our minimalistic

example here we have a function called

set implementation which will change

where those delegate calls are going to

be sending this could be equivalent to

like upgrading your smart contract and

then we have implementation here to read

where that implementation contract is

now to work with proxies we really don't

want to have anything in storage cuz if

we do delegate call and that delegate

call changes some storage we're going to

screw up our contract's storage the one

caveat though to this we do still need

to store that implementation's address

somewhere so we can call it so EIP 1976

is called the standard proxy storage

slot which is an ethereum improvement

proposal for having certain storage

slots specifically used for Pro

and in our minimalistic example here we

set by 32 private constant

implementation slot to that location in

storage and we'll say okay whatever is

at this storage slot is going to be the

location of the implementation address

so the way our proxy is going to work is

any contract that calls this proxy

contract if it's not this set

implementation function it's going to

pass it over to whatever is inside the

implementation slot address that's what

we're going to build here so we have

this small proxy is proxy and we'll

create a real minimalistic contract so

we'll say contract

implmentation a and we'll just give it a

un 256 public

value and then function set value un 256

new value public we'll say value

equals new value and so this is going to

be our implementation so now anytime

somebody calls small proxy our small

proxy contract it's going to delegate

call it it over to our

implementation a and then save the

storage in our small proxy address so

we're going to call our small proxy with

the data to use this set value function

selector so let's make it a little

easier just to figure out how to get

that data by creating a new helper

function we'll do

function get data to transact

and we can get the data using the ai.

encode with signature that we learned in

an earlier lesson so function get data

to transact we'll pass it to un 256

number to update so we'll give this the

number we want to call a new value we'll

have this be a public pure that's going

to return a

bytes memory and we'll just say return

ai.

encode with

signature set value uint

256 comma number to

update so you'll remember this from our

call anything section and if you don't

remember how to do that remember to

refer back to our nft section to learn

how to call anything and use ABI do

encode ai. encode with it signature and

call anything with its raw bytes we're

going to get the data to transact and we

know that when we call implementation a

from our small proxy we're going to

update our small proxy storage so we'll

create a little function in solidity

just to read our storage in small proxy

so we're going to say function read

storage this will just be a public view

we'll do

returns returns you went 256 value at

storage sloted zero and we are going to

use a little bit of assembly here since

we are doing all this low-level stuff

and we're going to call the SL load op

code to read the value at storage slot

0o we'll say value at storage slot 0o

and we're going to set it and then in

assembly this is how we set things we're

going to set it equal to SL load of

storage slot zero and then it will

return this value here so we're reading

directly from Storage oops and then we

need a little parentheses here sorry so

now so let's go ahead and deploy our

small proxy and let's deploy our

implementation a now our small proxy has

a function called set implementation so

we're saying okay anytime we call this

proxy contract we're going to delegate

call the functions over to here so we're

going to grab implementations A's

address paste it into set implementation

777 so this is the data of set value un

256 with that number to update and coded

in it so if we call our small proxy with

this data our proxy contract is going to

go oh okay this is a function uh I don't

I don't see that function here we're

going to call our fallback right which

again is coming from open Zeppelin and

our fallback is going to do this

delegate which is this lowlevel stuff

but it's basically just doing a delegate

call we're going to call our fallback

function and then we're going to get the

function in the implementation a we're

going to borrow this function and we're

going to use it on our on ourself so if

I copy this the implementation has been

set to being this address down here so

all the logic is going to be down here

so when I go ahead and I grab this I

paste it into call data and I hit

transact looks like it went successfully

went through if I read storage now we

see that it is indeed

777 which is incredibly exciting now

this is incredibly beneficial because

now let's say we want to go and update

our code right we don't like contract

implementation anymore so let's go ahead

copy contract implementation a and we'll

make a new one called implementation B

now let's say whenever somebody calls

set value we do value equals new Value

Plus 1 or plus two let's go ahead let's

save this let's compile this and let's

deploy implementation B we'll grab

implementation B's contract address

we'll call it on set implementation in

our proxy and essentially we have now

upgraded from implementation a to

implementation B now if we use this same

data here we're still going to call set

value with 777 but instead we're now

delegate calling to implementation b

instead of implementation a so if I call

if I put this data into the lowle call

data and I hit transa it looks like it

went through now I read storage and now

is

779 since doing value equals new Value

Plus two so this is a minimalistic

example of how upgrading actually works

now now this is incredibly beneficial

because we can always just tell people

hey make all your function calls to

small proxy and you'll be good to go but

like I said before this also means that

the developers of this protocol can

essentially change the underlying logic

at any time this is why it is so

important to be sure to read contracts

and check to see who has the developer

keys and if a contract can be updated if

a contract can be updated and a single

person can update it well guess what you

have a single centralized point of

failure and technically the contract

isn't even decentralized now something

else I was talking about in the video is

function clashes function selector

clashes right now whenever we call set

implementation the proxy function set

implementation gets called because we

don't trigger the fallback because we

can see the function is here however if

I have a function called set

implementation in our implementation

this one can never be called whenever we

send a function signature of set

implementation it's always going to call

the one on the proxy this is this is

where the transparent proxy that we're

going to be working with can help us out

here and the up Universal upgradeable

proxy can help us too and I'm not going

to go too much deeper into these now but

we've left some links in the GitHub

repository to teach you more about these

selector clashes and how those two proxy

patterns that I just mentioned the

transparent and Universal upgradeable

can get around these if you're confused

by anything in here go into this

discussions thread and make a new

discussion about proxies make a new

discussion about the assembly about the

Ule set implementation this is a great

time to connect with other people taking

the course and ask questions here cuz I

know that this is a really Advanced

section and requires you having gone

through a lot of those subl lessons that

we've gone before and if it takes you a

couple times of playing around with

solidity and playing around with remix I

definitely recommend you do so this is a

section where seeing really is believing

and I want you to jump into remix and I

want you to test this and I want you to

play around with this and see what you

can break and Fiddle with

all right so now that we've learned all

about this delegate call function and

what it can do and the power of it let's

actually put it to use let's actually

build an upgradeable contract example so

we can really see this power so let's go

ahead and let's start doing this of

course all the code that we're going to

be going over with is available in the

GitHub repo associated with this course

if you want to follow along so let's go

ahead make a new directory boundary

upgrades

f23 let's code boundary upgrades f23 or

file open folder you know the drill now

I know in that video we talked a lot

about this transparent proxy pattern

versus the uup UPS we're actually going

to be teaching the U PS Pro in The UU PS

proxy the upgrade is handled by the

implementation and can eventually be

removed and this is incredibly important

especially if we want to heed my warning

I made at the beginning where we want to

really do this as little as possible and

this is kind of a crutch to get started

and we've seen issues where if you have

upgradeability and you have a

centralized entity that can upgrade and

change your contracts those are often

exploited so the U UPS proxy allows us

to eventually remove the upgradeability

so that the code is truly immutable and

also U ups proxies are technically a

little bit cheaper to deploy you can

read more about the differences between

the two proxy types in the documentation

for open Zeppelin and additionally if

you go to the contract wizard in open

Zeppelin most of these types in here

have a upgradeability option with

ufs that we could even open in remix and

see exactly what some of these might

look like so we're going to be going

through that with our our own example

here so we're going to go ahead we're in

our folder we're going to do Forge

knit of course and we're going to go and

delete these once again bye goodbye

goodbye delete with the trash I held

down command so I can select all three

and let's create a very minimal contract

that we're going to actually upgrade so

we're going to say a box V1 do soul and

this is going to be what we're going to

upgrade so in this box V1 we're going to

do

spdx

license identify MIT you know the

drill pragma solidity 0.8 r with a

little carrot

here contract box V1 like this cool now

so since we're using the U UPS proxy

we're actually going to need to add all

of the proxy upgradeability into this

contract as well so we can actually

borrow from open Zeppelin kind of like

what we're seeing here because they have

all of these contracts already created

for us but let's actually just write out

what our what we'd want our box to do

first and then we'll go ahead and do

that so we'll say a un 256 internal

value or number a little bit less

confusing we'll have a function get

number public view or better yet

external external view returns un

256 turn

number all of this is something you all

get because you did the stable coin

video which was a monster of a project

version external your returns you

256 return one and that's it this is all

our box is going to do now let's copy

this box let's go to our source we'll

create a box v2. Soul paste all that in

here and let's change this a little bit

let's have the version return two get

number will still return number but

let's add a function function

set number un

256 number this be external null like

this but so here's oh and this rename

this to box V2 Okay cool so now we have

our box V1 we're going to deploy box V1

and and then at the contract address of

box V1 we're going to upgrade it to box

V2 now remember though if we upgraded it

changed some storage variables we would

mess it up right so if you go to the op

zeppin documentation let's actually

reopen this back up in remix here we can

see kind of what's going on here so this

token example that they have they say

it's initializable upgradeable ownable

and uu PS upgradeable they say it's all

this stuff so for us we're going to go

ahead and we're going to install this

open Zeppelin contracts upgradeable

package and this is actually at a

different open Zeppelin repo we look up

open Zeppelin contracts upgrade

GitHub there's this open Zeppelin slopen

Zeppelin contracts upgradable repository

that we can use and this is the one that

we're going to want to install so we're

going to copy this like that Forge

install this this D- no-

commit all right great we've installed

it now we can start using these

contracts upgradable code in here let's

just go in here do a rem mappings equals

we'll say at open Zeppelin SLC

contracts

upgrade a

equals lib

slop dein and let's do a toggle word

wrap Zeppelin contracts gradable SLC

contracts hopefully that looks right

let's go to lib opens up a contracts

upgradable yep that looks right okay

cool so now we can start using this so

in this remix example it can be a little

bit confusing because there's a lot of

imports going on right so let's kind of

break this down so the first thing that

we're going to need need is going to be

this U UPS upgradable contract and I'm

just going to copy this line feel free

to copy this line as well or you know

write it out yourself and I'm going to

toggle the word wrap here of course

we're going to do named Imports because

we're good Engineers uh what did I mess

up oh I don't need this versioning okay

cool and if we control click into this

or we command click into this or we just

open this we can see exactly what is in

this upgradeable code here we have this

uyu PS upgradable contract it's

initializable it's some proxy stuff you

know yada yada yada we scroll down got

some

modifiers it has this function upgrade

to address new implementation upgrade to

and call and it has this Gap at the

bottom so let's talk about these so this

upgrade 2 function this is the function

that gets called when we want to upgrade

our box so we're going to say our box is

uus U UPS upgradeable and then it's

going to say hey uh should be marked

abstract because we don't have all of

the functions defined in here and this

contract is actually known as an

abstract contract abstract contracts

have some functions defined and some

functions undefined and they expect

their child classes to implement those

functions so for example at the bottom

here we have this authorized upgrade

function which isn't defined so an

abstract contact basically says hey you

better Define this authorized upgrade

function because I'm not going to do it

you need to do this and this can be

helpful for a lot of reasons right for

example let's say you want to make sure

to not forget to add some function so

this is something that we're going to

need to Define these are how we're going

to actually do the upgrades we see that

this is you know obviously the function

that we're going to have to Define so we

can add authorization parameters in here

such as who can actually do the

authorization so if I toggle the word

wrap we can see function that should

revert when message. sender is not

authorized to upgrade the contract so

for example if you wanted your proxy to

be owned by a dow you would update this

to be ownable or only owner or something

like that but then they call this

upgrade to and call U UPS which if we

control click into or we just go to

where it's defined uh we toggle the word

wrap here we can see this performs the

implementation upgrade with Security

checks for ups proxies and additional

setup so if we scroll into here this is

the code that's actually doing the

upgrade and it's really low level right

so we're call this function set

implementation which now routes all

contract calls via delegate call to this

new implementation address that we set

and then it does a couple of checks in

here and then it calls upgrade to and

call which which calls upgrade two which

call set up

implementation which mainly just sets

the implementation slot which basically

like I was saying before it says okay

all contracts are going to be routed to

this address now right but if we go all

the way back all the way back that's

kind of the long of what this upgrade 2

is going to do right so it's going to

change where we route all of our

delegate calls and then if we have any

data we want to send it'll call this as

well the data is obviously going to be

none uh if you just call upgrade to

anyways I'm getting kind of in the weeds

here right this is the function that it

has set up to to do the proxy stuff we

showed before right this changes the

implementation address so we obviously

need this we also need to implement our

own authorized upgrade function so we

can just go ahead and copy this and in

here we'll paste it in here and for us

uh we need to make this override instead

of virtual I'm just going to leave it

blank because I don't want any I don't

really care I don't want any

authorization stuff in here right but

this is where I put like you know

require or excuse me if you know

message. sender does not equal owner you

know revert right right but for us I

don't really care so I'm just going to

leave it blank right and so this is

going to say anybody can upgrade this so

this is why this is going to be the most

important one right this U UPS

upgradable is doing all that proxy

upgrade stuff all right cool so what

else now you'll also notice here at the

bottom there is this Gap thing now you

can read the docs here this empty

reserve space is put in place to allow

future versions to add new variables

without shifting down storage in The

Inheritance chain what what what what

the heck what are you talking about

storage gaps the reason these proxies

work is that they point to the slot

number instead of the name of variables

so if I were to upgrade from box V one

to box V 2 and I put in another other

number here guess what if I did this

upgrade whatever number number was in

box V one is now set to other number

instead of number this is because

proxy's point to storage slots they

don't point to variable names they point

to storage slots if we upgrade to V2

other number is now in storage slot zero

whereas number was in storage slot zero

over here right so what is the best

practice to do is to have this Gap at

the bottom so a u into 256 you can put

really whatever you want here which

basically just says heyy we're going to

save 50 storage slots in storage for

adding new variables in the future you

could have this be you know 100 you know

whatever whatever amount you want right

and this is just so that in the future

if you need to add more storage slots

you don't collide with other places that

storage is already being reserved so

it's really important that they have

this Gap especially for U UPS if this

doesn't make sense definitely 100% be

asking questions about it and you'll see

a lot of people will ma even manually

add their own gaps sometimes so

sometimes you'll even see somebody go

you know like Gap two or whatever they

want right so that they have additional

gaps whatever they want to do cool so

this is why we need

this now right like this we could ship

this code and this would be upgradeable

now of course box V2 is not upgradeable

um but box V one would be upgradeable so

why

is remix adding all this other stuff

what is initializable well let's copy

this and let's paste it in and you can

also see all this weird initialized

stuff what what what is going on with

that well let's let's add this in and of

course we're going to do a named proxy

if you want to write this out yourself

feel free uh excuse me we're going to

remove this because we did not add the

version in here uh initializable so what

is this why is open Zeppelin telling me

I got do I got to do this initializable

thing and it's doing all this weird

initialized stuff so let's go into

initializable oh and if it doesn't let

you do that let's open up our file

explorer we'll look for initializable

Doo and let's see let's read this so if

you want to pause and you want to read

this I'm even going to toggle the word

wrap if you want to pause and you want

to read this feel free to do that but

the main thing we know is this piece

here since proxy contracts do not make

use of a Constructor it's common to move

Constructor logic to an external

initializer function might be thinking

wait wait wait wait what they don't use

a Constructor remember storage is stored

in the proxy not the

implementation so we have proxy which

will direct I'll call to the

implementation but it's like borrowing

the implementation functions right so

all the storage is happening over here

if the implementation has a Constructor

and it sets number to one right the

proxy will have number still set to zero

cuz the when you deploy a contract The

Constructor gets called from the

implementation so proxy contracts or

contracts that are meant to be used via

proxy don't use the Constructor so what

you need to do is then with a proxy you

need to First you need to deploy

implementation then you need to call

some initializer

function now the initializer function is

going to be essentially your Constructor

except for it's going to be called on

the proxy so that's kind of the

difference if that doesn't make sense

please ask questions about it because

it's really important so Constructors

are not used in proxy contracts so what

a lot of upgradable contracts do is they

first they call this disable

initializers function in Constructors

like you see here and I'm actually going

to copy this paste it into my box View

one like this and then often you'll see

this comment I'm going to paste this

over here because sometimes different

lters will say hey you're using a

Constructor in a upgradeable contract

you shouldn't do that so we just say hey

like let it happen right what this

disable initializers function does is it

says hey don't let any initialization

happen so if we go see this we say

require that you're not initializing

right you can't call any initializer

functions so you could just as easily

just just do this right they're kind of

the same but this is much more of verose

right this is making sure hey don't do

any initializers Constructor don't do

anything so this and this are almost the

same but this is more verbose as you

know verbose is better but let's say we

do want a Constructor what we would do

is we' add an initializer so we do

something like function

initialize public initializer

initi

initializer and of course we'd say our

boxy one is initializable public

initializer like this and we would add

whatever we want to initialize and then

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

deploy the contract and then we're going

to have the proxy immediately call our

initialized function instead of doing

this Constructor instead of the

implementation having the storage we

want the proxy to have the storage

typically you'll see initializer

functions have two underscores like this

so if we want our box V1 to have an

owner right we can't set storage we

can't do like owner equals message.

sender in the Constructor like we

normally do with a ownable contract

instead we need to put that in the

initializer function so what a lot of

people will do is they'll add double

underscore like ownable uncore in it

like let's say we did want this to be

upgrade uh ownable and actually let's go

ahead and add that right now we're going

to add this ownable upgradeable I'm

going to paste it

in remove that ownable from like this

comma I know I kind of was quick but I

uh I know you all are Advanced enough to

kind of know what I just did here I

Factor this a little bit so that's a

named import remove the version and now

we're doing this ownable upgradable

instead of ownable I'll explain what

that means in a second oh and this

actually

goes here a note if you see this

linearization of inheritance graph

impossible this means that we're trying

to inherit stuff in the wrong order so

we'll just do this oh is that the right

order no that's still the wrong order

that the right order cool that's the

right order okay so what what you'll see

is these upgradeable initializable

functions will be prepended with double

underscores right and so what this is

doing is it's sets the owner it's

setting the owner to message. sender and

if I command click into this or command

click into this we look up ownable andit

we see it does this ownable andit

Unchained all it's doing is calling

transfer ownership right that's it this

is essentially the same as setting owner

equals message. sender right but we're

just just prepending with the double

underscore to say hey this is an

initializer function treated as such

right it should only be called in this

initialize section additionally most of

the time you'll see this initializer

function which doesn't do anything but

it's best practice to have this in here

to say hey this is a u UPS upgradeable

contract we're going to treat it as such

okay so you'll see this in here a lot

too but I know I kind of went through

this a little bit quickly but let's just

do a quick recap of what we learned we

can't use Constructors with our proxies

a Constructor adds storage to the

implementation and if we have a proxy

pointing to an implementation the

implementation would have the storage of

where the owner is and we need the proxy

to have the storage of where the owner

is so we need to call initialize through

the proxy not through the implementation

the initializer function is essentially

a Constructor for proxies you can almost

think of it like that we want to preen

them with this double underscore to know

that they're

initializers and we don't want any

initializers to run in the Constructor

and we only want them to run once you'll

also see this initializer modifier which

basically just says hey you can only

initialize one time right a contract can

only be initialized once otherwise it'll

error great and that's pretty much going

to be our box so now we made this

ownable so since this is ownable down

here in our authorized upgrade we could

add an only owner modifier in here so

that only the owner could upgrade it if

we wanted to but we're not going to add

that but I wanted to add this ownable in

it here just to show you hey like so

this is what you do instead of working

with Constructors so that's our box V

one let's fix our box V two so our box V

two we're going to do pretty much the

same thing so we're going to grab all

these paste it in here I'm going to

toggle the word wrap we're going to make

this

initializable uh ownable

upgradeable and UPS

upgradable is like this we're going to

need to add authorized upgrade which

we're going to keep blank but if you

want to play with this you can obviously

implement this we're going to want to

add a Constructor and an initializer so

we're going to copy both of these and

just paste it right in here a

Constructor which disables Constructors

and then an initializer which is going

to be really what we want and that's

pretty much it that's the only changes

that we need to make now we can make

make this even smaller right we could

say okay cool we don't care about

upgrades we don't care about

initializing and we just say goodbye

this doesn't need initializer this

doesn't need any of that stuff and we

could even delete all this if we wanted

and now it's just UPS upgradeable right

without any initializer and without any

Constructors and we could do the same

thing with box VI one but I just wanted

to demo what it look would look like if

you did want a Constructor but now that

we've done all this work

let's actually show you this in action

so we're going to deploy box V1 we're

going to get an address we're going to

use that proxy address to make sure that

these functions work we're going to then

deploy box V2 we're going to point our

proxy to box V2 which will essentially

mean we upgraded our contract and it's

all going to be from the same address so

let's do this we're going to make a

little two scripts we're going to make

one called deploy box. s soul and a new

one called up upgrade box. s.o so we're

going to deploy the box and then we're

going to upgrade it so let's deploy it

spdx you know the drill

license ragma solidity

0.818 contract deploy box is script

import script from Forge STD script.

so we're going to need to imple

import box V1 from

docbox V1 doso function run

external external returns I'm going to

I'm going to return address and you'll

see why in a bit returns address address

proxy equals deploy box turn proxy and

I'm going to create a deploy box

function function deploy box so this is

a little bit different this will be a

public returns

address and what we're going to do is

say box V1 box equals new box V1 this is

going to be our what our implementation

this is going to be our logic right this

is where our proxy is going to point to

delegate call right to borrow those

functions now we're going to need to get

a proxy on top of this the pro proxy

that we're going to use is the ERC

1967 proxy and we can learn more about

this proxy in the open Zeppelin

documentation we can learn more about

this at the EIP for ERC

1976 whatever you want to do but it's

going to be this proxy that we're going

to use to point to our implementation

right to point to our box V one which

has all this upgradable logic in it so

we're going to import that we're going

to import ERC

1967 proxy from and this is actually

just a regular open Zeppelin contract so

we're going to do Forge install open

Zeppelin slash open Zeppelin contracts

this is just a regular one contracts

oops uh D- no- commit we're going to go

to our boundary. toml and this is a

remapping

comma open Zeppelin SLC contracts equals

lib slopen

Zeppelin open Zeppelin Dash contracts I

think that's what it is right lib open

Zeppelin contracts and opens up on

contracts upgradeable okay opens up on

contracts SLC contracts like this and oh

Port this from

atop Zeppelin contracts proxy RC

1967 uh like this so this is the proxy

type we're using now we're going to say

ERC 1967 proxy equals new erc1

1967 proxy and if we command click onto

this or control click or just look at

this this does have a Constructor we

pass in the logic and the data so we

basically say hey proxy this address is

going to be the implementation the logic

that you're going to use and then any

data you want to pass to the initializer

right if we look at upgrade to and call

call upgrade two and then if there's any

initializers call that afterwards right

uh we're not going to have any

initializer stuff so we're not going to

do that but we're just going to say

address box because we just deploy this

box no data this is where like I said

this is where we' put the initial add

stuff we wanted but then we're just

going to say return and address proxy so

cool and let's just make sure stuff is

working Forge

build or at least we're going to make

sure code is compiling and source file

that's not specified required compile

version that's cuz we haven't

implemented that that's fine cool this

looks good and we're going to write some

tests to show you this actually working

in a little bit

but cool so we have a deploy box let's

actually write an upgrade box script now

and then we'll write a text

to show both of them spdx

license identifier MIT pragma solidity

0.818 contract upgrade box is script

import script from forg STD script. Soul

script scripts cool function run

external

returns address

I'm going to have this

external oops I'm going to have this use

the most recently

deployed box so to do that we're going

to actually

install Forge

install chain Excel org D boundary

devops D- no- commit like I said there

might be a better devops tool than this

you can find the recommended devops tool

the GitHub repo associated with this

recommended tool is going to be Foundry

devops so great so that's what we're

going to use I've worked with this one

before so we're going to say address

most recently deployed equals devops

tools. getet most

recently deployed going to be deep me

and this is where we're going to get the

ERC

1976 proxy let me oops toggle the word

WP here move this down on block dochain

ID oh let's import that as well import

from oh oh and I got to go to The

Foundry

doo do a little bit from libf Foundry

devops

SRC devops tools. s looks good get most

recently I spelled that wrong get most

recent deployment so we're going to get

the most recently deployed

proxy first and you'll see Y in a second

and first we're going to actually deploy

box V2 so we're going to import box V2

from SRC boox v2. Soul oops s so we're

going to do a little vm. start

broadcast did we do that in box deploy

box oh we should do that here back in

the deploy box we're going to do vm.

start broadcast

and then a stop

broadcast that okay bm. St broadcast in

the upgrade box we're going to say box

V2 new box equals new box V2 bm. stop

broadcast and then we're going to say

address proxy equals upgrade box and I'm

modularizing this for our test cases but

we're going to say we're going to create

a new function called upgrade box where

we're going to pass pass in the proxy

address right this is the proxy address

and then the address of our new box and

then we're going to say return proxy so

we're going to create this function

upgrade box which has our previous proxy

and then the address of our new box for

us to do so we're going to say function

upgrade box address proxy address uh

address new box this be a public returns

address do vm. start broadcast so okay

so we're going to call upgrade box we

have the proxy address and we want to

call upgrade on this right since this is

just an address we can't call upgrade on

an address we're going to need to call

upgrade on using the ABI of box V1 right

so let's import that as well import box

V1 from Sr cbox V1 doou we're going to

say box V1 proxy equals box V1 of the

proxy address like this and what we're

going to do is now that we've given our

proxy address box V1 ABI we can now just

call proxy do upgrade 2 since box V1 is

U UPS upgradeable means it has access to

this

function address new box this we're

going to upgrade it and we're just do

vm. stop

broadcast like this we could also

optionally wrap this in box V2 or we

could you know do a direct function call

whatever we want to do now we'll just

return

address

proxy and that's it right so what is

this doing when we actually upgrade well

we deploy Box 2

implementation we are calling this

upgrade box function and what we're

doing is all we're doing is we're saying

hey point the proxy to this new place

that's it we're saying proxy contract

now points to this new address that's it

don't believe me all right let's write a

test so new file and we're going to

write some crappy tests here we're just

going to do the whole Suite just to show

you the power deploy and upgrade test.

T.O you know the drill

spdx license identifier MIT

contract deploy and upgrade test is test

import test from Forge STD test. Soul

fragma solidity

0.818 we got to do a whole bunch more

Imports we're going to need to import

deploy box from do script SL deploy boox

dos. sole import upgrade box you know

this is what we're actually testing from

do/ script D upgrade box. s.o readying

to import box V1 from yep thank you

GitHub co-pilot and box V2 we're

probably going to need to import more

stuff but it's fine function set up what

do we want to set up here well let's get

a deploy box public deployer upgrade box

public

upgrader we'll do an address public

owner equals make

addr owner we're going to say deployer

equals new deploy box upgrader upgrader

equals new upgrade box okay cool and we

probably should write a whole bunch of

tests but for this video I'm just going

to write

one say box V one public box V1 and

we'll say box V one equals deployer do

run we're going to have to wrap box V1

like this boom so we have our box V1 it

gets deployed our deployer run is a

deploy BLX run Returns the address of

the proxy not the address of the Box V1

right Returns the address of the proxy

not the box vi1 so we can even call this

to make it more clear box vi1 public

proxy since this is actually a proxy

address actually let's do this even

better address public proxy and this is

why before we working with addresses

because it can be kind of confusing to

know what it is the proxy right the the

proxy and it right now points to box V1

cool hopefully that's more clear so now

we'll do a function test

upgrades like this and we'll just test

the whole darn system so we have the box

we have the proxy address point to box

V1 now in our upgrade box in our run we

went ahead and did all this but for now

let's just use this upgrade box

functionality because so we can so I can

show you a little bit more granularly

what's actually happening right so test

upgrade let's let's deploy our own box

V2 we do it in run we could 100% do it

in run but I want to do it myself so I'm

going to say box V2 equals box V2 or Box

2 equals new box V2 vm.

prank box 32 box two now I'm going to

say address proxy equals upgrader do

upgrade box proxy which is just an

address address of box two so our

upgrade box upgrade box here all it's

doing is saying okay cool get the proxy

for box V1 and now point it to V2 so

we're calling that in our test here and

now we could do unit 256 expected value

equals 2 and we could say assert equal

oh actually we don't we shouldn't even

set this let's not even set this right

so this address is going to be the same

we're never resetting this address we're

being very clear about that boom proxy

deployed here boom we're never even

we're never Chang the address so it's

always going to be this address now we

can do though is we can Sayer equal

expected value is box V2 on the proxy

address. version if this works this

means that on the proxy address which

originally pointed to boxy one it's now

pointing to box box V2 we could also do

box V2 proxy dot set value or what do we

call it box V2 set number set number

number we say like seven or something

right and we could say assert equal

7A comma box V2 roxy. getet number like

this and we could even add another

function test proxy starts at as box V1

right public we could say vm. expect

revert with calling th this function

because set number doesn't exist on box

V1 so we try calling set number on the

proxy it should fail so let's run these

one at a time Forge test- M this should

indeed

revert great and then let's test this

and this should indeed upgrade Forge

test t-m test upgrades oh we failed

let's get some granular detail here- VB

left is seven right is zero set number

get number oops we forgot to actually

add set number in here so let's do

number equals underscore number whoops

now let's run that

test and boom it passes we have

successfully upgraded our box this is

very exciting

so let wrap this up I know we went

through this really quickly I want you

to ask a ton of questions about this

process ton of questions about this ask

them in the discussion ask them on

Twitter ask them to your buddies

whatever you want to do we just learned

about upgrades like I said I highly

recommend you do not default to this and

you do not let protocols that have

upgradeable smart contracts keep this

centralization Vector because it is if

you have an upgradeable smart contract

that means that a group could change the

logic of that code at some point or be

coerced to change the logic Etc but this

is an incredibly powerful primitive to

know about especially delegate call

we're almost done push this up to GitHub

add this to your portfolio take a break

congratulations

I'm going to go ahead and deploy this to

a test now just to show you what it will

look like on ether scan feel free to

just watch sit back relax you've done a

ton of amazing work to make my life

easier I'm going to borrow a make file

and just kind of tweak it let's change

let's just delete all this stuff deploy

it's going to be deploy box box upgrade

P script upgrade box

box make deploy args equal Das Das

Network

aoia all right so I ran the deploy we

deployed two contracts let's grab this

one firsta ether scan let me show you

what this looks like looks like this one

didn't quite verify correctly I could go

ahead and manually verify it if I wanted

but let's look at the second one looks

like neither one of these actually

verified correctly but that's fine I can

go to the my broadcast see which one is

which we can go to both these runs let's

see the first one okay we did create box

and so this is going to be the address

of box V1 so I copy this paste it in

here I can go ahead and verify this

manually later but I know that this is

my box V one we'll go back to broadcast

click this one scroll down uh this one

doesn't have a contract name but I know

that this one is going to be my proxy

address so I go to your browser let's

open keep them both up paste it in here

this one didn't get verified correctly

either but that's okay so this one's our

box this one's our proxy and this is the

one that's more important right this

proxy is pointing to this implementation

okay now we're going to call our upgrade

we're just doing make deploy make

upgrade like this oh and I

needl since I'm using Foundry devops I

need ffi equals true remember only do

that if you are confident about what

you're running do make

upgrade so this actually is a bit of a

bug with this script that I just found

out I do need to update my run latest to

ERC

1967 proxy I either need to upgrade my

script to look for null or I need to

upgrade Foundry to add this for the

proxy name so I'm just going to manually

add this in we're going to hit clear

we're going to rerun it look like that

is a bit of a bug sorry about that but

now that it knows that this is the ERC

1967 proxy we're actually running this

script now to upgrade the box and the

first thing that we're going to do is

we're going to deploy our box V2 which

for some reason is actually verifying

looks like something was just wrong with

the first time I did it but all good if

I paste this in we now have a box V2

being created and it looks like it's

trying to verify right now oh and looks

this one actually did verify so if we

refresh this one so it looks like our

box V2 is here we place this in it looks

like this one did actually verify which

is great box Fe 2 now if we go back to

our proxy we hit refresh we can see we

called an upgrade two on this contract

now whenever we call functions on this

it'll actually point to box V2 right so

we can even grab the contract address

we'll use a little cast send paste this

in here we'll call get number like this

or actually excuse me cast call cast

call and of course Das Das RPC URL seia

RPC URL this we can see that it starts

off at zero that number starts off as

zero then we can call well we can do

send instead set number takes a u into

256 we'll set the number

277 RPC D- private key private key

remember you're going to need to do

source. to do this we'll send a

transaction to actually update update

this and we're calling the proxy right

we're not calling this box V2 address

we're calling it right on the proxy then

if I go up up and we do call again we're

now going to get 4D for the binary and

if we do cast

d-2 base paste DEC for decimal we

convert this hex to decimal and we see

we get 77 back so we have successfully

deployed and worked with a proxy this is

so awesome take a break we got two more

you're so close you're almost done we

got two more scrolling all the way down

founder governance another quick one and

then introduction to security and then

I'm going to send you on your way to

make the future of Finance the future of

smart contracts better place you're so

close take a break get ice cream post on

Twitter I will see you

soon all right welcome back we're almost

there everybody let's scroll on down to

lesson 14

we are now on Foundry dowg governance

and of course all the code that we're

going to be working with is in this

GitHub repo so if you want to follow

along feel free to go here now there's a

ton of conceptual stuff to go over

before we get into this but basically

we're going to learn everything about

what a dow is what they're for and how

to use them and as we're going along and

as we're learning about Dows I want you

to take some time to read these two

articles they're both from vitalic and

they address a lot of the main concerns

with dows one of them are that Dows are

not corporations where decentralization

in autonomous organization matters and

this article came out in response to a

lot of people having really hard

coordinating doubts because since

they're decentralized autonomous

organizations and it can be difficult

sometimes to coordinate with so many

people and so many heads so this article

is really interesting where Dows work

really well and sometimes where they

don't and this one is one of my favorite

articles about plutocracy plutocracy is

is government by the wealthy this is

something that obviously sounds bad and

something we want to avoid in this new

system that we're creating if we default

to typical erc20 based governance we're

going to run into a lot of issues

outlined in this post if that doesn't

make sense to you right now don't worry

it will and we'll come back to this in a

little bit but first let's learn about

Dows what Dows look like and how they

actually work especially as developers

so I made some videos about this in the

past let's go ahead and watch those and

we'll come

back now before we learn how to code a

dow we should learn what a DA is and

again I've already made a video that I

put a lot of work into so we're going to

watch what a DA is from a high level

first then we're going to learn how to

code a

da now Dows or decentralized autonomous

organizations is a bit of an overload of

term but it typically describes any

group that is governed by a transparent

set of rules found on a blockchain or

smart contract and I say overloaded

because some people say Bitcoin is Dow

because the miners could choose whether

or not to upgrade their software other

people think that Dows must use

transparent smart contracts which have

the rules ingrained right into them and

then other people think Dow is just a

buzzword so they just slap the name

really onto any organization so that

they can get some clout and this makes

her sad

Patrick and this is enough to be

confused with the da which was an

implementation of a DA back in 2016

which set the record for the largest

hack at that time so there's a lot of

different ways to think about it and the

Dow term is used in a lot of different

ways but in essence imagine if all of

the users of Google were given voting

power into what Google should do next

and the rules of the voting was mutable

transparent and decentralized this

solves an age-old problem of trust

centrality and transparency and giving

the power to the users of different

protocols and applications instead of

everything happening behind closed doors

and this voting piece is a Cornerstone

of how these operate this decentralized

governance if you will and it can be

summarized by company or organization

operated exclusively through code and to

really understand all this we're going

to look under the hood of the protocol

that's setting the precedent for all

other Dows and compound then once we

look at compound we'll understand what

goes into building one of these and all

the trade-offs all the different

architectural choices mean for your

group and then in my next video I'm

going to have a full codal tutorial for

developers looking to build one of these

themselves but be absolutely sure to

watch the rest of this video because

it's going to give you all the

architectural fundamentals so you can

make Intelligent Decisions when you get

to that section and be sure that you and

your Dow friends smash the like And

subscribe button so that we can keep

giving you the best engineer first

content on the planet when it comes to

Smart contracts let's get into it so

here we have the compound protocol it's

a borrowing and lending application that

allows users to borrow and lend their

assets and everything about this

application is built in smart contracts

now often times they're going to want to

do a lot of new things maybe they want

to add a new token to allow borrowing

and lending maybe they're going to want

to change some of the apy parameters

maybe they're going to want to block

certain coins there's a lot of different

things that they might want to do so

that's where we're going to go ahead to

governance this is where you can find a

user interface for a list of all the

proposals and all the different ballots

that came to be so here's a list of some

of the governance proposals that this

protocol has actually been making to

improve and let's look at one of these

proposals that currently actually in

process so if we click on the proposal

we can actually see everything about

this proposal who voted for who voted

against and the proposal history here

now the first thing to one of these

proposals is somebody has to actually

create the proposal in a proposed

transaction and we actually see that

proposed transaction right here if we

click on this and we scroll down we can

actually see the exact parameters they

used to make this proposal let's go

ahead and decode the input data and we

can see this is exactly what this

proposal looks like the way that they're

typically divided is they have a list of

addresses and a list of functions to

call on those addresses and then

obviously the parameters to pass those

addresses so this proposal is saying hey

I would like to call support Market on

this address set Reserve Factor on this

address here are the parameters we're

going to pass they're obviously encoded

with bytes and then here's the

description string of what this is doing

and why we're actually doing this the

reason we have to do this proposal

governance process say is that these

contracts likely have access controls

where only the owner of these contracts

can actually call these two functions

and the owner of these two contracts is

likely going to be this governance sty

and values to zero just means that we're

not going to send any eth along with

these transactions once a proposal has

been created after a short delay it

becomes active and this is when people

can actually start voting on them this

delay between a proposal and an active

vote can be changed or modified

depending on your doubt then people have

some time to start voting on them and if

it passes which this one overwhelmingly

did it reaches succeeded if we click on

this transaction again and we go to the

compound governance contract and we

scroll down to contract right as proxy

we can actually see the exact function

that the people called to vote namely

cast by vote cast vote by signature and

cast vote with reason we'll talk a

little bit about the exact differences

between these in our next video but

these are the function that they're

actually calling and if you go to the

compound app and we go over to vote this

is a user interface you can actually

vote through to make it easier if you're

not as techsavvy so you can vote right

through this app. compound. Finance or

you can just send the transaction

yourself once all those votes happen it

reaches this cued stage now what does

cued mean well before a proposal

actually becomes active there's a

minimum delay between a proposal passing

and a proposal being executed so

somebody has to call this cued function

and it only can be called if a vote

passes and it says okay that proposal ID

has been cued and we're going to execute

it soon now if we go to a different

proposal like this one for example we

can see it has been executed we can see

somebody called this executed

function and they executed proposal 82

so this is going to be a full example of

the life cycle of a proposal going

through this process now there are a

couple that even failed whole punch of

you voted against this and if you scroll

down you can see it was created it was

active and the majority of people voted

against so that's where it stops now

often times just putting one of these

proposals through isn't enough to really

Garner some votes for it you generally

want a forum or some type of discussion

place to talk about these proposals and

why you like them or don't like them

often times a discourse is one of the

main places that people are going to

argue for why something is good or why

is bad so people can vote on these

changes and again snapshot might be one

of these tools that you use to figure

out if your community even wants

something before it even goes to vote

you could join one of these and with

your tokens actually vote on things

without them being executed just to get

the sentiment or like I said before you

could build your protocol in a way that

snapshot actually helps you with the

voting process all right now you've seen

the protocol that has been influencing

all the other Dows on how to vote now

you know now that we know what a dow

looks like let's talk about the the

architecture and tools that go into

building one of these and additionally

the trade-offs that they have and the

first thing to talk about here is going

to be the voting mechanism now voting in

decentralized governance is critical to

these Dows because sometimes they do

need to update and change to keep with

the times not all protocols need to have

a dow but those that do need to have a

dow need a way for participants to

engage this is one of the most important

questions to ask and to tell your

communities how do I participate how do

I engage in this D

how do I help make decisions and you'll

find this is a bit of a tricky problem

to solve now an easy approach to this

problem is going to be using an erc20 or

an nft token as voting power similar to

what we saw with compound use the comp

token to vote for different proposals

seems simple enough right boom problem

solved hooray now this actually might be

the right approach for certain Dows but

it also runs the risk of actually being

less Fair because when you tokenize the

voting power you're essentially auction

off this voting power to whoever's got

the deepest Pockets Whoever has the most

money gets to pick the changes so if

it's only the rich people who get to

vote then it's highly likely that all

the changes in the protocol are going to

benefit the rich which doesn't really

seem like that great of an improvement

over our current world nfts are

interesting because they have this

non-fungible component but yet even they

still run into this issue additionally

if you buy a whole bunch of votes you

make a bad decision and then sell all

your votes you as an individual don't

really get punished you just punish the

group as a whole but you being malicious

you can get away with pretty scot-free

now again this voting mechanism is going

to be correct for some groups but for

other groups maybe not it really just

depends on what your Dow and Community

setup is going to look like now the next

one we're going to talk about is skin in

the game now vitalic has actually

written a lot about this and I highly

recommend you read his article Link in

the description to see that the skin in

the game method means that whenever you

make a decision your vote is recorded

and if that decision leads to a bad

outcome your tokens are asked you get

punished for making evil or bad

decisions for your Dow and your protocol

I like this mentality because even if

you buy a ton of tokens and decide to be

evil with it you can be held accountable

for your bad decisions now the hardest

part about this though is going to be

how do we decide as a community what is

a bad outcome how do we actually punish

these people and that's easy because the

answer

is I'm not sure now the third method of

this voting mechanism is probably one of

the most interesting ones but also the

hardest ones to implement and this is

proof of personhood or participation

imagine that all users of the compound

protocol were given a single vote simply

because they used the protocol and even

if they had a thousand wallets they use

the protocol one human being means one

vote this would be amazing and a far

more fair implementation where votes

couldn't actually just be bought the

issue however comes in something known

as civil resistance how can we be sure

that it's one vote equals one

participant and not one participant

pretending to be thousands of different

people so they get more votes this

method hasn't really been solved yet but

I'm willing to bet some very clever

engineer will do some amazing chain link

integration because proof of personhood

is basically just offchain data that can

be delivered on chain and that's exactly

where chain link shines now as you can

see all these methods and even more that

you probably think of aren't that

far-fetched and we actually see these

exact same methods happening in the real

world proof a person who or approve of

participation might just be the exact

same as kind of the regular government

voting that we see every day in the

United States at least one person gets

to vote for one president you can't go

around making a whole bunch of fake

people and voting for president but in

companies the erc20 voting standard kind

of applies the more shares of a company

you have maybe the more voting power you

have in that company so we can draw

parallels between the real world and how

voting and governance is going to work

in our smart contracts and in fact you

should draw parallels and look for

inspiration from the web TW space now

when it comes to implementation of the

voting I put them into two categories

onchain voting and offchain voting

onchain voting is exactly what we saw

with compound there's a smart contract

on chain you're a voter you call some

function called vote with your metamask

your Ledger or whatever send a

transaction and boom you voted congrats

you can wear your little thicker Now

call that function and you send a

transaction you send a transaction H

what do transactions use that are kind

of annoying and kind of costly uh oh

that that's right gas imagine you have

10,000 people in your community and it

costs $100 to vote per person you are

now costing your community $1 million

anytime you want to change anything this

is obviously insane and not very

sustainable for your community the pro

here is that the architecture is really

easy everything's going to be

transparent everything's going to be on

chain and that's really good but yes the

con is that you're going to break the

bank account for a lot of people

potentially now there are a lot of

variations of this to help solve some of

these problems especially the gas

problem one of the ones that I'm

incredibly excited for is this one

called Governor C where they use some

random sampling to do some quadratic

voting to help reduce cost while

increasing civil resistance you want to

learn more about that one too be sure to

read about it in the description so

onchain voting is the simplest one here

but let's talk about offchain voting how

could you possibly vote off chain in a

decentralized context relax relax you

can vote off chain and still have it be

100% decentralized you can actually sign

a transaction and sign a vote without

actually sending to a blockchain and

therefore without actually spending any

gas instead what you can do is send that

signed transaction to a decentralized

database like ipfs count up all the

votes in ipfs and then when time comes

deliver the result of that data through

something like an oracle like chain link

to the blockchain all in a single

transaction alternatively what you could

do is you could replay all these signed

transactions in a single transaction to

save gas this can reduce the voting cost

by up to 99% right now this is an

implementation and one of the most

popular ways to do this is through

snapshot and I'm just dying for someone

to make a chain link integration because

it's going to be so much safer more

secure and better and blah blah blah

dying for it this is your call to action

go build this thing this offchain voting

mechanism obviously saves a ton of gas

to the community and can be a more

efficient way to store these

transactions anyways however it needs to

be implemented very carefully if you run

your entire Dow through a centralized

Oracle you are essentially reintroducing

a centralized intermediary and ruining

the decentral of your application so

don't do that and if you made it to this

point in the video give yourself a

little path in the back you're doing

fantastic learning is fantastic like I

said I have a video coming out after

this one that's going to show you end to

endend how to build one of these from

scratch let's learn about some of the

tools that you can use to help get you

up to speed quicker now there are a

number of no code solutions that can go

into building one of these Dows Dow

stack

Aragon just kidding this is Aragon

colony and DOW house are all

Alternatives that can actually help you

with the Ops side of running a and

building a doubt however if you want

more granular control and you don't want

to have to pay any of the fees

associated with these protocols you

might want to do it from scratch now

let's talk about some of the more Cody

solutions that you can use Snapshot is

one of the most popular tools out there

for both getting the sentiment of a dow

and actually performing that execution

users can vote through this protocol

with their actual tokens those

transaction gets stored in ipfs but none

of it actually gets executed unless the

Dow chooses to so this can be a great

way to get the feel for what your Dow

wants to do

and optionally you can send the

transactions and execute the votes as

well I highly recommend checking out

zodiac which is a suite of Dow based

tools for you to implement into your

Dows as well tally is another one of

these uis that allow people to see and

actually vote and interact with these

smart contracts through user interface

for those of you who don't know about

nosis safe you absolutely should nosis

safe is a multisig wallet and the reason

that I put this on the list even though

it's adds kind of this centrality

component is that most Dows in the

beginning are probably going to start

with some type of centrality it's much

easier to be fast when you don't have

thousands of people to wait for a vote

and in the beginning any protocol is

going to be centralized to some degree

anyways using a multisig where voting

happens through only a few key members

can be good in the beginning for your

Dows and often emergencies as well but

just keep in mind when you add one of

these you are adding this level of

centrality and then of course open Zepp

and contracts we love open up in

contracts these are the contracts that

we're going to be basing our Dow codal

on all right so that's all the tools

that's the architecture one more thing

before I let you go legality the future

of dows is interesting for all these

reasons we just talked about but

especially on a legal front does it make

sense for a DA to live by the same

regulation as another company how could

you even force a DA to do something

you'd have to force them to all vote a

certain way if the government tells you

to it's it's a little gray it's hard to

nail down who to even keep accountable

for these Dows in the United States at

least you can actually form your own Dow

and have it legally recognized in the

state of Wyoming this is something I

want to do someone just have to see what

happens there w at this point you have

been injected with all the Dow knowledge

you need to succeed and Thrive with this

new amazing technology and these new

amazing Concepts and it's time to build

[Music]

baby now we are still going to build a

dow from scratch but we do have our

special guest Juliet from the Aragon

team to go over a no code solution that

you can use as an alternative hello

everyone uh my name is Julia chier I'm

the developer advocate for Aragon and

today we'll be building a dow without

using a single line of code let's go so

to do that I'll be using Aragon as my

Dow framework and to give you a bit of a

better overview as to how Aragon

architecture is set up um Dows are

essentially composed of a smart contract

which is the one that contains all of

the assets that the organization manages

um so it acts as a treasury and then all

of the other functionality for Dows is

really enabled through plugins and we'll

see how this uh how this is represented

itself throughout the process that we'll

build so we go into ab. ar.org we go

into creating a da um first we'll see

the process uh that we'll be taking in

order to do that and then we can get

right into it so firstly we need to

choose the blockchain which our Dow will

be deployed in um I'll choose orally for

the sake of Simplicity and playing with

testnet um then we get to describe our

Dow so we can have a developer Dow um

which can be something like this we can

set up our ens we can set up our logo a

description a dow for developers um and

we can add in additional oh we can add

in additional links um as well that

represent the

organization then we'll go into defining

the membership this is the what will

Define who is able to participate in the

governance of these assets um and

currently our app supports two different

types of uh membership definitions and

governance mechanisms one of them is

token holders which enables holders of

specific tokens to vote in the

organization and then we have multi-c

members which establishes a specific

Quorum that needs to be met in order for

a proposal to go through now to give you

some context both of these on the back

are plugins um which essentially extend

the functionality of what Dows can do

through enable them this specific uh

decisionmaking process in order to

manage the assets of the

organization however keep in mind this

can be anything and plugins can also

work to move uh funds they can be

treasury management mechanisms they can

be different types of coordination

Styles um and so really the

possibilities are endless when we speak

about uh customizing these types of

onchain

organizations then we're going to create

a token um this this can be something

like developer token we can call it

something like DVP um I can set up say a

th000 tokens for myself or add any other

address that I want to transfer uh some

funds to um then I establish what is the

minimum amount of tokens that someone

needs in order to create a proposal I'll

say 10 uh I could also just say like

allow any wet out there to vote um and

create proposals at which point uh there

is a risk of proposal spam so keeping

that in mind I'll just say that we need

um say 10 tokens in order to create a

proposal then we'll go through our

governance settings so what is the

minimum support threshold needed the

minimum participation needed for a

proposal to be valid how much times the

minimum duration the uh proposal needs

to be out there in order for it to uh be

counting the votes and then we can say

that we don't want early execution which

means that we wait for the entire time

of the duration of the proposal as well

as uh not enable people to change their

vote after they' voted I can also vote

yes to that and then the last step is

simply revising um those parameters that

have set so out of everything that we've

defined only the blockchain selection is

the one thing that we cannot change

later on since that's the blockchain

through which we're deploying our Dow

but really everything else um we can

change it later later on with a proposal

vote um and so the idea here is to

really enable these types of immutable

organizations to mutate and evolve with

time um so I'll sign in my proposal I go

back into my deployment um and so at

this stage what's happening on the back

is that Aragon is deploying this Dow

construct instance with uh the specific

plugins defined installed as we

determined throughing through the Dow

creation

process so once that's done we'll can

come into the dashboard of our Dow we'll

be able to see who is a member of our

organiz ation how many tokens are hold I

can create proposals I can make deposits

um and so this is where we'll be

managing the organization um keep in

mind that this is a a pretty um default

template that Aragon has set up as our

initial drafts we have a lot of

iterations coming in terms of the type

of plugins you'll be able to use the

different types of uh decision-making

strategies you'll be able to implement

and so the customizability really is

endless thank you very much

all right welcome back you now know a

ton about Dows and how they work and

we're are going to go over one of these

plutocracy Dows right one of these erc20

based Dows and how to build one yourself

from scratch however I want to challenge

you to not default to this a lot of

protocols default to okay I'm just going

to launch a governance token we're going

to be good to go and then a couple years

down the line they realized that that

was a horrible decision and they have a

hard time scaling their model they run

into issues where they can't separate

speculation on the token from the

utility of the token and there's a ton

of issues with that model so anybody

who's watching this if I catch you

launching a DA in the future and you do

not have a foolproof white paper as to

why you need a governance token I will

be very disappointed in you I know that

doesn't really matter to you but I will

be very disappointed in you and you will

make me sad so please don't make me sad

but we are going to learn this

methodology and how to do it so let's

jump in because guess what we only have

two lessons left and then you're ready

to go on your way all right you know

where to begin mkd boundary Dow f23 code

boundary Dow f23 or file open let's pull

up our vs code at this time you should

be pros at this part Forge in it

I don't want these three files boom boom

boom goodbye boom so let's do a little

read me and let's talk about what we're

going to do so one we are going to have

we're going to have a contract

controlled by a dow 100% controlled by a

dow every transaction that the Dow wants

to send has to be voted on and we will

use erc20 tokens for voting which like I

said this is kind of the default model

that the industry is currently using but

but I'm telling you it's not a great

model please research better ones and

make web 3 better but all right and this

is the model used by pretty much every

Dow at the moment compound Unis swap a

etc so I'm showing you the most popular

model but yes I'm telling you please

don't default to this please don't

always use this but let's start with

this first one we're going to have a

contract controlled by the Dow so let's

create a minimal contract that we can

vote on stuff for and we're going to do

something pretty similar to what we've

already done we're going to do SRC new

file we're going to make a box. soul

real similar to what we did before right

spdx license identifier MIT pragma

solidity

0.818 little carrot contract box let's

close this like this like we said we're

going to make this ownable it's going to

be controlled by the Dow so we're going

to do a little open Zeppelin work Forge

install open Zeppelin slash open

Zeppelin

contracts D- no- commit and since we're

doing this we're going to need to open

up our

founder. paste this in here uh I copied

this from a previous project opens up

on/ contracts lib opens up and blah blah

blah now since we have that we can do

import ownable from atop Zeppelin SLC

contracts SL

accessable Doo and our box is going to

be ownable and the Dow is going to own

it tracks all right cool going to be

real minimal contract un 256 private

number this obviously should be like

sore number right uh event number

changed looks like that function

store un 256 new value or new number

public this will be our only owner

function which this store function will

be only ownable will be only callable by

our Dow we'll say number equals new

number we'll even

emit number changed with the new number

this is sore number and then we'll do a

function read number or get number get

number public or external view returns

un

256 return s number and that's it that's

the whole contract boom that's it this

is kind of looks like box kind of looks

like symbol storage it's kind of an

amalgamation of both but this is it cool

we'll make sure it actually

compiles with Forge build make sure it

compiles looks like it's compiling okay

cool awesome so we have our box what's

next well every transaction that the Dow

wants to send has to be voted on we will

use erc20 tokens for voting so let's

create our our voting token here

new file go token. soul and this is

going to be our voting token now we

could implement this from scratch but

again what we can do for this is

actually just come to the contracts

wizard of open Zeppelin go to erc20 and

select votes and literally just copy

this to clipboard and paste it in or

copy this ourselves and paste it in here

this is going to be our voting token

that's it so let me talk to you about

what we just copy pasted and we're going

to update this to be named Imports

because named Imports are awesome this

draft erc20 permit we're just going to

import this erc20 permit and then erc20

votes so I'm just going to talk you

through what this is actually doing so

it's a regular erc20 token exactly as

we've seen but has these two kind of

extensions let me toggle the word wrap

and we have the opens up and contracts

installed okay pool so I'm going to

control command click into them again

you can open up the file viewer and you

know type the actual name of the

contract if you want erc20 permit what

does this actually do this allows

approvals to be made via signatures

basically you can sign a transaction

without sending it and let somebody else

send the transaction that's it it's

based off of this EIP we don't really

need to understand this too much but if

you're interested I would definitely

recommend recommend looking into it the

more important one is this erc20 votes

contract and like I said it's based off

of this compound voting in delegating it

does a lot of important things here

number one it keeps a history of each

account's voting power keeps snapshots

of them now this is important because

when you start a vote you want to use a

historical snapshot you don't want to

use the current balance of everyone's

tokens at the moment somebody could do

something called a flash loan which is

something we didn't talk about

but they basically can use this defi

thing to get a ton of tokens for a very

very short period of time and crash the

vote so we use a historical value and

the way to get that historical value is

to keep checkpoints of people's values

we can also use a delegate function on

our tokens sometimes we trust a person

more than we trust our understanding of

a topic so we can actually hold on to

our tokens still that tokens are still

ours but we can delegate the voting

rights of our tokens to somebody else

these are some of the two main features

that this token has if we scroll down we

can see we have this checkpoints

function which gets checkpoints and

there's this checkpoints mapping address

to checkpoint we can see the checkpoint

object says from block and then votes

and if we scroll down there's this Apon

token transfer function which anytime

you transfer a token this gets called it

ends up calling this move voting power

which does a whole bunch of of stuff in

here but the main things are it calls

this right checkpoint function so

anytime you move tokens by delegating

tokens or transferring your tokens you

write a new checkpoint right so you say

hey at this block this was people's

voting power and you don't do it for

every single block right you don't

calculate someone's checkpoint in every

single block you only calculate the

updates in the checkpoints so if we

scroll to the top for example says from

block this would be like you know let's

say you minted let's say you bought a

token at block and then you sold it at

block 25 this would just have two

checkpoints block five and block 25

that's it it adds some gas for every

single transfer you make but it allows

us to do these sophisticated voting

methodologies so and that's really it

other than that it's a basic erc20 token

just has these checkpoints has these

additional delegate functions as well

and that's really it and cool like

that's it our governance token is done

that's all you need to do

what else well guess what the open

Zeppelin wizard can help us with even

more CU what do we need next well we

need a doubt right we need a system we

need a contract to actually manage these

votes right and guess what the wizard

has one called Governor we can go

through this and update settings so we

can update the name if we want I'm going

to leave it as my Governor a voting

delay which is anytime somebody proposes

something it says okay we're going to

wait at least one block for the voting

to start maybe you do something like 100

blocks you know it depends on your chain

the voting period for how long the

voting will actually last a proposal

threshold where the minimum number of

votes an account must have to create a

proposal most of the time this is kept

zero a quarum percentage percentage of

tokens that need to vote in order for

something to pass if there's 100 tokens

in circulation at least four tokens need

to vote for it to pass make these

settings updatable or not this is this

is to make the contracts fully

compatible with Bravo which is the

compound implementation the type of

votes you can have erc20 votes you can

have ERC 721 votes which is nft or

comple a time lock controller anytime a

vote passes give users some amount of

time to leave the Dow before it's

implemented and then upgradeability we

probably want to avoid this as much as

we can because like I said before

security and with that I'm just going to

leave all the settings to be default we

can literally copy this into our

contract and not really have to do

anything so new file my

myor do Soul B this in and let's talk

about what is going on in this contract

what are these different functions so

first off let's update this to named

Imports and we also need to import IA

votes this is going to come from

Governor votes we're going to need to

import this time lock controller which

is going to come from this Governor time

lock and then we're going have to import

I Governor which is going to come from

governor and that's it so just update

these to named Imports and we're good to

go so let's walk through what this is

doing so my Governor is governor

governor settings Governor County blah

blah blah all this stuff I'm going to

give you the high level overview of what

all of these does this Governor contract

if we command click into it or control

click into it

the core of the governance system this

Governor contract we control click into

it it brings us to Governor votes but

let's go to the governor contract this

is kind of the main contract here and

how it works is it keeps this mapping

basically of proposals right each one of

these proposals have a vote start a vote

ended and then an executed or canceled

and that's really it every single time

somebody submits a proposal this mapping

gets updated and if we scroll down we

have this state function this is the

function that tells us if a proposal has

passed based off of this mapping of

proposals if it's executed if it's

cancelled what's the deadline has a quum

been reached Etc this is what most user

interfaces are going to read to see if a

vote has passed or not keep scrolling

down we can see a proposal snapshot

which is basically getting the deadline

when the proposal is due we can see some

stuff like a proposal threshold and then

a whole bunch of unimplemented functions

like Quorum reached vote success get

votes Etc and this is because this

Governor function is this abstract

contract meant to be extended on and

implemented with Governor votes is one

of these extensions where it says okay

erc20 token voting that's the way we're

going to do votes and this has a

function like get votes which reads the

token voting weight from the tokens

built-in snapshot mechanism to get how

often somebody can vote

uh and that type of thing now in our

governor one of the main functions that

we has is going to be propose and these

are going to be the variables it takes

in targets is just going to be like a

list of different contracts to make a

transaction to values is going to be a

list of values to send with each Target

call data now that we know all about

call data is going to be the byes data

that we're going to send with each

transaction and then just a description

right so for example this might be like

0 x0 blah blah blah some address here

and if it's just one it would just be

like you know one address here it's two

you know it might be like this Etc

values might be like you know something

like zero meaning the transaction we

send to this address we're just going to

pass zero value you know if there's two

transactions with two addresses like 0x

blah blah blah something or other you

know we could have two values right call

datas are going to be

the call data for sending to Here and

Now that we know about function

selectors function signatures and Etc we

know that with this this call datas

section allows us to make allows us to

call any function and really send any

data to this target that we want so it

makes it completely modular and then

some description right and this is

really just for the internal state of

the governor you know it might be

something like proposal

to send money to Dawn right and so if

this was like one two3 this is Don's

address cool we've just made a proposal

to send money to Don right if this was

you know like like the link token

contract for example we could have this

be zero we could find the function

selector for transfer we could be like

transfer function

selector and encode you know and then

encode all the data for the for

transferring some link we could then say

proposal to send link to Chris or

whatever we wanted to do here right so

this is how we can propose any

transaction for our Dow to do and send

proposals so really really important

function here and if we go through it we

can see it hashes the proposal it does a

whole bunch of checks in here it adds

our proposals to that proposals mapping

it gets a deadline picks a snapshot for

votes and everything emits a log and

importantly it returns a proposal ID The

Proposal ID is a hash of all the inputs

so that this proposal ID will be unique

then we have an uh another important

function called execute and all of the

inputs you can see are the same as the

inputs up here right the only difference

is it's saying a bytes 32 description

hash this is just going to be the

encrypt description from up here and

it's this function that gets called o

excuse me and it's this function this ex

Cube function that gets called once a

proposal has passed to actually send

that proposal right so here it first

reverse engineers and gets the proposal

ID from all those inputs which should be

the same as what was proposed and then

says okay let's get the status of that

proposal State based off of how the

votes go and if it's good to go then go

ahead and execute it right so we do some

execute stuff here the execute internal

function actually sends it with some

familiar stuff here right we're doing

targets. call values call datas Etc this

is this lowlevel functionality here it's

got some before execute stuff some after

Execute stuff we don't really need to

worry too much about that we can vote to

cancel transactions we can get votes and

then finally another incredibly

important function is going to be cast

vote and there's some derivatives of

this like cast vote with reason reason

cast vote with reason and pams cast vote

by Sig whole bunch of different ways to

cast vote but the main thing this cast

vote thing does is it calls this

internal cast vote function which calls

this internal cast vote function and

this is the actual function it calls so

it gets the proposal based off the

proposal ID it gets the weight of your

vote based off of the snapshot of the

tokens that you hold calls this internal

count vote function which basically just

updates some internal State variables

to add your votes to them and then

admits an event that's it right and

updates your vote based off of whatever

your weight is which in the system that

we're using the more tokens you have the

more you your vote counts and those are

the main functions here so hopefully

that made sense I know I kind of went

through that a little bit quickly but

that's kind of the basics of the

governor now Governor is the main

contract Governor settings is just an

extension to add stuff like voting delay

voting period voting threshold Etc

Governor counting simple is also an

extension uh which is just an extension

for a very simple counting mechanism

this extension allows our votes to be

against for and abstain and so we have

this proposal vote for each proposal

they get this struck and this is where

those votes get counted we have against

votes for votes abstain votes and then a

mapping of who has actually voted

Governor votes just implements this get

votes contract and Governor votes quorum

fraction this is just an extension or

token weight extraction and then we have

this important time lock controller

function every single Dow should 100%

always have this Governor time lock

control using this model means the

proposal will be operated by the time

lock controller and not the governor

thus the assets and permissions must be

attached to the time lock controller so

we're actually going to deploy a

contract called time lock that's going

to own the governor anytime our governor

contract votes on something and says

okay this vote has passed let's executed

the time lock controller will say okay

cool but you have to wait X days or

something you can't execute without some

delay and it's really important to have

this because if a dow votes on something

that a lot of people in the Dow hate it

gives them time to get out of the Dow

before they get steamr if you will so

really important to have this and that's

pretty much it so we have some uh voting

delay voting period Quorum State propose

we have all these uh which are just

calling super right that's pretty much

it and that's all we really need for our

governor contract right we have this

Constructor which takes the token that

we vote on as an input parameter and the

timelock controller that's going to

block us from block us from executing

proposals right away time lock

controller contract is going to own our

governor controller contract and that's

actually the last contract we need to

create a Time lock. Soul so this is the

only one we have to build ourselves but

we actually barely have to build it

ourselves SPX license identifier pragma

solidity 0.

8.18 carat contract time lock and we we

barely have to implement this because

open Zeppelin already has one of these

so we just say our time lock is

time lock controller and then we can

just import it import at open Zeppelin

SL contracts SLG governance time lock

controller. let's import it like this

from I spell that right time lock

controller okay that's more right

governance governance contracts

contracts open Zeppelin open Zeppelin

time lock cont controller time lock

controller okay cool that looks good now

we'll just do a

Constructor and we'll pass some

parameters in here we'll say U 256 Min

delay which we'll put a little comma

here this is going to be the Min delay

is how long you have to wait before

executing we're going to have to pass

and we can find all of these in the

Constructor of

this m delay proposers executors and

admin right this is the Constructor of

the time lock controller so we're going

to need to have this be the Constructor

of hours as well M delay we're going to

need

proposers is the list of addresses that

can propose so we need an initial list

of proposers we're going to update this

so that it can be anybody and then xeq

tors is the list of addresses that can

execute execute we're going to update

this as well so that anytime a vote pass

is anybody can execute it so M

delay address array memory proposers

address array memory

xter boom and since this time lock

controller parent class has a

Constructor I'm tle the word WP we going

to put those in here and it's just

exactly the Constructor parameters we

created in delay proposers

xors computers

and then we also have to give it an

admin which we're just going to say is

message. sender for now and we need to

give it an admin at first so that we can

eventually move the Tim lock controllers

admin so that only the Dow can do

anything with the time lock controller

and you'll see us do that in a minute

but those are all the contracts that we

need that's it we've written the

contracts we're done like I said I'm

going to do this kind of quickly I do

recommend that after this you go back

and you really try to understand what's

going on here because I I know I'm kind

of doing this quickly but now we're

going to write a test to show it

actually work and that's it I'm not

going to write a deploy script here uh

if you want to go back and you want to

write a deploy script that's great but

I'm just going to write a test to show

you basically endtoend exactly the

process that happens in one of these

Dows so let's go ahead let's write the

test my Governor test.

T.O and the other reason that I'm going

a little bit quicker here is because at

this point you understand a lot of this

right and you know and should know how

to go back and flush this repo out right

with scripts with tests unit tests fuzz

tests Etc and you know how to make this

project badass and I'm just I just want

to give you the new stuff right teach

you the new stuff for here teach you

about the Dow stuff so let's write some

test just so that we can really see this

process work end to end and we're just

going to have one giant test just to

show the whole process so you know the

drill pragma solidity here contract my

Governor test is test you already know

we're going to import test from Forge

STD test.

soul and we're going to need a function

function setup it's going to be Public

public of course and we're going to need

a whole bunch of stuff in here function

setup oops what are we going to need

well we're probably going to need at

least these four contracts so let's go

ahead and import them

import

myga nor

from as Maga veror do Soul import box

from Sr cbox

Doo import time lock from here hit up

co-pilot taking over a little bit import

gov token okay it failed it almost took

over here from SRC go

token. s oh is that not what it's called

ah sorry let's change this name to gov

token like this it's good okay so now

let's actually deploy some of these so

our gov token say actually let's create

each one of these my governor

governor box box time lock time lock go

token go token cool first thing that

we're going to need is our gov token

equals new gov token and I know this

doesn't take any input parameters but we

should give our gov token we should

actually mint some of these this gov

token doesn't have a mint function so

I'm just going to create a mint function

but in your system maybe you just have

the Constructor mint to the message.

sender I'm just going to go ahead and

add this function mint address 2 256

amount

make this public um this probably isn't

what you want your token to have you

probably don't want anyone to be able to

Mint any tokens but this is what I'm

going to do mint to amount that's it

there's an internal function called mint

that we're going to call so I'm just

going to say I'm going to Mint to some

user I'm going say

address public user equals make address

this is going to be our user here do

this capitals user like this say gov

token. mint user and we'll do un 256

public

constants yeah initial Supply equals 100

ether we're going to Mint ourselves 100

ether boom all right cool now something

that you'll often forget is that just

because you minted tokens doesn't mean

you've have any voting power so we want

to run gov token. deligate delegate

function and we're just going to

delegate to ourselves so we're saying

hey we now have 100 tokens we're going

to delegate those 100 tokens voting

power to ourselves you could delegate it

to somebody else if you wanted to but

for our test we're going to do it for us

and we need to actually do vm. start

prank user because only the user can

delegate tokens to themselves and we

might as well stay as the user for these

next ones just that we can start off as

owners of the contracts we're about to

do so now that we have our governance

token next what we want to deploy is our

time lock because in order to deploy our

governor we're going to need both the

gov token and the time lock so we have

the gov token let's actually create the

time lock now so we're going to say time

lock equals new time lock and what does

this take M delay posers executors so

let's create those going to scroll up

we're going to make un 256 public

constant Min delay delay equals

360 0 which is going to be 1 hour this

is the delay after a vote passes right

so this is the time locks M delay nobody

can actually execute a past proposal

until an hour goes by boom we'll do M

delay what else do we need we need the

proposers for stuff and we'll just make

this at the top address array Pro

proposers address array

executors and we'll just leave it blank

because we don't care proposers

executors and this is actually how with

the time lock controller you say anyone

can propose and anybody can execute you

just leave these arrays blank cool looks

good okay now that we have that we

finally can deploy our governor contract

CU we have these two so we'll say my or

what do we call it do we just call it

Governor yep governor

equals new my

Governor go

token time lock like that now we have to

Grant some roles so the time lock

actually starts with some default roles

and we need to Grant Governor a whole

bunch of roles and then we need to

remove ourselves as the admin of the

time lock right we don't want single

centralized entity to have power over it

so first we got to get some of the roles

so we're going to say byes 32 proposer

roll and the way that the time lock has

roles is it hashes the names of stuff so

we'll say proposer rooll equals time

lock

proposer Ro there's this function on the

time lock called proposer role uh and

we're going to allow this proposal Ro to

be just the governor so only the

governor can propose stuff to the time

lock say bytes 32 xq tour Q

rooll is going to be Tim lock. executor

ro we're going to give this to anybody

by setting it to the zero address and

then byes 32 admin roll right now that's

us time lock dot nope it's going to be

time lock admin roll and so like I said

these are just kind of the um these are

hashes in the time lock and we just need

to update these we're going to say time

lock time lock dot it has a grant roll

function we're going to Grant this

propos propos a role to the governor so

only the governor can actually propose

stuff to the time lock or say time lock.

Grant roll xq rooll to address zero

which means anybody can execute a past

proposal and then time lock. revoke

rooll revoke the admin role from user so

the user will no longer be the admin and

then we'll say bm. stop prank this then

we just need a new box box equals new

box and now we're going to transfer

ownership of the box to the time lock

the time lock is owned by the Dow so

we're going to say box. transfer

ownership to address time lock so

transfer ownership a common

misconception here is oh shouldn't we

transfer to the Dow no we should

transfer to to the time lock so the time

lock owns the Dow so the time lock owns

the Dow and the Dow owns the time lock

it's kind of this weird two-way

relationship but it's the time lock that

gets the ultimate say on where stuff

goes so we transfer it to the down and

so we can even do a quick test function

test can't update box

with governance public oops public we'll

say vm. expect revert box. store one

like this since our

box has a store function that's only

owner the owner is now the time lock SL

the Dow oops if I try to run this test

right Forge test DM paste this in this

should pass

because you can't update the Box unless

it's through

governance and this will also be our

sanity check to make sure our uh all of

our code is compos which it is okay

great let's keep going so now let's make

a giant function function test

governance updates box public and this

will show you the exact process from a

code standpoint of how one of these Dows

actually work so first let's get started

un 256 value to store is going to be 888

boom so we're going to update our box

right this box here we're going to

update this new number to 888 okay let's

come up with a proposal right remember

if we show up my Governor we click into

governor in uh and we click into

Governor function

propose right here first thing we need

to do to kick off anything is propose

something hey we are going to propose

that box updates the stored value to 888

so we're going to need to have all this

stuff in here Target values call datas

descriptions so let's start with

description because that's simplest

right string memory D description equals

store one in box that's it that's our

description pretty easy right what else

do we need okay we're going to need some

call datas oh well we know what call

datas are that's that function selector

and all that other stuff that we learned

in that nft one right so we can say

bytes memory

so if you go back to The Foundry nft f23

we go to SRC subl lesson we can remember

oh wait we can we can call anything that

we want right and all we got to do is

encode stuff right like ai. encode with

signature or encode with selector or

whatever we want to do here so we can

actually say oh okay so this allows us

to make any function call that we want

so we'll encode it by saying encode

function call equals we want to well

what do we want to call well we want to

call this store function ah so we know

the function signature of store is going

to be store unit 256 so we can say ai.

encode with signature we're going to

call the store function like this and

then what else do we need well we need

the value like this and that's it cool

let me toggle the word rep here cool so

we have the encoded function call so we

have the call datas that we need to call

in okay great what do we need next and

we're going kind of in this reverse

order values uh well we don't really

care to send any value right so let's

even just go to the top here we'll make

a un 256 array values it'll start off as

blank we'll just say values. push Z cool

we'll just have it be empty we're not

going to send any eth and then the final

thing we need is targets so we want to

call this on the box contract right oh

and actually call datas is also an array

so we're going to do a couple things

we're going to do

values all

datas and targets targets right so the

call datas is a un 256 no call datas is

a bytes array targets is an address

array so we're going to say values. push

zero call datas do push that encoded

function call that we just made and then

targets. push the address of the box

right so now we have all that now we can

finally call our proposed function and

what does this proposed function return

returns this un 256 proposal ID and we

need that to keep going so first thing

we're going to do is propose to the Dow

propose to the Dow so say you and 256

six proposal ID equals

governor. propose the targets values

call datas and

description boom and we got our proposal

ID just like that now we can even view

the state of this proposal now right

because we can call that state function

so we can do even like a little

console.log

proposal state uh we can call a state

function like this actually get a

copilot has this right except for we

want to turn this into the U 256 version

so we'll say un

256 governor. State proposal ID like

this and if we look up function State

we'll find this there's like a million

of these in our governor. soul it

returns this proposal state which if we

control or command click on that we can

see all the different states that can

have pending active canel defeated

succeeded cued expired executed so

pending obviously is going to be zero

active is obviously going to be one

canceled is going to be two Etc right

and of course we're going to need to

import console from test Okay cool so

this should return what should return

pending it should return a zero and it

hasn't started yet it's not active

because there's a delay right so we want

want to actually update our fake

blockchain to move past that so we'll

just do vm. warp we'll use these cheat

codes remember lock. timestamp plus and

then we'll just do voting delay you went

six public constant voting delay equals

one this is how many blocks till a vote

is active right and from our wizard we

just left this as one oh go back to

Governor we just left our voting delay

as one so this voting delay is one so uh

plus voting delay and then actually

we'll do voting delay plus one and then

we'll also do roll to increase the time

as well bm. warp EXC going me to

increase the number block.

number plus voting delay plus one now if

you view the state it should be active

so now it'll be active cool two after a

proposal starts because we've proposed

enough time has passed we now can

actually start voting on something so

I'm going to do this cast vote function

but I'm going to do cast vote with

reason because I like cast voting with a

reason so we're going to do string

memory reason equals cuz blue frog is

cool that's going to be my reason that's

why I'm going to vote for something

because blue frog is cool in order to

vote we're going to need to call this

cast vote function if we go to Governor

we look for the function Vote or excuse

me cast if we go on our search bar we

can look for function cast vote there's

a whole bunch of cast votes we can see

in here we need to pass a proposal ID

and

support how do we know support works

well let's look at this Casto internal

function this Caso internal function

down here support

count vote we got to look at this count

vote function so let's look for function

count vote okay this is the abstract

implementation let's we don't want

Governor compatibility Bravo we want

Governor counting simple because that's

we're using Okay support how does

support work aha okay so there's this

vote type struct that it's checking for

let's go to the vote type okay against

for abstain so against is going to be

zero

four is going to be one and abstain is

going to be two so what do I want to do

I want to write vote four so we're going

to do one so we're going to say we have

our reason un 8 vot way equals 1 which

means I'm voting for voting yes if you

will and now let's do our vm. prank our

user or our voter and we'll do

governor. cast vote

with reason proposal ID vote way and

reason reason all right cool now that we

voted let's speed up this voting period

because everyone voted because we're the

only voter let's speed up this voting

period and we set the voting period

automatically if we go back to our my

Governor right voting period was set to

one week in here this number represents

one week so we're we're going to speed

up this voting period I'm going to copy

this number scroll up to the top we'll

do U into 256 public constant uh excuse

me voting period equals this oh and this

should have a semicolon voting period

we're going to speed through the voting

period I'm going to just copy these

change this to

voting period voting period now now that

we' voted and the voting period is done

what do we do well we actually need to

cue the TX before we can actually for

execute so we have to cue it first so

there's a queuing process so on our my

Governor there's a function function q

and a whole bunch of them have this let

me open this up function

Q on this Governor timelock controller

there's this queuing bit because a que

means it's passed but we have to wait to

queue it up we just pass the same bits

that we originally did for propose so

we're going to go back here we'll say

the only difference is we need to Hash

the description first so we'll say bytes

32 D description hash equals check

256 api. in code pack description now we

can call governor. Q propal ID uh excuse

me this is not right

c.q um um targets we're going to pass

the same values that we proposed with so

that we guarantee it's the same proposal

so targets values

function uh call datas and description

hash oh we don't need that zero we're

going to queue it and then we're going

to

finally wait this m delay which we said

hey after a vote passes we need to wait

this m delay before we can execute so

I'm going to copy this again paste it

here instead of voting period this going

to be M delay M delay and then finally

we can execute so we'll do governor.

xute it's going to be the same as what

we did to queue it up I even just copy

this whole thing paste it here targets

values call Dat is description hash

X let me spell this right and now

finally we can do assert box dot get

number equals the value that we

stored

boom we even do like a console

diog box value box sucket

number okay copy this open our terminal

clear porch test DM paste - VV so we can

see the console. logs pull it up

is this what we've been waiting

for no we ran into an issue we see these

two logs proposal state is zero we're

getting vote currently not active so

let's add a couple more of these so we

can see where it failed it looks like it

got to the cast vote with reason and it

failed so let's go to our test so it

looks like it proposed okay it looks

like this failed so it says it's

currently not active so did we mess up

our voting delay ah it's cuz I did warp

for both this should be vm. roll let's

see do we do oh we messed that up for

all of them let's fix this roll roll

roll okay cool let clear let's run it

again hold this

up oh my goodness it passed and we can

see in the logs proposal state was Zero

we waited and then it became IM active

and and then finally after we got

through all the different states we

finally were able to update the box I

know we kind of sped through this

section but like I said at this point

you're becoming a pretty sophisticated

smart contract engineer and I really

wanted to show you the process of voting

of a typical Dow from today and for you

to see it from the coding side as well

now if you want to go further with this

I highly recommend you look into some of

the different methodologies and some of

the the newer methodologies that

researchers are coming out with for

people to actually do votes because like

I said plutocracy is not the best so if

you want to go farther try experimenting

with other ways to build Dows maybe

flesh out your own doubt maybe deploy a

doubt do whatever you want to do here

but in any case you should be incredibly

proud of yourself because you got

through the hardest lesson of this whole

course already which was the stable one

and then you just learned this

incredibly powerful Advanced course in

how Dows actually

work students we're almost at our end

there is one more lesson for us to do

and it's our smart contract and security

auditing for developers do not leave

this course without watching this I want

you to have at least the fundamental

knowledge of where you should look for

security help what you should have in

mind for security especially now that

you have the ability to go out and

deploy some amazing contracts I'm not

going to teach you how to audit step by

step here right but I am going to teach

you here's what you should be looking

for in an auditor here's how you you can

begin to start thinking about security

and I am working on some security and

auditing education material as well to

make those of you who do want to go down

that path successful so

give yourself a pat on the back do a

little dance do a little celebration get

some ice cream and I'll see you in the

next one and then I will I will release

you to the world so pause the video and

I'll see you

soon and as a special piece of bonus

content we have Harrison here to give us

some tips on gas optimizations so enjoy

hey guys I'm Harr Leo and I'm the CTO

and co-founder of pop punk LLC where

we're building Gaslight GG uh Gaslight

GG is a audit firm but we focus

specifically on gas optimization for

protocols to ensure that your gas costs

are as low as possible uh in addition

we're happy to announce that we're now

building uh hyper optimized public goods

tools for evm developers to make sure

that everyone has access to just the

best and the cheapest contracts so

Patrick invited me on here to show an

example of some some common ways that

you might be using too much gas in your

smart contracts Without Really noticing

so I have a quick example here we're

going to look at an airdrop contract

this is a super basic airdrop contract

which I'm calling airdrop bad or bad

airdrop uh very simple we have a token

we're using a counter to iterate um and

count the number of transfers uh so as

you see in the Constructor we set the

token here uh and then we have our

airdrop function so we have two

parameters um for this function the

first one is a memory um array of

addresses which is the recipients and

then we have a memory array of un 2506s

for the amounts the first thing we're

doing is we're checking to make sure

that the amounts match otherwise we're

going to revert the next thing here

which is really common um is making sure

that you're batching your your actions

so if we see in this case we have to

Traverse through the entire uh input

argument array a fulltime just so we can

transfer the number of tokens from the

message. sender to the contract so let's

say there's 50 amounts we'd have to do

50 separate transfer from it's

definitely not ideal uh and then lastly

here we have a super basic Loop where

we're just iterating through the array

um and we are transferring the tokens

from the contract to the user with the

respected amounts here uh lastly we can

see that we're iterating this counter

every single time in the array or every

time in the loop yeah so keep that in

mind so now if we look at a more ideal

example of this the first thing that

you're going to notice is we're using a

mutable for the token a mutable is good

if you're obviously never going to

change something because we set this

value in the Constructor and it'll be

included in the contract deployed by

code which is cheaper to read from every

time if we look now here we've changed

our arguments for our function the call

data and we've added a new one called

total amount this is done so we don't

have to do two Loops through the array

we can do one so if you see here the

first thing that we're doing is we're

transferring this total amount from the

message. sender to this contract so

that's going to cut a large amount of

gas because we're only going to wind up

looping one time so if we see here we

we've changed the way that we're going

through the loop technically we don't

have to Cache this array length because

we're using call data but if you do see

here it's the same thing we're

transferring tokens from this contract

to the recipient uh we're also using

unchecked for our Loop iterator because

it's not going to overflow cuz the odds

of someone doing an airdrop to more than

the max U 256 of addresses is kind of

crazy um and the final thing to look at

here we're using an unchecked block

again but rather than updating this

state value of transfers every single

time and paying that base G gas cost

each time we can just update this amount

at the end with the bulk length so these

are small things that you can think

about when you're writing your smart

contract to ensure that you're saving as

much gas as possible if we look at the

results of this the airdrop bad costs uh

1,

94,6 190 gas and the airdrop good cost

44842 gas so we've essentially saved

600,000 gas just by doing Simple things

you know it doesn't make the code

unreadable um and you're just making

sure that you know the end users of this

will not have to spend a crazy amount of

money so I want to thank Patrick for

having me on here uh you can find me on

Twitter atpunk onchain um or the

business account is atpunk LLC if you're

a small protocol or a large protocol

feel free to reach out for gas Audits

and uh pretty soon in the near future

you'll be able to go to gasl light.gg

and you'll be able to deploy super cheap

super gas optimized smart contracts you

know through no and just pressing one

button thank

you all right welcome back to our last

lesson of the course I hope you're

excited because I sure am in this last

lesson we're going to give you just a

teasing of smart contract security and

auditing this is especially for

developers we're not going to go over

everything security however in here I'm

going to leave a ton of places where you

can learn and grow and absolutely be

sure to sign up for web3 education.

because we're going to put a whole lot

more security information information in

here as well but we are going to give

you the foundational information that

you need to even begin to start thinking

about where to go and how to work with

security in the space we have this repo

Denver security to talk a little bit

more about security and how it works but

I want to give you all a couple of stats

before we even jump into security to

impress upon you why this is so

important this is probably the stat

that's the most jarring to me according

to chain analysis as of last year 2022

about $3.8 billion doll was stolen in

crypto hacks and about 3.1 billion of

that 3.8 billion was specifically Defi

and if we go to defi Lama last year defi

had a total value locked of around 50

billion so if we do the math there 3.1

ID 50 we're talking around 6% of all def

was hacked last year that's like walking

up to a bank and saying hey can I put my

money in you and the bank going yeah

sure just ah heads up there's a 6%

chance all your money will be gone next

year that is an insanely horrible

statistic and it's why we need to put so

much more focus and so much more

emphasis on security there's a popular

website called rec. newws that has a

leaderboard that if you go to you can

see a lot of the top biggest hacks

hugest hacks to ever existed did went

off of code that was unaudited

unreviewed by Security Professionals

unaudited unaudited unaudited uh Na Na

un audited unaudited unaudited unaudited

out of scope unaudited out of scope and

it is not acceptable some of these hacks

were absolutely massive losing over half

a billion dollars so if you're a

protocol or if you developers go on to

build protocols here is what you want to

think about you can maybe spend $2

million of your budget on security or

get hacked for $200 million the spending

money on security is a 99% reduction

cost so if you approach security from a

business perspective it absolutely 100%

makes sense for you to spend resources

on security so to kick start this video

all of you protocol devs will probably

want to get a smart contract security

audit at some point a security Focus

code review before you launch your

protocol so let's start there I've made

a video recently on what a smart

contract audit is and how to prepare for

a smart contract audit that we're going

to watch first because even if you don't

want to become a smart contract auditor

yourself you'll need to know what a

smart contract audit is for when your

protocol is going to go launch to

mainten it so let's start

there a smart contract audit is a

timeboxed Security based code review on

your smart contract system an Auditor's

goal is to find as many vulnerabilities

as possible and educate the protocol on

best security best practices and coding

best practices moving forward Auditors

use a combination of manual review and

automated tools to find these

vulnerabilities now why are these so

important why is it critical that you

get an audit before deploying your

codebase to a live blockchain well for

starters there are entire websites

dedicated to how many hacks happen last

year we saw the most value ever stolen

from Smart contracts with almost $4

billion stolen due to the immutability

of the blockchain once a smart contract

is deployed you can't change it so you

better get it right the blockchain is a

permissionless adversarial environment

and your protocol needs to be prepared

for malicious users but even more so

than that an audit can improve your

developers team's understanding of code

improving their speed and Effectiveness

in implementing features moving forward

and it can teach your team the latest

and greatest Tooling in the space often

just one smart contract audit isn't even

enough and protocols go on a security

Journey that includes many Audits and

many different services like formal

verification competitive Audits and Bug

Bounty programs we'll break these down

in a future video there are a lot of

companies that offer smart contract

auditing services like trail of bits

consensus diligence open Zeppelin Sigma

Prime spearit Dow mix bites watch pug

trust and of course cyphon additionally

there's a lot of independent Auditors

that do great work as well a typical

audit looks like this price and timeline

first a protocol needs to reach out and

they can reach out before or after their

code is actually finished ideally they

reach out sometime before their code is

finished so the audit can have time to

slot them in once they reach out the

protocol and Auditors will discuss how

long the auto will take based off of

scope and code complexity the scope of

the audit is going to be the exact files

and commit hash that's going to be

audited how long the audit usually

depends on how many lines of code SL

complexity you can see a very very rough

approximation of how long an audit takes

on your screen now of course this

depends firm to firm audit to audit and

tool to Tool so take these with a very

large grain of salt additionally it's

this duration that sets the price and

same thing at the time of recording

Prices range wildly depending on who's

doing the audit how many people people

are doing the audit how complex the code

is and more and these initial

conversations are really just to get a

ballpark estimate and Slot you into the

auditor schedule commit hash down

payment start date once you have a

commit hash you can finalize the start

date and final price the commit hash is

the unique ID of the codebase that

you're working with so the Auditors can

know exactly what code they're going to

be looking at some Auditors will ask for

a down payment in order to schedule you

in audit Begins the Auditors will use

every tool in their Arsenal to find as

many vulnerabilities in your code as

possible we'll give you some tricks in a

minute to make this a successful step

initial report after the time period

ends the Auditors will give you an

initial report that looks something like

this with all their findings listed by

severity usually categorized into highs

mediums lows informational noncritical

and gas efficiencies High mediums and

low represent the severity of impact and

likelihood of each vulnerability

informational gas and non-critical are

findings to improve the efficiency of

her code code structure readability and

best practice improvements that are not

necessarily vulnerabilities but more

ways to improve your code mitigation

Begins the protocols team will then have

an agreed upon time to fix the

vulnerabilities found in the initial

Auto report sometimes depending on the

severity of the findings this might mean

you have to start from scratch but more

times than not you can just implement

the recommendations the Auditors give

you this is usually much shorter than

the audit itself final report after the

protocol makes these changes the audit

team will do a final audit report

exclusively on the fixes made to address

the issues brought up in the initial

report then hopefully the protocol and

Auditors have a great experience

together and will work together in the

future to keep web 3 secure now there

are a few key things that you can do to

make sure your audit is successful as

possible to get the most out of your

audit you should have clear

documentation a robust test Suite

ideally including fuzz or invariant

tests code should be commented and

readable modern best practices are

followed there should be an established

Communication channel between developers

and Auditors during the audit and an

initial video walkthrough of the code

should be done before the audit starts

the most important part of the process

is going to be during the audit to get

the best results you want to think of

you and your auditor working together as

a team one of the best ways to do this

is to have a dedicated Channel where

Auditors can ask questions to the

developers the developers will always

and forever have more context over the

codebase than the Auditors ever will

because they have spent so much more

time working on the codebase and the

more documentation context and

information that you can give to the

Auditors the better this way it can be

easy for anybody to walk through the

code and understand what it's supposed

to do in fact 80% of all bugs are

actually business logic implementation

bugs this means that these are bugs that

have nothing to do with with some weird

coding error and are just somebody not

knowing what the protocol should be

doing so it's vitally important that the

Auditors understand what the code should

be doing having a modern test suite and

tooling can also make Auditors spend

less time fidgeting with your tooling

and more time finding issues post audit

we highly encourage you to take the

recommendations your Auditors give you

seriously additionally after an audit if

you make a change to your code base that

new code is now un audited code it

doesn't matter how small the changes

we've seen a ton of protocols saying oh

I'll just slip in one line of code and

sure enough that's the line of code that

gets exploited and often depending on

the seriousness of your protocol and how

many users you want to use it one audit

might not even be enough working with

multiple Auditors and getting more eyes

on your code will give you a better

chance of finding more vulnerabilities

what an audit isn't now here's the thing

an audit doesn't mean that your code is

bug free an audit is a security Journey

between the protocol and the auditor to

find as many bugs as possible and teach

the protocol different methodologies to

stay more secure in the future sec is a

continuous process that is always

evolving no matter how much experience

someone has people at all levels have

missed vulnerabilities on the

unfortunate day that that happens be

sure that you and your auditor can jump

on a call quickly to try to remedy the

situation and maybe consider getting

insurance for your protocol as well so

now with that being said now you have a

good idea of what a smart contract audit

entails and what to expect end to end a

smart contract audit is a security

Journey endtoend leveling up your

protocol so that you can have all the

best practices and security know how to

deploy your code to a live blockchain

forever and of course if you're looking

for an audit be sure to reach out to the

cyphon team Link in the description and

as always stay safe out there and we'll

see you next

time all right great welcome back so now

that you know a little bit more about

what a smart contract audit is let's

talk about the process that smart

contract Auditors and Security

Professionals take and the tools that

they use security is both for protocol

developers and for auditors you as a

smart contract developer need to know

all these tools and probably should use

all these tools before you even go to

audit at the end of the day it is you

who is responsible for the codebase that

you launch and additionally you often

can't just do security at the end you

have to have security built in from the

architecture from day one for example if

you build a car and the car is a total

piece of garbage and you say hey cool

it's time to race you're probably just

going to have to start over and and it's

not a very good use of time for you to

even go to the audit there are some

tools like security which which have

opinionated security and code quality

standard for solity smart contracts and

we showed you the simple security

toolkit from n XYZ for great places to

read before you go to audit and make

sure you have checked off or you've

looked at this doc to make sure you're

even ready to go to audit anyways let's

talk about the audit process so there is

no Silver Bullet but typically the smart

contract audit process goes through a

process of manual review and then using

tools and there are a ton of tools

Security Professionals use to make sure

code is secure now manual review is

probably one of the most important if

not the most important tool that we have

in our toolbox manual review is

literally going through the code line by

line and going through the docs and

making sure the code actually does what

it's supposed to do there's kind of a

joke in the developer Community where if

you just read the documentation for 15

minutes you'd be way better prepared to

actually do code but a lot of people

don't do that so step one on any audit

is really getting some understanding of

what the protocol should do most bugs

are actually business logic issues and

the only way you'll know if business

logic is wrong is if you understand what

the protocol or the business should do

and repetition is the mother's skill so

the more you read code the more you read

docs the more you do these audits the

better you'll get for example for

example if we had a contract like this

this caught with past we have this set

number function this code technically

isn't wrong right it'll compile fine

it'll deploy fine but maybe if we read

the docs and we read that set number was

supposed to set number to new number we

would then read this function and go oh

my gosh you're setting it to new number

plus one that's clearly wrong right and

the only way we would have caught that

bug is by understanding what the

function should be doing so that's

manual review now let's talk about some

of the other tools that we have in our

tool box here the first line of defense

is going to be test Suites which is why

we spent so long in this course writing

test Suites all the most popular

Frameworks out there have test Suites I

don't really need to go over them

because you have already done so static

analysis this is something we haven't

gone over static analysis is going to be

automatically checking code for issues

without executing anything hence the

debugging is static most of these tools

were sort of just dumbly look for

keywords in specific spefic orders and

AI is actually going to be an example of

static analysis as well and we'll show

you an example of all of these once I

get through this fuzz testing we've gone

over fuzz testing involves providing

random data as inputs during testing uh

we have stateful fuzz testing which

we've definitely gone over in this

course as well differential testing

which we aren't really going to go over

but it's a way to actually write the

same code multiple times and compare the

code against each other but then finally

there's formal verification now formal

verification is a generic term for

applying formal methods to verify the

correctness of Hardware or software

applying FM means anything based off of

mathematical proofs in software often

used as a proof of correctness or proof

of bug or just mathematically prove that

something in your code can happen this

can be a little bit confusing obviously

um but to me the way that I generalize

it is you basically take your solidity

function you take your solidity code and

you convert it to math and math can be

solved math has right and wrong answers

1 + 1 equals 2 right so we convert our

solidity code to math and then

mathematically prove or disprove it

symbolic execution is one of these

formal verification these formal methods

and symbolic execution involves

converting our code to a mathematical

expression there's some tools here like

Matt Manor Z3 zeror even the solidity

compiler actually has a symbolic

execution ciment there is a fantastic

article on hackam D by Paulina who goes

over some of these different symbolic

execution clients and Compares them to

each other I left a link to this of

course in the GitHub repo associated

with this course symbolic execution is

one of these tools that is the most time

intensive and a lot of protocols and a

lot of audit firms don't even go down

this route because even symbolic

execution isn't a silver bullet it's not

a guarantee that some code has no bugs

it's not a guarantee code is bug free

but especially if you have some

incredibly math computationally heavy

process symbolic execution or form of

verification might be a good tool to use

AI tools AI tools are a work in progress

long story short sometimes they're okay

and sometimes they're absolutely

terrible all right so now that we know

some of these tools let's actually see

them in action and I'm going to go kind

of quick here but what we could do is if

we're in the GitHub repo associated with

this course you can actually download

this Denver security re now this does

not have the- f23 at the end of it

because this is a lesson that I've done

in the past but it is associated with

this course what we'll do though is

we'll just clone it we're not going to

build a project from scratch here we're

just going to look at some code

ourselves so we'll do get clone paste it

in do code Denver security we'll open

that up in a new tab here and I and I

want to just show you how bugs can be

found with some of these different tools

here so in our SRC folder we've got a

couple of files here we have caught with

fuzz caught with manual review CAU with

slither staple fo symbolic CAU with test

Etc each of these has a bug in them

where one of these methods was going to

be how you catch it our first one CAU

with manual CAU with manual review we'll

do a toggle word wrap the way we can

catch this bug is just with manual

review right so we have this function do

math and the comments or the docs here

say Dev adds two to number two add and

returns it we can then easily read the

code and say oh my goodness we're only

adding one boom that's an issue that's a

bug that's something that we would want

to fix that's how we would catch this

one next CAU with test. soul this is the

one that we saw in the presentation that

we gave set number should set the number

a unit test would easily catch that this

was wrong all right what's next static

analysis or Slither now this is

something we haven't really gone over

but one of the most prevalent hacks in

this industry is going to be a something

called a re-entrancy attack and you can

read more about it in the solidity by

example re-entrancy I've left a link to

this of course in the get AO associated

with this course but they're actually

tools that will automatically check for

stuff like this if I pull up my terminal

and I use this tool slyther I've already

gotten installed you can go ahead and

check out the install instructions

yourself but if I run slyther Dot

it'll automatically compile my codebase

and then it'll give this massive print

out of a ton of the issues that it found

and right at the top right in red you

can see hey there's a withdraw issue

there's a re-entrance issue with your

withdraw function and then obviously we

could go back update it rerun Slither

and this would go away so a lot of these

issues have tools that you can just run

and it'll automatically detect so

slyther is one of these tools that I

think everyone should run on their

codebase before going to audit what's

next we've caught with fuzz which we

know what fuzz is we learned about

fuzzing we have this massive function we

see this here say should never return

zero so there's probably a fuzz test so

if we look in our fuzz test we actually

smartly wrote a test fuzz here where we

say hey the return number from that

function should never be zero we can

then grab that Forge test Forge test

d-mt what's it called test fuzz and we

see we get a failing test here we see we

found that if it passes 1

265 it actually will fail come back to

our test here and we can see there's a

conditional if my number equals 1265

1265 modular 1265 is going to be 0 + 1 -

1 * 1 is 1 which means it return zero we

don't want this to return return zero

which means we break our

invariant if we call change value with

zero it'll set my value to zero up here

and then we can call do more math again

with zero we're going to get 0id 1 + 0

return Z and boom this will break as

well and then finally we have symbolic

here where we can actually just use the

solidity compiler to do symbolic

execution we have these two functions

Function One Function One symbolic where

we have this revert in here and this is

going to be the bug in solidity we can

add asserts to our code base and we'll

go over a video that explains this more

in depth to tell our solidity compiler

hey this should not hit and this should

hit this conditional should not be hit

this one should hit in Foundry in our

Foundry doomo we can add information in

here to send to the solidity compiler

we're going to tell that our solidity

compiler to use the CHC model Checker

time out of 1000 and to look for those

assert keywords and if we just run Forge

build or Forge build-- fors to force it

to rebuild it'll compile and it'll give

us this output here saying warning CHC

assertion violation happens here meaning

it found an issue it found an input such

that this assert line hit so if we pull

up our terminal we can scroll down we

can see exactly we can see exactly what

the input is

8088 is the input that will allow that

to hit if we look 8088 / 4 does indeed

meet this criteria so it would go ahead

and revert here so those are some of the

tools we have in our toolbox we'll go

over symbolic execution a little bit

more but let's wrap this lesson

up so to talk to us more about the

process of manual reviewing we have

legendary ethereum smart contract

researcher tincho to walk us through his

process in a real process of him going

through ens he did an audit on ens Just

for kicks and ended up getting paid out

$100,000 for finding a critical

vulnerability so let's learn from

legendary manual reviewer tincho

this is Tino ethereum security

researcher previous lead auditor at open

Zepp and creator of damn vulnerable Defi

and today we have the pleasure of

talking with tincho going over his

auditing process so that you can learn

how to make damn un vulnerable

defi to do this we're going to be doing

a live mock audit of the ethereum name

service GitHub seeing exactly some of

the tools and techniques that tinel

would use to audit this I don't have

super formal auditing process I really

think that everybody will find their own

ways I will just show you briefly some

things that I do today link to the full

interview in the description let's get

froggy so this is a repository for inss

the first thing that I would do is

obviously go to repository you would

clone the repository to my local

environment but if you're like very

unfamiliar you should probably go to the

documentation at least I don't know read

the introduction now he says there's no

formal audit process but this sounds

like a good step one download the code

read the documentation read the

documentation here we have the

architecture is telling us like already

some keywords that we will need to

understand at some point such as what a

registry is what a resolver is already I

will get familiar with this probably

these are contracts that I'm about to

see in the code and so on and so forth

one thing that you can do also after

reading some documentation is looking at

audit reports if we go to the actual

code we will realize that there are lots

of things wait a minute what the heck is

that look logo what wonky text editor is

tincho using that my friends would be

vscodium it's different from vs code vs

code is a product owned by Microsoft

that actually sends a lot of your usage

information over to Microsoft vscodium

doesn't do this they have removed I

think Telemetry and some related to

Microsoft tjo said he's just been trying

it out recently but maybe it's a

security Alpha leak so multiple

contracts in here already we see that

lots of folders it's using harad from

what I can tell these days I like that

use Foundry more than those that use

herut so in that case what I would do is

I created another folder in which I have

a Foundry local setup why do you like

Foundry better why do you make this

Foundry local setup it's faster and I

can write quick test only using solidity

I will do whatever thing that I want to

do here but just an easy way to have

something quick and dirty to test things

quickly bring and use the tools that

you're most familiar and best with I

think that's super important and don't

be afraid to bring your disgustingly

horrible dirty dirty

tests but anyway already we saw that

it's quite complex so what I would do in

this case is there is a command L

utility that I would use which is called

celoc celo will help you count lines of

code and so I would use celo it would

give me a nice output that you can

actually pass to a CSV and instead of

doing this here what I would usually do

is I would move that to a spreadsheet I

have the scope for in right all these

files are now ordered here and now I can

have a view in terms of how many files

do I have how complex they might be so

apparently I have 59 files and now I

know the name wrapper will be one of the

most complex conts perhaps right because

it has more than 700 lines of code

another approach to do this scoping

phase you can actually use this tool by

consensus which is called solidity

metric so you can run it on a project

and it will actually give you a nice

report of the code ways and level of

complexity and then I have a column

stating where the thing that I do is not

started it's in progress or it's done so

this is his next step he either uses

solidity metrics or CL loock ranks out

the contracts that he needs to audit

based on complexity and starts going

through it moving contracts from not

started to in progress to done a very

organized approach when you is alone in

might seem silly but when you work in

teams it's quite important as the a

progresses I will be less and less

focused on this file because probably

this is super complex and will related

to either but most of all it's very

useful at least for me at the beginning

of the just understand what am I looking

at once I have this table I usually

start with the little Legos and then I

go move up in complex so in this case I

will probably I don't know start with

the erc20 recoverable contract here it

is and it's quite short say okay it's

ownable inheriting from open saing as

aitor probably I can take that for

granted which is out of the scope and I

will assume that's working correctly and

it has a single function to recover fun

okay it has access control so this is

probably fine as long as they are

handling access controls in the right

way this is fine and it's actually doing

this right so we start with the small

little building blocks or Legos as

tincho said and now you're going to see

Tino's brain start switching into how

can I break this as an aor you might

start wondering where this is good for

any token out there right where it's

possible to actually execute a transfer

on any address that the owner passes

here and where that could be problematic

for behaved erc20 tokens and if you're

familiar with usdt for example that

could be problematic in this ah now

we're seeing him drawing on his

expertise knowing that usdt is a weird

token usdt actually doesn't return a

Boolean on its transfer froms whereas a

lot of other tokens actually do what

usdt when you see that only owner

function do you think okay is this a dow

is there a single person who controls

what are your thoughts at least at the

beginning I wouldn't worry about it too

much at some point I will read

documentation about roles of this but

yeah at some point I should probably

understand at some point Who's the

actual owner okay say that you think

that this is okay so what I would do

usually is I would take notes in the

code right so in this case I would say

like Access Control okay for example

just to have a note saying that I was

here or you can have a question like

Patrick said Is this governance right

let's say this was an issue so I would

do this shouldn't be I know let's say

shouldn't be owner another thing that I

do to take notes is actually have noes

files in the same place very R nodes

very having a file where I can quickly

dump ideas that I have some point things

so go well I would have an issues list

here I will start listing I know in line

blah blah blah of file blah blah blah

issues take notes in the code in a notes

file somewhere just have a place where

you can dump thoughts maybe you can even

use a note taking plugin I don't use any

plugins that's because I don't like

having the UI clut too much with stuff

yeah no taking extension was a dumb idea

and one thing that you have to be

careful when you start with the very

little things so it's very easy to go

deep into the rabbit hole of the single

thing that you are trying to AIT is as

for example I have very little knowledge

of DNS I'm not like super familiar with

the and I got like very like down into

DNS because I was just paying attention

to this single resolver and that led me

to realize that after I know two days I

was growing familiar with DNS but I was

losing the big picture of actually hey

I'm actually putting ens so it's very

easy to go deep into the rabbit hole of

the single thing that you trying to

audit remember to jump out of the rabbit

holes perfect so at some points in

during the audit you will realize that

you might need to test things so in this

case I saw these two functions one is

going from my bites thing she returning

an address and the other is doing the

other way around it you might say it's

okay but if you're lazy you can actually

use fun to help you in that so what I

did in this case I used my very hungry

hacky boundary repo that I have in here

and I actually copied these two

functions to a contract like I just took

them not even trying to do fancy Imports

or whatever just BR copying and pasting

them here and I did a quick test uh F

test in which I provide an address I

pass that address to this for function

and the result of that I pass it to the

other function and I want to make sure

that I always get the same address as I

said a lot of times yes you're going to

write code and not just do manual

reviews T here wrote what's called a

fuzz test which you should absolutely

smash that like button because we're

going to have a video on that sometime

in the future use your tools to validate

findings that you have an inkling are

wrong in the cases where I have to set

up more complex stuff perhaps having a

separate folder with a single project is

not that convenient because I would need

to set up the whole in system and that

wouldn't be that convenient so in those

cases I would go to the actual testing

environment of the project if you're

doing a private out how important is the

process of of talking and interacting

and and keeping Communications with the

client open I would say it's almost

fundamental usually developers will have

much more context than you as an auditor

on what the system is intending to do so

you can spend a whole week trying to

figure out on your own where this

modifier should be in this function or

not but if you actually send a question

to the client and tell them hey should

this be here or not and they will tell

yes it should be here you can see it in

test blah blah blah you can see them as

companions during the O and you should

rely on them you can rely on the client

AO protocol is your code good you think

so hell yeah my work is done having said

that it's also important not to trust

too much at the end of the day they are

trusting you as the expert so in this in

that sense I would advise okay keep the

clients at hand ask questions but also

be detached enough since they built the

code they have spent more time time

thinking about the code and looking at

the code than you ever will ask them

questions and don't be afraid to ask

questions I guess at this point what's

the next step are we wrapping up now are

we writing the report up what do we do

next the thing is I always get the

feeling that you can be looking at a

system forever it there's always one

additional line that you can check

there's always one additional attack

that you can think of one additional

potential C my vulnerability and

everything so what I do is I time bound

myself to have a certain level of

confidence when you're shipping the

report that you did your best and you

thought of every single possible attack

or vulnerability that you could think of

in that limited amount of time time

bound

yourself when you're going through this

code how are you thinking of different

attacks like when you're looking at a

piece of code how do you get that

context of what different types of

attacks to think of yeah I don't have a

checklist very difficult to translate

experience in doing it have this

adversarial mindset of try to at least

there lots of knowledge that can come

from all every single day reading

vulnerability reports every single

daying or reading responsible

disclosures that are published reading

all this reports I read newsletters like

I don't know I have this constant influx

of in security related information to

solidity that little by little I think

you start growing the intuitions the

experience that actually help you

identify quickly things that can happen

in smart contracts and always remember

that you can miss things there's no per

auditor I think that everybody has

audited sufficient enough and complex

enough systems they have all mied issues

and it's okay security is a is a thing

that we have to approach from many

different angles and auditing is just

one thing that must be done but is not

the only one knowing that you're doing

your best in that knowing that you're

putting your best effort every day

growing your skills learning grow and

intuition and experienceing you

something that I always say is to audit

to me is 50% finding vulnerability and

50% delivering readable report once the

client starts fixing the issues they

will send you the fixes for the issues

and what you have to do at that point is

actually review the fixes and make sure

that not only the vulnerability that you

highlighted in the report is fixed but

actually this have been introduced by

the fix and then you wrap up your whole

auditing process with writing a very

good report and take the time to do so

once you give them the report they will

go ahead and fix the issues come back

say hey we fixed them and then it's your

job to make sure that they fix the

issues and they didn't reintroduce new

bugs let's say you give your audit

report done your time box you've done as

much as you can you think you did a good

job four months goes by oh my God 100

million dollar hack they've ended it up

on wrecked what do you do what happens

let me approach you slowly okay all we

first say I have always been of the idea

a security code review should be

valuable enough beyond the fact that I

find or not find a critical issue so I

should be able to provide value to

whoever is working with me to whoever is

trusting me beyond the fact that I did

or did not find a crial isue obviously

the less critical issues that you miss

the better the safer and perhaps they

miss something and that can happen and

has happened and will continue to happen

but it's naive to think in my opinion

that just because an auditor miss

something whole blame of thing is on the

audit this I think is a really important

final thought you as an auditor it is

not solely your job to make sure their

code is bug free you share that

responsibility with the client however

this doesn't give you free range to suck

at your job people will notice tcho

thank you so much for being here thank

you for all you've done for the web3

community and I'm sure everyone will get

a lot from this okay padrick thank you

for inviting me bye bye

[Music]

so to understand symbolic execution a

little bit more we've got some members

from the trail of bits team to teach us

about symbolic execution and formal

verification formal verification is the

act of proving or disproving a given

property of a system using a

mathematical model symbolic execution is

is one technique used for formal

verification symbolic execution explores

different paths in a program creating a

mathematical representation for each

path or more plainly converting your

code to a set of mathematical

Expressions is this the Silver Bullet

for your auditing Journey let's get

froggy I had the absolute pleasure of

interviewing trailer bits head of

engineering Joselyn and security

engineer from Trailer bits as well Troy

about fuzzing testing methodologies and

importantly formal verification I have

links to the full interviews with both

of them in the description and in this

video we're going to summarize a lot of

that and focus on what formal

verification and symbolic execution

actually are but to do that we need a

quick refresher on some of the testing

methodologies that we use in web 3 if

you haven't seen my invariant testing

video be sure to watch that first before

coming here and to really understand

this you do need at least a high level

understanding of solidity as well what

tools do we have in our toolbox to have

high Assurance about our program layer

one the unit test obviously you have

unit test which you do a very specific

thing like this function does this and

you start looking at things like test

code coverage like statement and Branch

coverage and I think that's kind of the

bare minimum the absolute bare minimum

in security is a unit test for example

if this is our solidity and we have a

set number function which should set our

number variable to whatever new number

is a unit test would be able to catch

this and if we're using Foundry we could

get an output that looks like this so

I'm assertion failed and we can go see

our test and see that when we call set

number toine number we assert that we

get what we want and if that breaks cool

our unit tests have saved us Foundry

hard hat apworks truffle brownie and all

the most popular Frameworks have unit

test built in Layer Two the fuzz test

fuzzing is where you take random inputs

and run them through your program as you

have to Define things in your code that

you always want to hold true and fuzz

testing is the new bare minimum for web

3 security because I decree and as Troy

said you need to understand the property

or invariant of your system to do

fuzzing once you have your property

defined you throw random data at your

system in order to break that property

if you find something that breaks it you

know you have an edge case that you need

to refactor your code to handle for

example if I have a function like do

more math and I know that this function

should never return zero I can throw a

whole bunch of random numbers in here to

try to get it to return zero I can have

a fuzz test that looks like this which

passes in a whole bunch of random

numbers and tries to assert that we

never get zero and we can see from our

fuzz test it was able to pick a random

number in order to break our invariant

or property now like I said we recently

did a video on fuzz testing or invariant

testing and I highly recommend everybody

watch that video because I de create

Foundry AK kidna and consensus diligence

fuzzer are some popular fuzz testing

tools okay what's next layer three

static analysis so the things that we've

been discussing unit testing and fuzz

testing or dynamic testing which Dynamic

just means like you're you're actually

doing something Dynamic analysis is when

we run or we execute our code in unit

and fuzz tests we do exactly this we are

running our code to try to break it in

static analysis we just look at our code

or have some tool look at our code for

example this code here has a classic

re-entrancy vulnerability in our

withdrawal function if we run a static

analysis tool like slyther it'll

automatically detect hey you have a

re-entrancy vulnerability and this is

great for very quickly picking out very

specific parts of your code that are

known to be bad practice some popular

tools for static analysis are going to

be Slither created by the trail bits

team and even the solidity compiler

could be considered a static analysis

tool so now that we have a little bit of

a backstory on some of the popular

layers of testing and keeping ourselves

secure let's jump into formal

verification and symbolic execution now

layer four formal verification so on a

high level formal verification is going

to be the act of proving or disproving a

given property of the system this is

usually done through a mathematical

model of the system and the property

there's that word again property you're

seeing that almost no matter what you're

doing in your testing you need to

understand the properties of your system

and right there JN gave us some of the

keys between fuzz testing and formal

verification fuzz testing tries to break

Properties by throwing random data at

your system whereas formal verification

tries to break properties using

mathematical proofs and there are many

different ways to do formal verification

such as symbolic execution and Abstract

interpretation for this video we're

going to focus on symbolic execution as

that's one of the most popular ways

currently done in web 3 symbolic

execution is then one of the techniques

that you can use to do formal

verification symbolic execution on a

high level is going to be a technique

where you are going to have your program

and you're going to try to explore the

different path of the program for every

execution paths you're going to create a

mathematical representation additionally

if you want to learn more about symbolic

execution outside of web 3 I left a link

in the description to an MIT open

courseware video which does a great

rundown of symbolic execution now let's

look at Jin's example of using formal

verification and symbolic execution

let's say this is our function that we

want to do formal verification on and

we're going to do symbolic execution to

do form of verification well let's go

back to what formal verification

actually is formal verification is the

act of proving or disproving a given

property of a system using a

mathematical model so the first thing we

need to do is figure out what we want to

prove or disprove for our demo we should

say our invariant this should never

revert and that's what we're going to

try to prove or disprove now this might

seem like a silly example but you can

imagine that this was a function called

withdraw money and you want users to

always be able to get their money out

which would seem like a much less silly

example symbolic execution is going to

be creating a mathematical formula for

this function f from our code we're

going to convert this function to a

mathematical logical representation of

every execution path from our code once

we have a set of math functions we can

push those into a solver which will tell

us if a property is true or false or if

our invariant is true or false when we

talk about the different Paths of our

function we can imagine okay one path

that our function can take is going to

be a + 1 being returned that's going to

be one of our paths but we can also

imagine that a + 1 is actually going to

overflow and therefore revert if we pass

in the maximum U 256 A+ 1 would revert

so that would be a second path that our

function could take and a symbolic

execution tool would find this second

path for us programmatically and then of

course convert these to a set of

mathematical Expressions this set of

mathematical Expressions might look

something like this a and also not a

imagine if you ask somebody can this set

of mathematical Expressions be true at

the same time the answer would obviously

be no it is impossible for both a to be

true and a to be false this is what our

solver is going to figure out for us but

with much more complicated Expressions

than this in our example the solver is

known as a SAT solver or an smt solver

and there many different types of

solvers but I'm not going to go too deep

into that right now running our symbolic

execution tool we would see two paths

our first path going to be if we give it

the maximum size of a un 256 we try TR

add one to it the function will revert

solidity doesn't allow you to add one to

the maximum size of a un 256 the other

path is anything lower than the max size

of un 256 we'll just add plus one and

then return so those are going to be our

two paths path one a is not 2 ra 256 - 1

and then a returns normally and a is 2

ra 256 and it reverts however instead of

a b c not a etc our symbolic execution

tool will give us an output that might

look something like this now what you're

seeing on screen is an smt lib language

and it's a language specifically made

for working with these solvers to solve

our mathematical representations of our

code I'm not going to go over too deeply

what this is doing but you can consider

this just a list of Boolean Expressions

kind of like a and not a and if a

therefore B and A B and C Etc now if you

take this code and paste it into a tool

like Z3 or run it locally on your

machine it'll give you an output that

looks something like this sat and sat

this first that is saying they were able

to find an input for path 1 and they

were able to find an input for path two

they were able to satisfy the booleans

in those different paths since it was

able to satisfy an input for path two

and we know that path 2 reverts we know

that this invariant is now broken

because our invariant is it must never

revert and our mathematical

representation said hey I've

mathematically proven that there is a

scenario where path 2 is executed and

your function reverts so sat here means

we mathematically proved that this

invariant breaks now I manually created

this smt lib list with the help of chat

GPT however symbolic execution tools

like mantacore hvm and even the solidity

smt Checker can give you this smt output

but all those tools come with a Z3 buil

in so they'll even just skip this step

and just give you hey is my invariant

broken or not even the solidity compiler

itself can do this entire process behind

the me explore the paths convert the

paths to a set of Boolean and check to

see if those paths are reachable or not

using the so compiler we can run with

model Checker engine and we can look for

an overflow in small soul. soul and if

we run this you'll see the solidity

compiler was able to do symbolic

execution to find out hey if I add the

maximum unit 256 as an input to here

you're going to get an overflow and that

function is going to revert now

obviously reverts are pretty easy to

find but we can even add assert a does

not equal 1 rerun this but instead of

overflow look for asserts and we would

see that again it was able to

mathematically find an input to break

our assert or our invariant said if you

add zero you're going to get one asserts

are what you're going to use if you want

to use more complicated and more

specific symbolic execution rather than

just overflow or underflows tool like

mantor will also give you an output with

the revert as well as a much more hypers

specific list of S&T Li that it's

inputting into its Z3 solver so a lot of

stuff just happened here let's recap we

built some solidity we understood our

invariant and the next two steps

happened at the same time with sulk or

manacore we used a symbolic execution

tool like the built-in one to solidity

to create a set of bluing Expressions

that represent every execution path of

our code and then we dumped them into a

solver like Z3 to see if our property

could be broken just by running this one

function solidity was able to do all

those steps behind the scenes for us we

go through a full walkthrough of this

example with the interview with JN so be

sure to check that out as well if you

want to learn more and don't be afraid

if this seems a little bit complicated

be sure to ask questions leave comments

in the descriptions and leave a like as

well and hopefully I'm going to clear

this up for you sometimes the solver

might not be able to solve the equation

too like if the equation is too complex

you usually provide a time oute to the

server just because you know if you have

to invert hash function you know good

luck to do that with the server well so

you're saying this isn't a silver bullet

for auditing like any technology even

formal verification and symbolic

execution abstract interpretation the

these are not a one-sized fits-all

approach using symbolic execution can

run into something called The Path

explosion problem where there's too many

paths for a computer to explore in a

reasonable amount of time and a solver

would never be able to finish how

practical is it to to take all these

steps how hard is this to really do well

there are a couple of things to consider

the first one is that this specific

technique symbolic execution as a couple

of limitation as you're going to explore

the different path of the program there

is a problem which is called the path

explosion problem which is basically if

you have too many paths to explore in

the program it's going to take forever

if you have an infinite Loop this

technique require significant effort to

be used you need to understand how they

work and you need to understand their

limitation and how to help them and also

significant effort to be maintained at

the end of the day I think what really

matters are the properties if you want

to know if a bug can occur and if the

property can be broken you don't

necessarily need formal method for that

and you can use a further which is way

easier to use and provide like kind of

the same type of value something that is

sometimes difficult for people is really

to understand how to create this

property and how to create enance for

themselves if someone wants to you know

learn a bit more we have this website

it's called secur track.com where we go

a lot of guidance and best practices and

among other we have tutorial on how to

use Aina how to define inv variant how

to think about properties there's a high

skill requirement to using these tools

itively at the moment people are working

on making them easier and easier like

the built-in solidity smt Checker

however as Jon's been saying sometimes a

sufficiently powerful fuzzer is all you

need and if you combine a fuzzer with a

symbolic execution back end the fuzzer

can pick better random numbers based off

of the symbolic execution and maybe you

can find all the answers you need

without having to do a formal

verification test suite and the most

important piece here is that even this

isn't a guarantee your code is bug free

all it does is mathematically prove your

code does that one specific thing

correctly I'm hoping as AI takes off

doing a lot of this will become much

easier and I guess we'll have to see but

for now hopefully you learned at least

the basics of symbolic execution if

you'd like to learn more leave a comment

in the description if you want to see

more videos about form of verification

let me know but the takeaway from this

is that you should become a stateful

fuzzing wizard thanks all for watching

be absolutely sure to go watch the

interview with Troy and Joselyn links in

the description and we'll see you next

time

[Music]

now for those of you who are looking to

become Security Professionals smart

contract security Wizards there are a

ton of resources you should actually

check out I've left a link of course in

the GitHub repo associated with this

course to this comprehensive list of

known attack vectors and common anti

patterns it's got a ton of different

solidity attack vectors that you should

100% know about additionally if you want

to learn more on doing security there's

a phenomenal game by a developer named

tincho called damn vulnerable defi which

is a way to learn offensive security of

defi smart contracts in ethereum and

they've got these amazing games they you

can check out and play to learn security

ethernut is another game that is

absolutely phenomenal that will help you

to learn and understand solidity and

smart contract vulnerabilities for those

of you who are looking to become

Auditors definitely be sure to check out

solid it which is this amazing tool for

you to check out audit reports from the

top smart contract security Prof

Professionals in the entire industry of

course be sure to check us out at cyphon

we do smart contract security and

auditing as well if you are building a

protocol yourself definitely be sure to

check us out for your next project for

your next protocol for any and all of

you absolutely subscribe to web3

education. deev we have some amazing

surprises coming for you in the next

couple of months and I don't want you to

miss it there's going to be some awesome

opportunities for you to participate

learn and grow in top security so be

sure to put your email in here and this

is really just the tip of the iceberg

there's so much more to go when it comes

to security we are working on more

Security based education as well so stay

tuned for that but the prerequisite for

the security course is this monster

Foundry course anyway so you have

already taken the first step to becoming

a smart contract security badass as well

but all right guess

what that's it for the security lesson

congratulations I and the web3 community

as a whole want to congratulate you for

completing this absolutely

monstrosity of a tutorial you have done

an amazing job to get this far and to

watch me talking to you right now and if

you haven't finished the course go back

and finish it before coming here we have

learned so much on this journey and I

can say from the bottom of my soul that

I am so glad to have you in the web3

space smart contract space the

blockchain space the cryptocurrency

space we are so excited that you're here

I'm really looking forward to seeing you

in the web 3 in the blockchain community

now a lot of people ask well where do I

go now I didn't have all this new found

knowledge I'm armed with the

intelligence of the web 3 developer

space well I've left some links in the

GitHub repository to lend you to those

next steps but the biggest thing that

you can do for yourself right now is go

take what you've learned and apply it

somewhere this is going to be probably

the most thorough course you will ever

go through in this space and you can go

tutorial to tutorial and boot camp to

boot camp all you want but at some point

you have to make that leap and you have

to dive in and that's where the majority

of the growth is going to be anyways so

if you're here wondering where to go

next go join a hackathon go start

jumping onto issues on GitHub repos go

start applying for Grants go start

applying for jobs and say I took

Patrick's massive course here's my

GitHub repo work on a personal Project

work on somebody else's project take

this knowledge and apply it the

challenges that you'll run into and the

challenges that you'll face really

trying to do something without me

handholding you is where you're going to

learn 10 times as much is what you've

learned here I've walked you as deep

down this Rabbit Hole as I can take you

now it's up to you to go out and do

something with it so thank you everybody

who helped me create this course thank

you for taking this course and I so

excited to see you in the community and

see what you build and see what we can

create with this technology

Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.