chainlink eth scanUpgradeable Smart Contracts: Code Along

chainlink price prediction whiteboard crypto where do i buy chainlink chainlink eth scan Upgradeable Smart Contracts: Code Along
chainlink eth scan chainlink elastos Upgradeable Smart Contracts: Code Along
good morning good afternoon and good evening everyone welcome back to the spring 2022 hackathon um hope everyones been learning a lot so im starting my morning over here get to start it with a really cool subject upgradable smart contracts this is like a super important topic if youre going to ever dive deep into the smart contract world and start developing some really interesting gaps so um you know get some coffee if you need it this this ones going to be really heavy on explaining the kind of how this all works so were going to spend a good time up front talking about that we will dive into a demo at the end where we deploy some basic upgradeable smart contracts um oh and this will be very evm focused uh solana does have native features that allow upgrading smart contracts so its really not too too bad on there uh but yeah well be focusing on the evm so if you dont already know me my name is zach ish im a developer advocate at chainlink labs im a big fan of web3 if you didnt already guess and yeah im just excited to be here so i want to start this uh off with a little story about myself um a little story about my my good old tesla um so the story of how i got it and im not bragging youll see where this is going um ive owned old cars most of my life uh the newest car ive ever owned before this tesla model 3 was a 2004 mazda6 so about a year and a half ago i decided to treat myself to a nice futuristic car with all kinds of new features that was just constantly changing and then this happened um so this was like a little uh little uh before a year that i had the car and uh unfortunately uh gotta got an accident uh wasnt my fault no one was hurt but my car was busted and i couldnt drive it for six months and i was devastated luckily i just recently got it back actually this past week so ive been happy about that but you see the thing is teslas are always upgrading right so i got all back and it was all fixed and new and looking great and uh all the physicals were nice uh but i noticed that the ui had uh completely changed right and it was uh noticeably worse than the previous one in my opinion so you see teslas they update all the time over air and this puts a ton of responsibility in the hands of the software developers working on the tesla ui um so luckily it was just the ui inconvenience and not something worse um the tesla engineers are pretty good about uh not putting anything too terrible in the code um but upgradable smart contracts are much the same as um you know teslas you could only instead of um peoples lives in in the car you have billions of dollars and peoples livelihoods impedes peoples future in these smart contracts so this is a very important subject to make sure you understand whats going on and you get it right so were going to talk a little bit about the what and why of upgradable smart contracts today uh well move on to the migration pattern which is a very basic pattern of uh updating smart contracts and well get into the meat of it which is in the proxies overview so this is the most popular type of upgradeable smart contract and then well dive into the demo ill try to answer some questions throughout and you know in sections in between in between these sections and um yeah and well well try to also this may go on the whole time so well try to get some time for a break in between you know maybe halfway all right lets go ahead and dive in and yes gm everyone good to see everyones having a a good start or into the day middle of the day all right so upgradeable smart contracts isnt that an oxymoron right um smart contracts are supposed to be immutable and now were talking about upgrading and changing them um and yeah kinda is right um you see the code we deployed to a blockchain is immutable uh but we can have that code encoded in it to say we can change it which is funny but it is possible so like think about variables we can deploy a smart contract with variables set to certain values but we can change those values later on if the code allows us to so a really basic form of upgradable smart contracts is uh governance right so governance is really a type of upgrade dows dows often decide how and when to change parameters via governance methods such as token holder voting and using multi-sig contracts so heres a little snapshot i took of compound about a day or two ago and you see they were voting on some risk parameters on the maker and ave token you know if they were going to deploy some implementations and some partnerships right so why is it important that we want upgradable smart contracts well while the immutability property of smart contract logic has a ton of value and um you know very rarely are things designed and implemented perfectly the first time traditional software is updated for a variety of reasons you know including bug fixes adding new features and performance improvements if youve ever owned any computer ever you know what im talking about and sometimes the parameters of an app have to be dynamic and change to optimize for different external conditions if youve ever used a ride share service like uber or lyft you know that the price per ride isnt static it depends on a lot of variables including the length of the ride at the time of the day what kind of traffic is going on and how many drivers are currently active and as always the engineering you know mantra that all of these are tools uh all these techniques were gonna go over our tools and every tool has this trade-off it has the situations that its useful for right so throughout this workshop well were gonna talk about a couple of different methods for upgrading smart contracts i just want you to keep in mind as we go through these that these are tools they do all have trade-offs and they are all appropriate in their own ways depending on what you want to do with your smart contracts and were going to discuss some of those so this will take us to the first topic the first kind of upgrade which is a migration so one of the most basic ways to upgrade a smart contract is to create a brand new version of that smart contract and just deploy that somewhere else on the blockchain to a completely new address you then ask all your users to just start using the new one instead of the old one just like alices above you just then tell everyone hey move over here you know youre done new contract upgraded but not quite um it can be really tough of course to reach everyone right um and this means people can be left using the old version if youre not effective and and getting out the message or maybe people are just stubborn and they dont want to move because thats how people can be so if we look on the left contract here we have contract a you know has a two variables and a function do cool stuff so then we just uh add in our new function do cooler stuff sort of do cool stuff and we redeploy it it has a brand new address up at the top and thats you know and then alice is over here hey everyone move over to this contract so this has of course these are the trade offs for this method um it is very decentralized right people can opt in into moving into the new contract if they want its very similar to forking a blockchain where uh you know users have to socially decide to move to the new chain um we have more you know this this keeps it very decentralized you know theres no controls that can be sent off to some group that some group can kind of gather control of like in the in token holding voting for instance token holder voting cons its impossible to ensure that every single user knows to move and you never know that the old contract you could have upgraded because it poses some kind of security risk so you could have a bunch of users still on an old contract thats vulnerable to something like a reentry see attack or an oracle attack and they could lose a lot of money by staying there and switch it the switch naturally imposes friction to your users so if youre going to constantly upgrade your smart contract youre going to have to constantly tell your users to switch to the new one have all of the front-end applications switch to points into the new smart contract and this can just pose a ton of friction to your users and in the software world and really the design world friction is the enemy right and in terms of making very usable and ux friendly apps so if youre iterating quickly on a smart contract often this may not be the best pattern for you to use so lets talk about uh proxies now this is the next and the biggest kind of class of upgradable smart contracts on the evm you know lets talk about what a proxy is in general um proxies are generally defined as the authority to represent someone else or a figure that can be used to represent the value of something in a calculation essentially proxies are a stand-in for someone else think about going to traffic court and getting a large represent you there theyre essentially your proxy in that court process on the web proxy servers sit in between you the person surfing on your web browser and the server that youre visiting so if you connect to a vpn which uses proxy servers in the middle that vpn will sit between you and the website you want to go to so lets say you connect to your vpn you go to that that that request will first be sent to the vpn who will forward it to in your on your behalf will see this request came from your vpn and send it back to that vpn who sends that response back to you so the vpn sits in between you and the web server you want to go the vpn is essentially acting like you on the internet just like a proxy server sits in between a user and the server they want to communicate with um a proxy contract sits in between a user and the smart contract they want to talk to um it can forward transactions to another smart contract um so this diagram we have the user you know theyre using metamax to communicate with this proxy contract here and they send a transaction its got a message message.sender message.value and theyre calling this uh forward function with some data the forward function we dont know what the implementation is but it just all we know is affords it to this contract and it eventually calls do cool stuff on this contract and well get to do some cool stuff with a smart contract and so with a proxy contract we can actually change the contract that it points to and this is this lays the foundation for proxy style upgradable smart contracts right so here in this diagram weve now changed this variable contract pointer and instead of saying its this address up here for contract b we put the address for contract c the same function forward is still there and its still forwarding to do cool stuff but as youll see the function and do cool stuff and contract c really is doing new cooler stuff on the inside i know these terms are very technical um so you know this way the user can stay pointed to this proxy contract but you the developer can change the contract that the proxy itself is pointing to and in this way you get an upgradeable smart contract design so you may be asking if we do that how do we keep the same state across smart contract upgrades lets look at this example so again you know weve switched our pointer from contract b to contract c down here were saying function forward to do cool forward to do cool stuff in contract c but since this is a brand new contract contract c has a new instantiation of its state and this these variables user a tokens and user b tokens are reset to zero while the state was stored in contract b before and you know user a had 300 and user b had 400 tokens so thats not good so that means every time we upgrade our smart contract all our users are going to lose all of the information they interacted with that kind of makes it useless and that kind of really defeats the purpose of blockchains right and having this kind of global state this is why proxy contracts themselves must store all the state every time we deploy a new implementation this way um you know we wont be resetting any state right so here weve moved those state variables user a tokens and user b tokens onto the proxy and the proxy is still pointing weve shifted it to contract c still forwarding and now user a and user b retain their 300 400 tokens respectively so because the proxy is storing all the state really instead of a pure forwarding function we need the proxy to borrow the functionality from the contract is pointing to and run the contract on the proxy state well talk about how we implement this process in a moment but just imagine we had a function called borrow cool stuff instead of forward and this actually took the cool stuff function pulled it into proxy temporarily and used it to interact on its state and a little bit of terminology here when we use proxy contracts to create upgradable smart contracts we call the con we call the contract the proxy points to the implementation contract since it contains all the functionality of the smart contract but it really shouldnt contain any of the state of that smart contract right so youll see here the proxy again is only state and borrowing functions right functions that borrow from the implementations and the implementation simply includes all of our business logic like do cool stuff all right before we dive into a little bit of the low level of how this all works ill go through some questions in the chat all right can you make a video on how to reduce the gas cost in our smart contracts yeah theres actually a workshop later today that is on evm opcodes and optimizing gas using that so if thats what interests you definitely try to make it out to that workshop yeah opcodes is a really interesting field uh interestingly this study in my opinion and you can really get some cool gas optimizations with that what if a state needs to be removed um thats an interesting observation so um you know when youre updating your implementation it would be possible to add in a function that removes some kind of state so like lets say youre going lets go back and look at our contracts examples if youre going from contract b to contract c uh the function and do new cooler stuff here or we can create a whole new function like erase token user a tokens right um you could do that but as you can see this is something that um could be very dangerous right if if done improperly in this case it could be erasing a whole users tokens which is not good in general this is something you wouldnt want to do right all your users are using your smart contract they expect their state to stay their state and so this might not be something you want to do but if you do decide you know hey im just changing a flag or some kind of indicator my smart contract then just make sure youre getting your smart contracts audited and youre doing it properly what what role does upgradeable smart contracts play in auditing um so auditors will definitely look at your upgradeable smart contract scheme um and see how it works and see if theres any risks to the users so they play a very big role in in the audits and thats why all this is so important so when youre implementing this you understand what kind of trade-offs youre introducing to your users with different schemes right theyre going to look and see if youre upgrading it what accounts have the ability to upgrade those smart contracts and whos holding the keys and what can you change what kind of functionality is in in the implementation going forward were going to talk a little bit about how some of the standards limit developers and how much they can do and thats generally a good thing how about inheritance hierarchies thats a great question i mean i i dont talk about it a lot in this this video but um you can have inheritance hierarchies in this um of course that requires all of its own kind of covering but you can do inheritance stuff its just gonna um come with us own hassles is the proxy a smart contract is the park street contract itself upgradeable um yes the pro the proxy is its own smart contract it points to another smart contract again like in this example this proxy is a smart contract and its sitting in between this user and contract c so um yes and yeah you could actually make the proxy contract upgradeable you could uh feasibly imagine a third tier of contractor sits in between this user and this proxy and then contract c uh but then were just going into like proxy inception um generally you dont want the proxy to be upgradable right like um this is kind of the whole point of proxy and implementation proxy stays stable your users just point to that the implementation is what you change oh this is a tough question we got melody where is the cat uh yeah my cat is in my room so he doesnt knock over any of my streaming equipment or chew on any of my cables are genuinely annoying me while im presenting how easy is it to roll back changes during a failed upgrade not easy right once you upgrade a smart contract it goes out there and users are going to start using it immediately because the the pointer will point to that on the proxy will point to the new contract and so you know we go here the proxy is pointing to contract c now and its doing new cooler stuff but if that new cooler stuff turns out to be not so cool and partial and risky to the users theyll automatically be exposed this is why its really really important to get this right up front make sure everything is set and every upgrade is um you know reviewed its uh transparent your users can see that its about to happen uh the code is thoroughly reviewed and audited this is all essential what if we want to upgrade by implementing new functions this allows that um you know once you deploy a smart contract you cant change it right like once we deploy proxy uh we cant add another function to proxy um in general other than forward but were going to talk about the specifics of how we can add functionality from contract b to contract c like if we want to add a new function you can definitely do that and one last question before we move on that means we are not upgrading the contract but configuring the state of proxy to route to a new different contract exactly you got totally all right so yep we kind of just generally talked about the proxy pattern and how we want to really borrow functionality from implementation we dont want to just forward you know so were acting on the proxy state and to understand how we can do that were going to dive a little bit about what happens under the hood in the evm specifically were going to talk about evm opcodes which again therell be a more detailed talk on this subject later in the day but when you write code in solidity its being combined by the solidity compiler which compiles it to what we call an intermediate language or bytecode right and this byte code is whats actually sent to the ethereum blockchain and this is what the ethereum nodes run when youre calling a smart contract and so if we want to forward a function a transaction from a proxy contract to another contract we really have two main op codes that are going to be used in a smart contract in the back end right you have call and you have delegate call and i have delegate call hided highlighted because this is the one were going to use for upgradable proxy patterns right call is totally useful and has its use cases uh when developing smart contracts but for upgradable delegate calls is going to be the key op code were going to look at and this is what were going to focus on for this workshop so another little background uh on how the evm stores data so ive talked you know just briefly on opcodes and that there are these op codes call and delegate call but how does a smart contract store state in the background and youll see why this is important in a bit um so the evm in the background doesnt know variable names it knows what are called slot locations and so when a smart contract is deployed an evm automatically creates whats called uh it creates two to the power 256 slots its like an array right for smart contracts to store data on the blockchain um and the solidity compiler maps variable names two specific slot locations for you right so you dont have to worry about the slot implementations when programming in solidity the compiler takes care of it and when you initialize um all this all these slots for your smart contract to store data theyre all initialized at the value 0 in every slot and remain that way until the value is assigned to them and so lets kind of look at this diagram to get a good idea of what im talking about right so we have this contract a and we have three variables here user a tokens user b tokens and user c tokens and this function and so here we have each of those variable names user a tokens b and c the solidity compile compiles those into bytecodes and automatically replaces them with these slot locations zero one and two right so two in the byte code user a tokens is this slot location zero x zero and user b tokens is actually this slot location zero x one and this is when you deploy contract a and theyre all initialized at zero we havent set them to any values yet yes up codes without cats is tough um you know hes having a good time hes chilling this is his like nap time he he went crazy this morning so i think hes gonna be all right but uh you know maybe after our break later i can uh bring him out for a cameo um all right so this brings us to that back to that delegate code op code right delegate call um so when delegate call is uh forwarding a transaction to another smart contract it will for that transaction in the context of the original user who sit that transaction right so lets look at this diagram again this is going to be a very diagram heavy very diagram heavy presentation right and so we have this user theyre using metamask right and they send a transaction and what i mean uh in this transaction is representative of their wallet right so it has their address as message.sender that just says hey this is my this is the address of the wallet sending this transaction has some kind may have some value of eth attached to it its calling contract b uh it wants to call this function call contract b with data its own data and this actually should say not call contract b but borrow amp here right and so theyre actually trying to call this function borrow amp and borrow imp calls delegate call on this implementation contract variable were pointing to right here so this contract here and it does delegate call and then delegate call will keep the message.sender of the user so this is super important it wont replace this with the message.sender of the proxy contract to the implementation contract its still this user calling even though uh its this contract actually delegate calling right and it keeps the message i send our message our value in the data so remember what i said earlier though we dont want just forwarding because the proxy contract stores all our state and we want to you know have that functionality work on that state right that shared state among all the users so what do you think will happen in this context if we delegate call to this implementation over here right um so in this case we have the user theyre sending a transaction um theyre gonna call this function uh add one to number right um oh no sorry theyre gonna call borrow imp right here and borrow imp is going to delegate call to the implementation its going to forward all those transaction values again message our sender message.value and but instead of running add one to number and the implementation contract and incrementing this variable number here by one its going to borrow that function its going to run it in its own context so its going to run add one to number and thats going to increment number one and the proxy now remember what i said earlier that in the back end um in these smart contracts they really dont know variable names they know slot numbers and the slippy compile takes compiler takes care of that for you right so when it borrows it the function add one to num its not actually going to have this num plus equals one like it is here its going to say hey get that storage evm storage slot 0x 1 and add plus 1 to that right so turns out here that this would this imp variable would have the storage slot zero x zero and our number uh variable would have zero x one so its gonna add one to our number so um the transaction has ended the number and the variable uh the variable in the proxy contract has been incremented by one and uh the prongs the proxy no longer has that function in it add one to num right thats it borrowed it its gone it doesnt have it anymore until this function borrow imp is called again so now youre going to see why we talked about storage slots right because remember when the proxy borrows functions and those functions change state it doesnt know the variable names it knows the slot numbers and so if your your proxy has state and the function is referencing a different slot number than what you want to change in the proxy uh mistakes can happen right so lets look at this as an example function borrow imp is going to delegate a call and its going to borrow the functionality of add one to number right and add one to num and the implementation contract is referencing this variable a which is that slot 0x0 for this contract right and its going to add 1 to that so when the proxy borrows this function into here its going to say hey add 1 to the variable at slot 0x0 well in the case of our contract thats the pointer to our proxy or our implementation contract right and so were going to add one to this byte and this all these bytes and now youre going to break our pointer our contract proxy is broken are you its going to be chaos for our users um its uh not a good time and this is called storage clashing when you know the wrong variable is referenced via its slot so now weve talked about some specific op codes you know call delegate call and how delegate borrows weve talked about you know storage slots and how this could result in storage uh clashes were going to talk about one more low-level concept here function selectors so just like just like variables are actually identified as storage slots under the hood functions are identified by their function selector which is a four byte hash of something else called the function signature now that thats a mouthful i know lets walk through it and well understand right so again here weve got contract a three variables and two functions one function of course our favorite do cool stuff because we always want to do cool stuff and um another function add and add just takes in two uints and returns the sum of those two units right and so here we have the function name of these two functions we have the function signature now youll notice what the function all the function signature is is the name of the function along with the types of any parameters for that function right so do cool stuff doesnt take in any arguments doesnt have any parameters so the function signature is simply the name but add takes in two units as its um as its parameters right so its function signature is the name but we say u and 256 comma u and 256 um you know inside the parentheses parentheses as the function signature um and so and youll notice also in the function signature note that there is no ver uh the argument names the parameter names arent there so we dont have a and b referenced here and if youre wondering where the 256 came from uint automatically defaults to un-256 right so these two are equivalent and so the function signature can then be hashed and in ethereum world the hashing algorithm thats used often is catch act 256 and after the function signature is hashed we take the first four bytes out of that hash and that gives us the function selector right so we hash literally hash the text do cool stuff um and we get uh with we have we hash it with ketchup 256. take the first four bytes um and we get this function selector right we we have pin 0x and the first bytes nine zero second seven b third byte five four and fourth byte bc right and if we hash the signature of add with get jack 256 this will be our function signature so why am i talking about this well remember when we call smart contracts um on the back end we think were saying hey call add or do cool stuff but really what the uh what the evm sees is hey i want to call function 0x907b54bc right they know the evm knows the function selector for a specific smart contract just like it knows slots for variables so just like we have variable slot clashes we can have function selector clashes it is rare but it can happen and this can be very dangerous just like the slot clashes so lets look at two functions with the exact same selectors right we have the function collate propagate storage which takes a single by 16 and the function burn which takes the unit and both of these functions have the same function selector right so um when you pass in to the contract um this function selector its just going to pick the first one that it sees so if you say hey you think youre gonna run burn uh your smart contract might actually run collate propagate storage and that could be doing something malicious right um or it could have unintended uh consequences to what the user wants to run this wont occur too often right it has about a one in four billion chance of happening um but thats still um you know a chance and its something that we we dont want to risk in our smart contracts right um if youre developing a smart contract so lets look at contract a here um the solidity compiler would actually catch this right it would prevent this from happening uh within the same contract so the solidity compiler will say hey coley propagate storage and burn they have the same function selector you cant compile this dont deploy it this is not good and so we dont really have to worry about it so much within the same contract but remember were talking about proxy implementation patterns here were forwarding or borrowing uh from one contract to another and so between two different smart contracts they may very well have uh function selector clashes right um so lets see so lets uh lets look at this example where this could happen right lets just kind of get an idea the user sends their transaction and theyre calling again theyre calling function 429668 right which is um this collate propagates storage on the proxy right um but it also matches with uh the function burn right so saying okay burn isnt actually on uh our proxy contract so there shouldnt be a clash right where normally um when were delegating using delegate call within our smart contracts its actually going to put delegate call within something called a fallback function right the fallback function is a function without a name um and it uh its what the contract falls back to if it doesnt know any other function to run right and in this case the user thinks hey im going to pass in this uh this function selector and i think im hoping that the fallbacks going to run and its going to borrow burn because its going to forward this function selector and im going to call burn and its going to do some action on my smart contract but instead it runs collate propagate storage and unfortunately this this function sends the users tokens to another address so now when they thought they were running some function on the implementation accidentally called collate propagate storage and they lost all of their tokens right so this uh this obviously caused not good things to happen to our user unexpected behavior and this is where proxy standards come in to help solve these problems like variable slot clashes and function selector clashes right lets not reinvent the wheel lets take advantage of people whove already solved these problems right and a great place to find pre-solved problems in libraries in web3 is open zeppelin and they really do have great library of these standards their code and documentation with how it all works were going to talk about these standards in a bit um and ill just forward this link in the chat uh the couple of links here on open zeppelin uh opens up lynn we have a github repo and some docs there for open zeppelin if you decide you want to check that out so lets talk about proxies versus migrations in general and like theyre kind of trade-offs in these design patterns and then were going to dive into some specific proxies later and talk about those tradeoffs right um so um page not found go ahead and uh yeah the i didnt mean to think that the chat client was gonna kind of compress them those are actually two different links right so we have the first github link and then the opens up link below it so just make sure youre splitting those up so in general the trade-offs between proxy migrations what are the pros of proxies versus migrations right we can in general we can quickly switch all users to a new implementation we can we can upgrade a smart contract and everyone is automatically quickly upgraded to the new the new contract and this allows the developer to iterate smart contracts quickly without frustrating their users giving them all kinds of uh all kinds of uh ability to to to rapidly deploy and and really improve their functionality cons i should say i have written there lots of power in the hands of developers its more centralized it can lead to that is what i mean it can lead if implemented improperly to lots more power in the hands of developers and more centralized and it all depends on how we implement the proxy again right were going to talk about some patterns here in a bit but for instance we can have the ability to up switch our implementation and change that point during the proxy to a multi-sig right and that multisig could be 10 developers or that multisig could be controlled by a governance mechanism in another smart contract and controlled by the users right so this can be a con if implemented improperly um you know proxies add gas to every contract call um compared to a migration right with a migration were just deploying a new contract ask everyone to point to that they still call the same functions but with a proxy we have this middle middleman right we have this proxy contract sitting in between us and the contract we actually want to talk to for implementation and it has to do delegate call and borrow and all of that has gas overhead um and so if youre really trying to optimize gas you know that that can be a con and of course proxies have a good bit of extra complexity thats added on top as weve seen with these clashes a lot of care has to be taken when youre implementing these kind of patterns so as a general rule of thumb if your contract is simple its well audited and hasnt needed change for a while um uh this may not be the best pattern for you right you may want to just do migrations um that might that might be solid an example of this is uni swap right they they release what a version like every year year and a half so far um and uh you know theyre not fixing any security critical bugs um and they have a governance module to kind of oversee those upgrades right and so theyve chosen the migration pattern which is uh perfectly fine for what they need okay lets uh see if theres any questions before we we move on to talking about specific proxy patterns so canal asks will the old contract still run on the blockchain um i like to pull up these diagrams while were talking about proxies so we kind of have the mental model there all right so yeah if were upgrading from contract b to contract c contract b does remain on the smart contract its still there its just simply our proxy isnt pointing to it you know once somethings on the blockchain its on the blockchain its there so yes i wonder if layer 1 and layer 2 run on the evm um yeah so everything that runs on ethereum runs on the evm so even layer 2 is run on the evm and what is the difference between the beacon chain and the evm so the evm is uh the ethereum virtual machine i should clarify this a little earlier right so the ethereum virtual machine is what runs all of the smart contract logic it manages smart contract state it it is like kind of a smart contract magic on all like ethereum type chains right uh the beacon chain is this concept and eth2 of this kind of like um this this like lighthouse this beacon chain right that kind of coordinates all these other change attached to ethereum i wont go into the detail of 2.0 but the beacon chain isnt really a thing for smart contract developers at the moment because um you know the merge hasnt happened yet where the beacon chain is like merged in and all this stuff um so really you just got to be concerned for now about the evm and how that runs smart contracts how does the program know to assign a slot to the variable number so lets bring up the slide there with the slots yeah so again when we were delegate we went through this uh delegate uh delegate call function right here we were borrowing add one to num and originally this function had num plus equals one in it it was referencing num the variable in this implementation um and we borrowed it and it automatically switched num to storage slot 0x1 and how did it know to do that well remember were looking at this as solidity code right but this is really all bytecode on the blockchain right so in the background there is no num plus equals 1 on the blockchain theres only this actually says in the bytecode storage slot 0x1 right so were just borrowing storage slot 0x1 plus equals 1 and thats coming into the proxy so the solidity compiler handles all of those kind of conversions for you and then you deploy the contract and it its referencing all the proper slots for you so essentially the solidity compiler takes care of it for you great question are there best practices on governance to allow disallow upgrades only only owner or other approaches yes um well talk about uh some of those coming up here in a bit to patterns that you can implement but yes there are some best practices security again it all depends on the nature of your smart contract and what you need out of it um perhaps you have not a very security critical smart contract iterating a ton on like some kind of game and um you know you dont need like a whole governance module and a multi-sig and all these different approaches at first um it really all depends but well go over some of that in a bit are we gonna see the hackathon how to do a proxy yep im actually gonna go over a demo at the end and uh awesome thanks alex for point uh posting that link yes that is uh the github link for the proxy contracts a great place to check out and see these implementations are all proxies moved at once in implementation or can select few be moved to an updated contract for example for access to premium functionality for our protocol so in general if im understanding this question correctly um when were upgrading um its all at once right so we write our contract c that has the new functionality added in in this case we just edited uh let me get that off the screen in this case we just edited do cool stuff and added newer functionality to this function but we could have added another function as well uh a function uh do awesome stuff here right and then when we upgrade contract b to contract c um when we upgrade those contracts they uh itll upgrade it all at once right were changing the pointer were pointing to contract c everything changes all at the same time now theres different patterns theres ways where patterns where you split up the functionality so this is possible but in general for what were talking about today it happens all at once so hopefully that answered your question lets go ahead and move on all right so you know we kind of uh covered all this we we started talking about how we want to implement these specific proxies there are some questions about that and so now that you understand how proxy contracts work in general how the delegate op code works and why we need to be very careful with these patterns because of things like function selector clashes and slot clashes i think were ready to start talking about specific implementations of proxy standards right and their trade-offs so uh a really prominent one and one were gonna talk about today were gonna go over this one in the demo is the transparent proxy pattern so im going to go over a very simplified view of this pattern here so essentially in the proxy a transparent proxy pattern um we make sure as always to have all of our state and all of our functionality our all of our state in the proxy and all of our functionality that does anything important in implementation right we have some functionality here in the proxy but the only functionality we have in the proxy is borrowing functions from the implementation and in transparent proxy we also include any of our update functionality right so in this case we have this function lets update our implementation address right its going to be a function so in the transparent proxy pattern we include this functionality in the proxy itself and what we do is we restrict access to any update functionality to some kind of admin right and that admin again it could be a single developer it could be a multi-stick of developers it could be a multiset controlled by governance all kinds of things but the function for uh our delegate call this fallback function here it um has this restriction of no admin so it wont allow the admin contract to run the fallback its going to check for that and this helps us prevent function selector clashes remember earlier when we didnt have these kind of protections on and lets say update imp ended up having the same function selector as burn well that could cause all kinds of chaos for our users for our devs that want to just simply update the implement implementation pointer and so now when our dev calls a smart contract the admin the admin can only call this it will never delegate call and call bring in burn in from there and this really helps with function selector clashes right um and our users they can update our smart contract which is uh which may be what we want right we dont want anyone being able to come in and just point our proxy to any other contract that could be extremely risky right and so this is the transparent proxy pattern simplified um ill add a link here in the chat to the eip right so this is a an official eip its been passed this is a well-known pattern and of course you can always read up more on this in the open zeppelin docs they have a lot of good stuff talking about transparent proxy patterns and we will be well be walking through this later so you can kind of see it in action the other big one is universal upgradable proxy standard so in our ups right ups right and uh in this standard all of our upgrade functionality so basically all of our functionality is in the implementation contract um and so because all of our functionalities in the implementation contract other than our delegate call of course the city compiler will again help make sure that theres no function selector clashes here right itll catch it before we put in a new implementation contract so theres no admin rights here we just have an implementation contract with all the functionalities let me the compiler make sure hey theres no function selector clashes and um were good to go now of course theres trade-offs here right and when youre using uh transparent are ups right what are what are those uh trade-offs right in general transparent proxy pattern of course like both of these it solves function selector clashes so both of them are good for that and when designing transparent proc using the transparent proxy pattern it can be its very explicit on who can run one function so if youre reading that code you know just from reading it oh this function its run by the admin or this function isnt run by the admin right this is run by the users so that ex this explicitness can be uh can be a pro right cons because were adding all these extras checks in between our functions and the transparent proxy trade-off it adds extra gas so again you know if youre a gas constraint that might not be the route for you ups again um solids function selector clashes so they both have that um and it saves uh gas per call versus transparent proxies because were not checking we just have everything in the implementation contract and theres also kind of a cleanliness here right where our implementation is literally all of our business logic including the upgrade logic right um so its very just cleanly separate proxy state and borrow thats it implementation all of our functionality including upgrade functionality clean love it chefs kiss but cons if all upgrade logic isnt included in the next implementation upgrade if you leave off some kind of upgrade logic like of the function change the pointer in the proxy your users can be frozen onto that proxy and you can be frozen from upgrading it further now youre back to the migration method and youre like i cant upgrade i cant upgrade the proxy anymore uh we have to we have to migrate to a new contract so you know its really important up front to make sure when youre upgrading a ups using ups pattern that you have everything you need in the implementation all right and theres more than this right so we have diamond pattern which actually splits the implementation contract even more into all these different implementation contracts where each implementation contract is a specific function all on its own um so theres a question earlier about you know if you just want to upgrade specific functions this can kind of give you that power so you may want to look into the diamond pattern more im not going to go into detail in it for time in this demo you have the metamorphic pattern which is like a factory pattern um which allows smart contracts to completely ride over themselves right and like just completely change the bytecode of a smart contract and how you think a traditional upgrade would work in a traditional system um of course that has all of its complications and trade-offs and theres probably going to be more to come right theres the landscape is changing fast who knows what patterns people will discover and what new technologies will be used to create new upgradable patterns so were about to dive into the interesting part were going to go into the demo so now you kind of a good understanding of how this works so when were actually writing the code ill try to reference some of these uh topics again um i see we have a question so ill answer this question um and then ill give everyone lets see a five minute break uh ill come back you know go to the bathroom drink some coffee maybe put some questions in the chat ill try to answer a couple when we come back and then well go through the coding demo so um gabrielle asked which is message.cinder for a contract behind a proxy uh the real message.sender are the proxy address right um so lets go back when were using delegate call the message.cinder is of the original person who sent the transaction so this user sends a transaction to proxy the proxys running delegate call and delegate call keeps the context of the original user so its the message dot center of the user right uh not the proxy get the cat please all right yeah ill ill go get him um ill come back from the break a little early so if you have some time ill show my cat and then well move on to the demo all right everyone um ill be back see you in five minutes get ready uh for some coding all right so so so im back here a little early for those of you we had a couple of requests in the chat to see my cat here he is hes a cute little dude his name is coda love him he can get a little rambunctious and get into trouble what im in in trance and giving talks though so i try to keep him in my room a bit ill give another minute and then well dive into the code if you have any questions feel free to drop them in now i see we do have some where can i see all the available public contracts um yeah ill be posting those in a bit um yeah theres a github repo see let me i can pull it up right now currently its under my github username but were going to be moving this to the the chain link general repo so when we dont use delegate call then its the proxy address uh correct yeah if youre using call its just going to forward the proxy address instead of keeping the context of the original user uh yep correct its one of the main reasons were using delegate call other than the borrowing functionality im glad yall are a fan of coda yes he is a very big cat um i got him when he was a kid so i had no idea who to get this big but he is a big uh of course scaredy cat like a lot of cats are um big softy love that cat okay lets go ahead and get on going uh with the cool code and so why did i say that tesla example right um well again teslas upgrade a lot so were going to try to do this coding context with a little fun uh built in the context of an upgradeable tesla power module um uh for the car right so uh oftentimes what theyll do is theyll uh theyll find some kind of improvement in how theyre um like doing the thermals of the car or whatever and it adds a couple of points of extra horsepower the car can then access and keep the same efficiency right so um thats what were going to be doing were going to be changing um and adding implementations uh to this like power module on our car and upgrading it um this is going to be using uh the transparent proxy pattern right so thats the one were going to use for this demo um were going to use whats called the opens up and hard hat upgrades plug-in right so its going to be in hard hat and were going to upgrade our smart contract right thats what were all here for so lets go ahead and dive in pull up vs code here one second and so um lets share that now lets share to do all right okay so on the vs code and actually where ive gone and started is cloning the hard hat starter kit right um so i like to i like to start a lot of my work from cloning the hard hat starter kit uh the chain link hard hat starter kit even if we arent going to be using a lot of the chaining functionality in this demo its just convenient because it already has a lot of the pre config stuff in our hard hat config all this is kind of already set up every library that we may need you get a lot of already built in tests and tasks so i actually like to start a lot of my projects just straight up from the the hard chain link starter kit right and if you want to know where to find that let me go ahead and get that link for you all so you can clone it from this link here on github right so this is a fresh fresh clone of that of that starter kit all right so weve got that the first thing were going to do here is were going to add were going to add a um the open zeppelin library that were going to use for this right so open a terminal in vs code wait for it to load lets say yarn hat no mick labs slash hard hat this will add that package in and while thats being added in were going to want to add a require statement to our hard hat config so hard hat knows that this is a package were going to be using throughout um our programming experience today right so were going to make a require statement here im going to say require and again were in hardhat.config um were going to say at open zeppelin slash hard hat upgrades oh save that and yarn is still adding there um so while thats being added on lets go ahead and start uh creating our smart contract that were going to be using today right so were going to go into contracts im going to create a new file you see since this is a hard hat starter kit we already have all these awesome chain link examples if we want to use those in our smart contract or not but theyre there so thats nice um were going to create tesla power dot sol all right so again what we want to do is we want to create just a basic smart contract for updating our teslas horsepower right um its like power module as always well start with our pragma pragma solidity statement telling the compiler what version of solidity were going to use were going to go with 3.7 were going to call this contract tesla power all right so were going to need a variable that were going to change were going to make it a unit 256. its going to be a private variable so were only going to change it via methods internally and were going to call a horsepower this is going to represent the horsepower of the tesla right were going to create an event and were going to call it horse power changed um were going to call that were going to put that in here as you went im going to admit you went 256 and its going to emit the new value when we change that horsepower right thats going to be the purpose of this event and were going to make a function this is going to be our setter function set horse power and this is going to take a un256 new horsepower public not public and were going to do horse power equals new horsepower okay so this function is going to take in a value of u and 256 and its just going to replace our variable horsepower with whatever we pass in right so we can pass it in whatever we want its going to set our horsepower to that of course we have that event so were going to admit the event horse power changed do you horse power lastly lets just put in some getter functionality here so function whose only purpose is to read that variable so were going to call it retrieve horsepower its going to be a public and since this is just reading state not doing anything else well make it view and return a ui 256. and oh we need returns up there do that do that mistake all the time and were going to return uh our horsepower state variable and uh thats going to be our tesla power smart contract right so lets go ahead and save this yarn is still doing its thing uh this is because its the first time ive run yarn on this um on this repo so its actually um not just adding in that one package that we asked for but its installing all of the node modules were going to be using so thats why its taking some some time down here all right so we have our smart contract here now of course something that you all i always try to get in the habit of i think any good developer should get in the habit of is writing tests um as were developing our smart contract right a little test driven development so lets make a basic unit test for this smart contract were going to put it in this test directory here under unit well call it lets see were going to call it tesla pistol power the name of our contract unit as following the conventions down there dot js gonna be a hard hat test here oh did i not looks like my vs code is running a little slow right now probably because of all the stuff going on with yarn uh lets give it a second here to catch up with everything if it freezes we can switch to a different vs code there we go perfect all right so yep we created that yarn finish too it was doing a bunch all at once and um yeah lets go ahead and uh write this unit test um im gonna put a lot of the boilerplate to save time here as i copy and paste and ill just kind of walk through it see here so well put in all of the imports ill just copy and paste those in and then ill put in the describe statement and ill actually type through the tests with with yall live okay so um here were saying all right were gonna put a describe statement in our test and were gonna say hey this these this group of tests in this file is going to be for our tesla and eventually its going to be for our uh proxy contract and all we want in this test is it is going to uh retrieve a value previously initialized right and so this is going to be an async function achieve that for this test you know our test is going to be async chin then well describe the test in here okay so what are we going to do well first were going to need to grab our smart contract that we wrote so were going to create two variables we call one uppercase tesla and lowercase tesla up here and stay there and were going to say uppercase tesla in this test is await ethers dot get contract factory tesla power right so what this is going to do is going to grab our contract from up here that we wrote in our contracts folder lets call tesla power and its going to bring that in and its going to assign it to this variable tesla and then were going to have to take a little tesla say await and this is where were going to call in that upgrades uh open zeppelin that we added in uh until throughout our hard hat folder so were gonna say upgrades got deploy proxy right so this will um this will take care this function will take care of deploying all the contracts we need for the transparent proxy patent right so this is going to take our tesla power its going to take all that functionality and deploy it as an implementation contract have a proxy contract that points that implementation and also have a third contract called the admin contract which will um which will handle all those admin privileges we were talking about earlier right so were going to want it to deploy the tesla contract and were going to set the horsepower to 600 and im going to talk about why were doing this in a second and we will set it the initializer here 600 oh im typing what we had up there again look at me sorry about that but you got an explanation of whats going on up there a little earlier um thats whats going on up there were going to expect um now were going to make our expect statements right so thats what were doing were deploying our proxy contracts um were going to take the tesla were going to initialize it with 600 and our initializer is going to be this function now implementation contracts can actually have constructors like you would in a normal uh a normal smart contract right so um because if we had a constructor right it would have uh that would be a function that would initialize state in our implementation which is what we dont want and uh with this horsepower the upgrade function will take care of separating out that state into the proxy so open zeppelin has got us on that um so thats why were setting saying hey since we dont have a constructor were gonna have this set horsepower function as an initializer right this is gonna be the function it runs immediately after deploying right so its going to deploy it and then this library will take care of calling that function for us and passing in the value 600 and setting our horsepower to that right so lets go ahead and write our first expectation statement right so well say await tesla tesla so well call our deployed contracts and well say retrieve horsepower then well put to string so were going to convert what we get so were going to call that retrieve horsepower function on our uh on our deployed contract implementation were going to retrieve the horsepower and since we set it to 600 it should be equal to right and one more expect statement you know well save this one well save this one for later now were just going to figure out why is it giving me this error here so good got that let me just look through theres probably a parenthesis i forgot to close here for each its good oh that was right and after our if statement uh fun with uh coding is that you always get these little things i see what it is um function here no async folks thats right so horsepower um all right so i dont know to save some time here ill just copy and paste the code theres probably some parentheses in here that i am missing so ill throw in the same code just properly okay and you dont need this expected okay so still giving me that so that means its something because i didnt close the describe thats it cool all right there we go all right so always a programming the parentheses and the curly braces that kills me but all right we got that going we got our first test on there um as were developing it and we can just run yarn hard hat test and its going to run that okay and of course were going to get that oh it didnt actually add in our hard hat upgrades all right lets go ahead and go back create a new terminal i dont know why it didnt i guess it was focusing on doing um the yarn uh install for everything and didnt actually add in so were going to make sure yarn add nomic labs flash and make sure i get this name right well go back to our hard hat config were going to add in that opens up another probably wrong ill probably add in at no make labs so were going to add in at open zeppelin upgrades to the end here slide that package so you can actually see that so well that is adding yeah thanks for pointing that out uh uh shaman uh missing the end of the describe thanks for that and im misspelling horsepower or do i got it misspelled in the test script let me know where im uh misspelling it if im spelling it somewhere um and i ill change it but well see real quick if theres a theres a compile error right um so yeah again what this um what this deploy proxy is going to do is going to deploy all three of our contracts for us again so we run this test it should do that so now were going to run yarn hard hat test its gonna do its thing all right its running through everything its compiling everything and so since were using the hard hat starter kit its going to run through all other tests real quick so only take some time the very first time we run it but while thats going um all right of course more errors perfect live coding lets do it uh ethers isnt added in as a context than this all right yes we didnt add ethers in to our require of course thats a very important package we want to add in there right so lets go in and well just get the required statement for ethers save this here there we go okay sps spdx see where this comes up with this time still not finding that ethers okay one second here see what could be going on our our hat.config here looks like ive got everything added in there lets just do one more thing and if this doesnt work ill just switch to uh the working code right but uh well try to add in well do darn add and well add in the and i think i did it at the beginning and i think because it went through that whole yarn install it didnt add it in so well see hopefully this works but its going to take some time of course so well thats going um and well run our tests when thats done lets go ahead and move on and were going to make a contract an upgraded version of our tesla power contract so when we deploy it well stop well see what were going to upgrade to right so were going to call this one tesla power v2 godzilla right and what were going to do is were just going to copy all of our tesla power contract were gonna add in a single extra function so instead of setting the horsepower were gonna make a function that increments it usually you dont get giant gains in horsepower even if youre improving efficiency so maybe you just get one horsepower extra at a time as they improve the technology of the car right so you and 256 turn so what this is going to do return anything what am i doing here were going to also going to do is were going to take our horsepower were going to add one to it so were going to increment our horsepower and thats it plus plus just means take horsepower add one make sure thats saved and it looks like our um yarn ad has gone through so lets fingers crossed through yarn hard hat test one more time were gonna go back and uh hopefully our test tests run lets go so we have our two contracts and after we deploy this uh tesla uh the original tesla power contract were gonna upgrade it to the tesla power v2 right so were getting one more error still not finding it um okay so to save time let me switch to a different um different vs code and ill go from there so one second sorry about that yall yeah our test is passing the others are throwing the air yeah um i probably forgot to add a yarn somewhere in the steps here to make sure that the ethers was added to those tests um yeah probably something in this setup right so lets go ahead and ill share share this screen right and so here we back our right we got our tesla power v2 we got our increment horsepower on there um and well go back to our test here and youre gonna see a little bit of extra stuff on the the test well go to the other test in a bit right but we still have the same logic here you know were deploying were using the deploy proxy were deploying it set to 600. and um were retrieving it and it should equal to 600 right lets go ahead and yarn test all right so i definitely tested this one out so this should work out i see this ones pointed to rink b we dont want ring p right now test network one second whats going on here default default default network is hard hat why is it trying to go to wrinky one second im trying to troubleshoot here notice theres no yep so lets see yeah that should have worked that work lets see weve got our voice grips test test is going through calling out the hard hat config im not sure why its its defaulting i mean were going to want to default the rink b in a bit anyway i mean i can go back to this shell the shell should work because it has even if its the point to ring fee it has everything set up in it yes there we go perfect im glad you all could join me on this journey of troubleshooting hardhat all right so its going through all our tests everythings running and its going to get to our random number consumer test everything is passing of course its running these other tests ill explain what they do in a bit um but yeah so everything passes at least at the beginning for what we wrote earlier again it uh right here this all the way down to this expect statement you know its checking to make sure that we deployed a proxy contract an implementation contract and the state in the proxy was set to 600. so um that is fantastic all right so we got that running um and now lets create uh if you want to deploy these separately there is a deploy script in here right that was created separately right so lets walk through this script right this will take our this is just if you want to separate from the test right you just want to have deploy uh upgradable smart contracts in general in this case we created a script called deploy tesla power right and its gonna again get our contract from our contracts folder its going to actually deploy it and its going to use that deploy proxy upgrades library from open zeppelin right and its going to set it again were setting it to 600. you can change it to whatever you want and we have our initializer which is the functional run after it is deployed and so we have uh and then some console.logs and its that simple right so were just this is a separate script that uh deploys it right so if we want to run this we can say yarn hard hat run scripts flash deploy tesla power now run the deploy script as a separate thing now i probably scripts deploy tesla forgot to add the js at the end um so what this uh so youre saying okay we got everything deployed uh we run the test everythings working where are the proxy contracts hows it separating out how can i see that which is a good question so to do that were going to go look at the transactions this wallet has been doing on rikubi and see where thats going so now im going to share a quick ether scan so ill go to the ether scan of this like demo wallet here and these were because these are actually going i think the hard hat now but um these are some deploys ive done earlier for the proxy contracts right so if we go here well see i created this contract this is the first contract deployed this is the actual proxy contract right and if we go to this one here and we see the other contract i created and this one actually because this this pattern has been done this code is already verified on etherscan this is that admin contract i was discussing earlier so this is the contract in the transparent proxy pattern that make sure that only admins run the admin functions and non-admins run the non-admin functions right the users and finally lets take a look here this is the transaction that created the implementation right so this is the implementation contract or sorry this is the proxy the first one was the implementation um uh yeah this is the proxy since this is a standard um they all look the same right its already verified all right so lets go back to vs code okay so were back here vs code weve gone through weve deployed our proxy pattern contract we have an initial implementation we havent upgraded it yet right so for the upgrade were going to want an upgrade.js script right and um were going to take our um original proxy and were going to point it to tesla power v2 instead of tesla power v1 now right so again were going to go through here were going to say hey get contract factory pull in that contract from our contracts folder tesla v2 were going to call upgrades library from open zeppelin and this is where you would put in the address of your original tesla power contract so this right here right and this will uh take care of uh doing the upgrade its that simple right um we have another script here prepare upgrade so you may be wondering what that does and this will just run some logic that checks uh itll run the prepare upgrade on this upgrades library here and this just checks to make sure that like everything is good with upgrade um and of course you need to point to the proxy address right there right so now if we want to run the upgrade script well run yarn hard hat run scripts slash upgrade dot js ah because it hasnt actually compiled our tesla power v2 dot soul uh contract here right so theres no theres no artifact there uh lets see tesla factory tells the v2 because we all we call it tesla v2 lets change the tesla power v2 thats it lets run it one more time man just the theme of this demo right lets see whats going on here ah saying that this isnt the right address okay its fine all right well run our deploy script one more time say network let the rank be oops deploy power yes its going to deploy this to rink b this time we got it lets put this address in so now well say yarn hard hat run scripts and well do upgrade all right lets make sure i got that script name right this time yep all right and so this will take the should take our um tesla power v2 again and take that pointer of course uh like its a proxy with a logic contract get there but um take our proxy contract and point it to the v2 contract instead of the v1 lets see what error were getting though doesnt look like any arent the logic contract 1067 b all right yep so well point to rink beam um hopefully this will work if not ill have to unfortunately move on due to due to time but i can kind of talk through the rest that really hits all of the functionality so hopefully this will this will run takes some time to run the upgrade so it looks like its doing it its just taking some time now right see just doing this thing communicating with rink um appreciate it enjoy the debugging process yeah um just one of those days you know ive got a you can see in action right this is what happens when you code so hope it helped you learn at least how we think yep it seems to uh kind of be stuck on running here right um so um im not sure why its stuck running here but yeah thats essentially what i would have done im sorry that uh we wont get to wont go to see this unless this completes uh relatively soon but with the last couple of minutes here if you all have any questions about the process i can answer any questions if not well just kind of go over what we talked about today so feel free to throw any questions in the chat so i can try getting out of it and running it again all right well oh there we go all right so now its on my environment variables uh we can set those real quick thats an easy fix now this is a demo wallet and a uh i always change my rpc urls after every demo so im not worried about showing this on on the screen but again always be careful with your environment variables dont ever show these to people right but this is again just a burner wallet with no real value in it right so um yeah well let that run and hopefully it comes back but lets go ahead and quickly review uh what weve been over today so were running short on time yeah so we talked about what and why on upgradable smart contracts uh we talked about the migration patterns we talked about what proxies are um the delegate call and evm basics you know um how delegate call borrows function selector clashes um slot uh clashes talked about two prominent patterns and the trade-offs in the proxy pattern space transparent proxies and universal upgradeable smart contracts and we went through a demo with a lot of troubleshooting but you know i think ill walk through the code you can understand uh what was going on i hope that was a little bit helpful there unfortunately at the last step there you know were getting some errors ill have to walk through and see whats going on with that um it looks like im getting some fee errors now so somethings going on with rink b um its not setting the the fee high enough um so yeah you know i hope this uh kind of gives you an idea of how to structure proxy contract upgrades um and uh you know going forward you can be a little bit more conscious of in the hackathon youre trying to implement a proxy contract upgrade really make sure you understand why youre using the specific pattern you want to use and what trade-offs are incurred from that you know but yeah thanks for following along uh please leave any feedback uh that you may have on the this workshop ill post this link in the chat for those of you this is the actual demo here so this will take you to this screen here and here is the link for those of you who dont have a camera to take take a picture of it right all right well thanks for joining everyone um hope you learned something useful from this uh love to see some feedback on how we could do could do this better and ill see you in the next one good luck in the hackathon In this educational video, learn about upgradeable smart contracts and how you can make them. Chainlink is the industry standard for building, accessing, and selling oracle services needed to power hybrid smart contracts on any blockchain. Chainlink oracle networks provide smart contracts with a way to reliably connect to any external API and leverage secure off-chain computations for enabling feature-rich applications. Chainlink currently secures tens of billions of dollars across DeFi, insurance, gaming, and other major industries, and offers global enterprises and leading data providers a universal gateway to all blockchains. Learn more about Chainlink: Website: Docs: Twitter: Chainlink Chainlink,