# ETHWarsaw 2023: Aleph Zero - Workshop - Safe and robust smart contracts in Ink!

- Channel: [ETH Warsaw](https://streameth.org/eth-warsaw)
- Date: 2024-10-07
- Duration: 54:33
- Watch: https://streameth.org/watch/yt-fnxMQ68I-ys
- YouTube: https://www.youtube.com/watch?v=fnxMQ68I-ys

## Description

Workshop - A workshop by Piotr Moczurad. Safe and robust smart contracts in Ink! A programmer's guide to the crypto industry.

Follow us for more updates: https://twitter.com/ETHWarsaw

## Transcript

who are expecting pragmatic privacy with Lial uh I hate to inform you that the title in the agenda was slightly outdated uh so if you want to leave I I I won't be offended um instead we're going to do something that's uh probably useful for prospective participants of the of the hackathon so like a very basic introduction to Smart contracts in Inc uh we've just seen go now it's time for some Rust uh go modern languages um okay so yeah I always include this definition of a smart contract but uh it's it's not really useful it just looks good on a slide um I I think of them basically as programs executing on a computer and the computer just happens to be to be a blockchain um you know but once you're able to program blockchain you can unlock a whole array of of very interesting use cases uh you know defi digital identity and and many many more uh so it's it's really a very very powerful thing to learn and uh having said that it's you know it's like the I think it was in the Spiderman movie that with great power comes great responsibility and true you can program a lot of uh very interesting um programs contracts but uh those seemingly innocent and and simple pieces of code uh you actually need to be very diligent in how you actually write the code and it needs to be written with with great care and um with a lot of focus on safety and well to that end I I'm actually a big fan of using languages that that kind of have the safety if not built in then at least you know uh they don't allow you to shoot yourself in the foot as easily as as other languages can um so rust is a good example of language that that's you know it's it's modern it's it's backed by uh by some research um so so it's it's very predictable and uh and actually allows you to express a lot of constraints in your programs so that you don't have to catch your bugs in production or or in the main net instead you can do it you know with the help of your compiler and test Suites um so we're going to be deploying this uh or or well working towards deploying on the ALF zero blockchain uh so if you're not familiar we're a layer one proof of stake blockchain well nominated proof of State actually uh with some focus on on privacy and uh and great performance so the block time and time to finality are both uh sub 1 second and uh what's quite cool for smart contract developers owners uh is uh extremely low transaction costs so a Zer is well roughly around a dollar so uh yeah this is this is virtually free actually uh in the current landscape and uh well of course we feature smart contracts in Inc and uh you might ask what is Inc well uh oh I'll get to that in a second first first I wanted to present a few useful links if you scan the QR code it just takes you to the main landing page the first link um but if you're starting to to learn about substrate chains or about um LF zero specifically or ink development then these links should get you started quite nicely so the first one is our main website and actually you know you can with just uh one or two hops get to every other link uh the second the second link is our documentation and is actually not only for smart contract developers also for validators uh nominators uh General users of the chain and anyone interested in how it works uh but but of course smart contracts are are there and actually a also a cool security guide uh that uh kelki security roote uh some interesting stuff there also the developer portal which uh is like a hub for for developers then the uh test A.D is the test net developer wallet so of course there are there are several wallets but this is uh this is the one you would use as a as a validator for example uh then of course the contracts UI and for the pro programmers Among Us you don't have to use the UI you can of course do it all from the command line but uh sometimes it's convenient and definitely looks better on slides so I'm including it here and the question we get asked all of the time is uh okay I I have the smart contract now how do I talk to it from my from my app and um well the last link basically answers that there's this API and JavaScript that you can use to talk to the chain make transactions create the chain so so that includes um talking to the smart contract and uh of course there are libraries in in other languages as well rust python you name it um now okay I I I mentioned ink several times already and um didn't explain what it is so Inc is not a separate language in a sense that it's actually built on top of rust so it's actually a subset of rust uh with some additional macros and convenient features targeted at smart contract development but you know by virtue of being a subset of rust it has all the goodies that rust has so like I said a modern language a typesafe language I always say it's as typesafe as you can make your language while still making it usable you know for for developers because anything more in my experience at least because I come from the hll uh development Community anything more type safe generally tends to be quite tedious to write and um also to tedious to make it you know run really fast uh R is also memory safe um also actually in contrast to go that we've just seen it's a different approach so go goes like the garbage collector approach we go the well rust goes the like kind of smart pointers uh approach but um has all this nice ownership Concepts uh you can see how it can make you know a complete memory Safe program with zero overhead uh the tooling is generally quite nice and it's winning the stuck overflow developer surveys like crazy so uh probably you know a good thing to learn in 2023 um now in well rust can compile to to different backends um and that that it includes wasm which we use for smart contracts so this is web assembly and uh you probably all know it it's pretty ubiquitous it's also uh fast and secure runs on pretty much everything so so yeah this is what it looks like on a very high level and uh of course one of the questions you might ask is okay I'm coming from solidity how how how do they correspond and uh while they are well different languages with with maybe different uh philosophies a bit actually conceptually you will you will feel quite familiar so like uh this table is not there for you to like really analyze but uh it's kind it kind of shows the onetoone mapping of Concepts right so pretty much everything you can do in in solidity you can also do in ink well the syntax is maybe slightly different uh and uh and yeah like I said the philosophy might sometimes be different but uh you'll feel familiar after after like uh a few contracts that you write now this is I know this is a wall of text again I I don't really uh you know want you to analyze it that uh diligently but this is more or less what your like onboarding flow looks like uh for Inc right so first you install the required tooling um and this this was like done on Ubuntu but but you can you can also install it on a Mac on on Windows yeah it's it's a bit tricky but should work uh so some some prerequisites uh including well of course you need rust uh and some libraries for like optimizing wasm and uh once you have R along with cargo and cargo contract which is uh well cargo is basically this build tool SL package manager SL like management tool for rust I we also have like an extension for writing smart contracts so you need to install um cargo contract this is the last line here and once you have it you can bootstrap a new contract um similar to you know what you would do in a like a rail Z and this gives you a basic flipper code and this is actually kind of nice because you know normally I would tell you to focus a lot on how the macros look and everything but to be honest you don't really need to because it's it's always going to be there as a starting point so it's good to know the overall structure but uh you know not exact order of characters or or something like that um you'll have that written out for you the the structure and you can focus on the logic which is quite nice then you then you test and build your contract and um what you get is well the wasm Blobs of the actual binary the contracts metadata which is quite important because you cannot really tell a lot about a contract just looking at its binary code even if you you know decompile it to like the uh human readable representation of wasm uh the metadata is also sometimes called an ABI it's basically what you can use to it's kind of like dog strings for the methods actually and also some information about where they are in the in the bundle and everything and for convenience the two are bundled together uh so that when you actually deploy the contract you can you can use just one file which is a nice touch and now something I've decided to include is is you know this is this is a pretty new and dynamically changing ecosystem so sometimes and this especially should be important for uh for those of you who are planning to take part take part in the hackathon uh there's a lot of moving pieces that you need to get right in order for this to work so your mileage may vary but this is the combination of versions that works for me and um so yeah so R 1.69 and you might also want to install the nightly tool chain uh like this cargo contract 301 and there there are newer versions right now but uh I feel confident using this one um now to to run your contracts uh even for local development you can you can do it in a number of ways uh I'm going to show you a cool one at the end but uh one of the recommended ways to bootstrap it really quickly is to get yourself a instance of substrate contracts node so you know this is you just spin up a very small local blockchain made of one node and the version I use to good effect is uh 0.26 and Inc uh 4.2.1 and now this is you know uh this is actually an important piece of advice that uh we've learned using our own experiences when you this is a line taken out of the cargo. toml file that you use to specify the versions of your dependencies if you're putting the ink dependency you might want to put it with the equals sign in front of the version so that it chooses the exact version that you specify otherwise on different installs uh cargo will try to uh choose the newer versions at least with the you know the the minor version and the patch version will will possibly change so it's it's actually really convenient to fix it on a specific uh on a specific version down to a down to even a patch version um so yeah piece of friendly advice um we're going to take a look at how the contracts are deployed I'm on purpose I'm not doing any live coding just because I've learned my lesson a few times something always goes wrong um so yeah and um it I I choose to to present the concept concepts by doing an erc20 or the PSP 22 spin on an R erc20 token so like you know your uh regular Garden variety fungible token and I'm calling it pcoin because I thought it was funny and uh well I I do quite a lot of these presentations and someone actually already made a pcoin and I think even on the main net so they kind of stole my joke but it's okay um yeah so what is erc20 or psp2 2 uh as we call it in the substrate ecosystem well it's basically an interface that your contract needs to implement in order to be viewed as a as a fungible token so there are some basic methods like total Supply basically how how much of the token is in circulation uh balance of a specific account it needs to know that allowance I I'm going to mention allowance later but uh for now I'm going to just going to focus on the transfer functionality and of course the well the transfer method the probably the most important one is basically you know uh you can transfer some of your tokens to some other address um and yeah and contracts are emitting events we are going to come back to that later um so so yeah let's you know let's Dive Right In so when you when you start creating the contract like I said this is this is going to be created for you but still it's nice to know what what this means uh you start with the flipper but you start inputting your own logic uh so at least it's useful to know what not to change or delete so the things with the with the hash or the pound signs are are macros they are not Commons for those of you coming from python um and um the the line the line at the top basically tells the the compiler not to include the standard library because the Inc has its like own Prelude uh with some Primitives um and the the second macro is actually very important one it's it tells the the system the compiler that that the module uh written below is actually a smart contract and it actually enforces certain invariant now the the module uh declared with the mod keyword is actually somewhat similar to a name space in in C++ so there's there's no like magic going on with modules like you could find for example in in Python uh the modules are more or less a collection of things gathered under a single name and uh you can import stuff into the scope of your module so if I do use ink storage mapping then I'm bringing the mapping name into scope and uh I'll be able to use it uh starting from from this import uh you can also like reexport stuff uh by writing Pub Pub use uh but it's uh beyond the scope of this of this presentation so yeah this is this is like the pretty much the the EnV variant that every contract has um now the the most important part so every contract needs some some form of a storage well actually you could in theory create a contract without the storage but um or maybe huh I'm actually not sure uh if someone is on the computer right now you can check if you can create a contract without storage because I think I think one of the things that the contract macro does is actually enforce the invariant that um a contract needs to have exactly one struct marked as storage um now there there's there's quite a few things happening here especially if you're not used to rust uh first of all there's the ink storage macro that that does some magic but more or less what it does is tells instructs the the runtime how to how to uh well structure the the memory on chain once you once you upload your contract and uh the details of the of the memory layout of the contracts are are way beyond the scope of of this presentation but you can uh read about them at the use.in site it's it's actually a very nice piece of documentation um now what we're doing here is declaring a a rust struct uh well we're prefixing it with Pub to just say that it should be accessible from from outside of our module but a struct is like an object in any object oriented language well sorry like a kind of like a class so if you're familiar with C or C++ it's it's very similar although the rust struct you you cannot like declare Behavior inside of the struct which is a very cool thing uh you cannot inherit from the structs they're just basically a box for Stuff uh with fields that you can access by name um so yeah that's that's pretty cool and inheritance um well yeah I this may be controversial but I think inheritance is generally not a good thing to have in your in your programming language I'm happy to discuss that after the after the workshop but I think Russ's Choice here is is great um so yeah you have this struct and it has two Fields the total Supply which will be the balance and balance is like the inks built-in primitive uh it also has the the the balance is mapping uh the mapping is well think of it as a as a hashmap uh or like any map like a dictionary in Python so this mapping will map from the accounts to to the balances of these accounts so this is kind of like a you know like a ledger or well not a ledger like a balance sheet of of all of the users of your contract and importantly if someone hasn't interacted with your contract and didn't get any transfer they will not have an entry in the in this mapping right but if you send them some uh some tokens they will get an entry we'll see we'll see about that later and um then there's the derived default line which uh which it's a macro that will basically create a default implementation of the struct for you if you're familiar with like the concept of a monoid a good default implementation would be like a zero of the monoid for for each of the fields so if you have like a number field it's probably zero uh as a as a default value and uh if you have like a collection then an empty collection is a good default value in case you ever uh need to implement it yourself this is these are the basic guidelines otherwise it just becomes confusing um now I said that rust structs don't have Behavior attached to them well in inside of the struct that's true but you can like add certain methods to the struct outside using the short for implementation I guess or Implement uh in in in this blog and um yeah so the the methods that we declare here uh you will find them familiar from other objectoriented uh languages that that you might be familiar with uh but the the first method that we need to have and it's it's a special one because it doesn't have self as the first argument uh it's it's going to be the Constructor and one of the things that the Inc uh contract macro enforces is that your contract needs to have at least one Constructor so the Constructor will be basically any method that you mark with the Constructor macro and it doesn't need to have any special names right so it doesn't have to be like in it or or new um but note that the users of your smart contract will need to call this method to to create your contract if they want to instantiate it so it's good if you know if it has a fairly intuitive name um now what this does here is essentially create an empty mapping of for the balances check who's the color of the contract uh by calling this this magical self colon colon en method and then calling the color method so this gives you the address of the account that is that is calling this this contract right now right so if if this is the Constructor then then you're the one instantiating the contract uh so this this color here uh enhance the contract owner but for other methods the color might be somewh entirely different and what we do here is we take the balances mapping and insert to it the the pair of you know the color so the the owner of the contract in this case and the total Supply because initially the owner gets the whole Supply and then uh they can make transfers to to other other accounts and uh and yeah and we basically create the instance of our storage struct uh note that in Rust you have this like concept of an implicit return so the last line will be returned unless it has a semicolon at the end but U here it doesn't so it just gets returned um yeah now if can go back yeah yeah yeah question yes it's a it's a reference or like borrowing and uh next slide is actually about that don't havea have the yeah it's like a ke key mapping okay um so yeah so the the the % so to to understand what it is we have to take a step back and talk about rust's memory management so basically how this works is you have this ownership model so everything you allocate on Heap has exactly one owner and uh yeah like like well I'm just reading the slide now you cannot access a piece of data unless you own it or have been borrowed it right right and uh what this means that well it might seem weird well what does it mean that you cannot you don't own it or or who who's the U here right and uh it's actually like scope based a certain certain scope or like a function or a block of code um is is the is the U in in this case right um so this is this is cool because this is a model of memory in which well you have like all of the safety guarantees but rust is able to check all of this at compile time and hence not induce any runtime overheads uh now you have two ways of essentially transferring the the ownership of of a given value of of like a piece of Heap allocated data so one is move and uh again those of you familiar with C++ you probably know move semantics so this is kind of similar uh and moving happens when you are passing by value so like just you know passing your argument to a function uh or you are assigning and uh moving means that you you you are no longer in ownership of the data so if you pass it to a function now this this function becomes the owner of the data and you can no longer access it as we're going to see in just a moment and uh the second way is borrowing and this is very similar to pass by reference in in C++ um now let's look at this example right so I have a struct with with just one field it's it's some number and now I have this function that takes this an instance of of this F struct by by value so and and just try doing something like returning the structs fied with you know incremented by one uh so now what I do to to to test how this works is I I create this this struct then I pass it to a function uh by value so remember what I said that we no longer own this F struct once we've passed it by value and then I try accessing the field of the struct and what do I get I get an error uh which is actually quite descriptive because the compiler pretty much tells you what's happening and how to fix it um so it basically says okay you you no longer own this value but you're trying to access it so something's wrong right um and indeed the compiler even tells you know what are the exact places where the problems occur um now how how to fix it I can say okay uh instead of just you know giving away the full uh the full struct in this in this line here I'm going to borrow with to the function the function will do what it must and then it will return the object to me so I can access it but notice that I changed the implementation a bit because right now I'm not returning the value of the field I'm just I'm just incrementing the I'm just incrementing the field by one right it's it's a super super simple operation and uh yeah seems like it could work and this this is to to answer your question this is this is what the m perent means so first you use it in the in the Declaration of the function to basically let the compiler know okay this value will not be passed will not be moved it will be borrowed and uh in the in the actual call you also say well don't just you know move this value here instead borrow it to this function and uh it needs to happen quite explicitly because otherwise you might do something that you didn't intend to and this way if you're you know if you're intending to to borrow this instead of passing by value you need to be explicit about it so it actually reduces the the number of of Errors you can make so okay this should work right huh no not really uh and that's because rust is quite conservative in What it lets you mutate right so uh it's it's a pretty well known fact right now that mutating the state pretty much is a pretty dangerous operation uh so Ras basically says okay if you want to mutate some State you need to be explicit about it um so how are we going to fix it well we are going to say okay so this pass by reference function is borrowing this this fo struct and it's borrowing borrowing it in a way uh that that will mutate it right so you know if you it actually makes a lot of sense to me if I'm like B borrowing a haird dryer from someone I usually don't like Tinker with it and uh if I am I'm going to let them know so this is this is what rust is doing here right now right um and uh we also need to be explicit about the mutating part in the in the actual call and now uh it all works and question like homework is okay this this makes sense but what if I'm trying to like return a borrowed value somewhere else right you you lend me a hairdryer and I'm just giving it away to someone else uh what what do you do in uh in this case yeah it's it's an interesting problem and rust has a nice way of solving it you probably will never have to use it in a smart contract so I'm not including it here I encourage you to to do some research now getting back to the contract um okay we we have the the module declared the contract declared the storage declared the Constructor declared now our contract needs to be able to answer some some some some calls from from the outside world right so uh again this is something enforced by the by the contract macro you need to include at least one message in your contract which will be a public uh public method taking self as a reference this is actually very similar to python but uh the contract the messages need to take the self as as a reference and not by value uh and it needs to be marked by the ink message macro so now the the first one we Define is is the very simple total Supply which is just a getter for the total Supply value um and if we declare it like that someone you know can go to the contracts UI import our our contract and and call it paying some small gas fee and learn the total Supply um now the the other method is actually it's it's very simple but it's actually very interesting and and showcases some of the very elegant uh parts of the rust philosophy so let's say we want to learn the balance of of a certain account in our in our of our uh token so what we do is okay we have this balances mapping right and we can get a value from under a specific key and now the the usual problem here is well what if this this key doesn't exist in the mapping right uh well to to to like solve this the the get method of the mapping doesn't return the value that a concrete value it returns a wrapper um called an option which may be something with with a value or maybe nothing and now we can call this this handy method unwrap or default which is saying basically okay if there is something in the Box just return it if there is nothing return the default value for the type of course the type needs to have a default implementation uh we've seen how you do it before and uh this is actually extremely convenient for our use case in which if someone is not in our mapping in our system uh they they don't have an entry right but here we have we return zero as their balance which is actually true right it tracks with the whole like banking analogy and uh we're going to see in just a minute how how it's used to actually make a transfer to someone that doesn't exist in the system yet but um basically this is this is the rust way of of handling uh well non determinism right uh it can return something it can return nothing we handle it in a like an algebraic way uh now I I just like to in include this graphic it's it's extremely simple but uh how do you make a transfer well we have Alice who has a balance of a of a, coins and she she wants to transfer the she wants to transfer 100 coins to Bob who also actually happens to have a thousand coins so she calls our transfer method uh with Bob as a recipient with 100 as a value so what do what do we do okay we first need to check if Alice has enough uh of the of the coins if she does we subtract the the transfer amount from her balance and then we learn the balance of Bob's account and increase it by by this amount and yeah just like that the the transfer is done and now Alice is left with 900 coins Bob with uh 1,00 and um and it's pretty cool because this is you know where our returning zero if someone is not in the maping comes in handy uh but yeah let's go through the code so don't don't worry about the about the boiler plate here uh basically the transfer is you know to an account from the Coler and we use the like the the wrapper here to make it a bit faster actually because wasm is good at references so sometimes it's good to convert something to reference uh this this is out outside of the scope but um yeah so so first of all we check the balance of the send of the sender uh if it's insufficient note that we don't don't you know don't throw an exception we just return this this error uh I'm going to talk more about this this this way of error handling then we decrease the balance of of the sender by inserting the previous amount with the value subtracted then we check the balance of of the recipient and insert well their balance with the transfer value added and we Adit the event and if everything went okay we returned this okay and now notice that if if Bob oh if in this picture Bob was not present in our system then the then the balance of implementation would return zero and uh it would actually all work and it's super simple and super nice um now you've seen this this this return error and something like that so this is a part of a of a larger concept of handling errors in Rust which uh yeah coming from hll I I I love this uh this is how you should handle your errors definitely uh so the way you handle errors in your contract but also well in general is uh instead of throwing exceptions which are by the way just a glorified goto mark my words uh you do this custom error type and you basically list all of your error cases and they are stes themselves like inum variants but you can put basically any information you want inside of these errors uh we here don't really need additional information in in case of some of them but uh some of them do require some additional description um so yeah once once we have this error we also need this this type similar to the option type that we returned from the mapping while getting so we have this this result that that has two variants it can be one of one of two things uh it's it's called the Su type by the way I believe um so it can either be an okay which is like the the happy path of the computation and then it carries inside the the actual result of this computation a value or it can be the the unhappy case in which case in it carries some sort of an error message and uh don't worry about the scary looking type barkings here uh it's just you know this just goes to say that this can be pretty much any type uh you want it to be and uh and yeah you can also you know if you're for example always using string as your error message type uh which you probably shouldn't but it works well for the for the example then you can make like a type alas um using the the the type keyword and one thing to note that the type keyword is not type checked so whether I write my error of t or my result of T and string is the is actually the same type right so there are some ways to distinguish types like that but uh the type keyword is not one of them and um and yeah this is this is actually pretty cool uh because you can now return your errors and uh it's up to you how you handle them right uh you can you can basically blow up your whole computation when you get an error but you can choose to handle it in some graceful way and uh it's good because you know it it basically puts all of the control of the error handling in your hands and um and doesn't and most importantly doesn't interrupt with the ex execution flow right so if you have like imagine I don't know nested for Loops if you throw an exception it just cuts right through all of the executions unless you catch it but you might forget to and so on and here it encourages you to structure your computation slightly differently and handle the errors more uh purposefully so I guess it's it's it's a great concept now the event is basically a way of letting the outside world know what is happening inside your contract oh I didn't read the slide but I just repeated what's here well it's okay um so for instance you might have a contract Explorer and someone uses it to or or like a web app and you want to use it you know display the information about someone's account what happened and so on similar to what you get in your in your like web to bank app you get the the the all transfers and everything so we can do a similar thing here and uh our code can emit events and events in essence how you declare them is you make yet another struct uh with a macro you should get used to it by now um the macro is ink event unsurprisingly and uh well you can put pretty much arbitrary fields in the in the event uh what you can also do is uh Mark Mark certain Fields as topics which basically will allow the the event ingesting system to like index uh these events based on this topic so for example here a good field to index on would be the you know the senders and recipients of the transfers uh because they should be pretty like discrete and and and unique uh the value wouldn't be a good field to index on right it's actually very similar to an index on a regular relational data base and uh prettyy much same do and don'ts apply uh now a question would be so this this event basically tells us okay a transfer happened and notice that we Mark the from account and to account as optional right so uh a question to you would be can you imagine a scenario in which we make a transfer but it has no sender or a scenario in which we make a transfer and has no recipient we want to anonymize it for example uh in this case probably the recipient would be something like uh like a mixer or something like that so okay yeah the the answer is uh you probably in some cases want to Mint and burn coins uh so minting coins is basically a transfer with no sender but with a recipient and burning coins is transfer with the sender but with no recipient burn is kind of like you know sending to devn or something like that um yeah so this is the way to emit emit events and um this is like the standard way if you dig deeper and uh and if you want to write uh like multi contract settings with cross contract calls uh you will need to handle your events slightly differently but that's a part of a larger discussion and I encourage you to to check out our EX examples in the uh on the LF zero websites there there will be some information about it um yeah so like I said the the option type you see that this is this is called an option type it has the sum and non variance similar to Scala I think Scala uses the same wording um of course you use the self en you've seen this method I think once or twice already in this presentation and uh oh and if you feel surprised by the by the asterisk here it's it's like an opposite of the m% right so you can take a reference to to something and you can actually take the something from the reference and D reference it similar to C++ um yeah so now a cool feature is that you can mark your messages as payable and uh this will allow the colors of of your methods well sorry messages as as we call them uh this will allow them to send some some of the chains native currency along with the transfer uh this is cool because you can have you know like an I don't know nft minting method that will require you to to pay it a few a zero in order to Mint your your nft right so this is a good way to to collect fees or take deposits um um yeah and the the way to to access well the value just gets you know added to the contract balance and oh by the way note that uh a contract is also an account it's kind of a special account but uh but it has a balance just like any other account and the contract can also make a transfer on it on its behalf um so so so there there are the important thing to distinguish is that we are talking about two kinds of currency here right uh the one we're talking here with payable is the chains native currency and uh all of the coins we were talking about in the previous slides were were the currency we we were just creating right it's like a more a lot more virtual because we we are just maintaining this this mapping um and what's also important is that while the chains native currency is you know is secured by all of the cryptographic goodies and uh hashes and validators and everything basically what you write inside of your PSP 22 contract then that's what you get and and the chain cannot verify that your that your logic is correct right so uh you need to be quite careful here um yeah so the once you have the general structure of the of the contract it's it's good to write some tests and I'm not going to dive dive very deep into into the tests uh just just know that they exist uh actually in two flavors one is unit tests so you know like they their functionality is pretty limited but they're fast fast to write and good for verifying like the very basic building blocks of your of your messages and your contract and you have end to-end tests which are quite a new addition uh but they allow you to test like the full full execution of your contract um yeah more on that in a second oh actually worth mentioning that in the in the PSP 22 standard or the erc20 for that matter as well well uh you have the approv method and the transfer from method which is very useful uh when creating like exchanges and other kinds of defi protocols this is basically a way to allow someone to transfer your coins on your behalf right and so there's an additional mapping involved saying who let who uh transfer how much and then you can transfer a someone's behalf uh it's pretty cool um yeah so a small bonus because well at least my my like knee-jerk reaction to seeing all these algebraic errors would be damn that that will be extremely tedious when I have you know multiple functions returning multiple errors will won't this just turn into a huge like you know ladder of if else statements or like pattern matches nested seven times well it would but we have this nice uh well syntactic sugar or yeah how how do you call it um we have this this this question mark operator right so imagine we have well essentially we have three functions so one is a computation that might fail with with error one as as the unhappy condition another function that might might fail producing error too so you know if we can handle it the the the brutal way saying okay if the first one failed then then just Panic kill the the whole program and same same thing for the two we can try to pattern match like different uh different combinations right there's there's four uh but we can do we can do this uh we can say okay let's let's make the top level function return some more general error and we will provide the conversion from error one to to this general error and from error two to this general error and now uh it will basically look like this right uh you might have actually seen similar stuff in JavaScript but here it's like based on these implementations of traits and uh and then you might think okay but won't this be even more tedious when I have to write the conversions well no because first of all the conversions can be can be really simple and second of all in like day-to-day usage uh you're not you're rarely creating your custom errors and uh usually all of these error STS will just have these conversions implemented so in essence this just starts looking like you know like regular imperative code but with the question marks so you know that it might fail and um there's full type safety and I think it's pretty cool um yeah so once once we created this we can deploy this on chain again no live demos here I've learned my lesson a few times um yeah so so we have this contract uui again you can use uh CLI and cargo contract to deploy your contract although I think for a workshop it's way more spectacular to showcase the graphical interface so I choose an account that I will use to to deploy this contract of course I have a either like a development version of the LF zero chain running or well I can deploy to testnet although I don't really recommend if you're tinkering deploying to testnet because well it's public so um probably better to start experimenting on your like local instance of the chain or or substrate contracts note or stay tuned um now I need to give the contract a name of course and uh upload the contract bundle that that that running the the whole cargo contract build uh gave me and uh it's going to get verified like if it makes sense and that you know check sums and everything uh now it's it's actually a two-step process but the the UI makes it look like it's almost a one-step process but first you upload the contract to the chain it gets like save to the chain it gets a code hash and then you instantiate the contract which basically means calling its Constructor and uh actually creating the storage struct and everything so yeah our our Constructor is pretty simple I choose what's the what's the balance that it will start with so uh sorry that all Supply it will start with there's some parameters uh that I can change but uh don't need to talk about them now but there's this really cool thing that it does is before the instantiation it actually performs a dry run so like it well you can think of it as simulating the run but it actually just doesn't modify the storage in any way it just runs it and uh this will this will tell you you know what how much you will you will pay in terms of gas fees and everything um now once you do that you basically get your get your contract on the Chain local or or not and uh you can interact with it and uh in the UI you you can of course you have the interact tab which which will allow you to choose the method and uh like interactively fill the fields and everything you can also view the metadata uh like I said this is constructed actually using the both the code and the dock strings you put in the code so actually it's super important to write good doc documentation for uh for the contract uh so yeah you can see that this roughly corresponds to what we've written uh and uh yeah this is basically us calling a basic transfer method I here I have a test another test account that I can that I can send some some coins to I can then of course verify that the that the balances change accordingly um and uh yeah there's a there's a log of the events so uh this is more or less how you use it now if you're starting in development or actually if you know you just want to move quick when When developing uh my recommendation for the hackathon and and Beyond would be to definitely check out Inc cathon uh this is like a boiler plate for a whole DB so including front end backend and smart contracts uh actually created by Dennis from from a zero ID uh one of our uh ecosystem projects deployed on the on the main net recently you should definitely check them out they're an incredibly cool project and in cathon is is written very well uh so it should yeah it should speed up your development um and another thing oh yeah there's a video um so a friend of ours from from Cardinal cryptography made something called drink which is basically I I somehow cannot make it full screen sorry I'm not good at computers um which is basically two things but the the most important part of its functionality is it gives you a way of executing ink contracts without spinning out a chain uh so this way it's extremely fast and uh super good for for pro prototyping for Rapid development um so you can use it as a library uh for example in your end2end test uh it's I think it's also going to become one of the possible backends for the end to end tests so that they run real fast and the other thing that you've just seen on the on the neat screen screencast is it has like a CLI or like a text based interface uh that well basically allows you to interact with the contracts in a in a quite interactive way and uh definitely check this out it's uh it's quite awesome uh very fast very convenient um yeah and you actually won't need won't need any other dependency besides rust to run it because it doesn't even well it doesn't even use cargo contracts it's it has all of the goodies bundled it B bundled inside uh okay I want to oh yeah yeah so uh thank you uh it was a pleasure to talk to to you and uh if you want to scan the QR code it's uh something that one of our teammates once created it's a like a kind of an assignment or like a smart contract scavenger hunt if you may if you will uh yeah that's going to help you you know get really good at analyzing contracts and interacting with them there there's no prices but uh it's a good learning experience okay so uh thank you that would be that would be it
