Safe and Robust Smart Contracts in INK | #Workshop Ethereum Brasil + Aleph Zero (EN)
Workshop Ethereum Brasil x Aleph Zero · 12 Jul 2023 · 1:05:35
A workshop on writing safer smart contracts in ink, the Rust-based contract language used on the Aleph Zero chain, built on the idea that exploits happen where developers do not know what their code does. It frames safety around unvalidated input, state changes, loops and fallback calls, illustrated by the DAO re-entrancy attack, then builds a simple PSP 22 token, a standard equivalent to ERC-20, to show Rust ownership, Result-based error handling and events. It closes with unit and end-to-end testing and a walkthrough of deploying and calling the contract through the contracts UI.
Speakers
Topics
From Workshop Ethereum Brasil x Aleph Zero, hosted by Ethereum Brasil.
Transcript
foreign they can text you and sometimes it's easier to make a question and to answer on the text and Google translate it can always help so I will ask you to introduce yourself talk about a little bit of Olive ziron and start your Workshop uh yeah sure uh yeah so like Esther said unfortunately I can only do a workshop in English well I can also do it in Polish but I I don't think that's during anyone any good
um so yeah I I work as an ecosystem Tech lead at lf0 I'm actually uh going to talk about that zero bits as a part of my workshop but basically we we are a layer one chain with uh well we're building on top of substrate but we with our custom consensus uh algorithm called lftft which is like uh up there with the with the fastest ones and uh the performance of rally is is great um also right now we're heavily focusing on the Privacy features and uh of course last but not least we the the chain features smart contracts in ink uh which is something we're gonna take a look at
today um but actually uh quite a lot of what I talk about during the workshop is also applicable to like solidity or or programming in general I kind of try to make this you know like accessible and interesting to to everyone uh how do I access the chat oh yeah yes I mean the polkadot one yes well parity one so it's um yeah if you know polka dot or or any other chains uh in the polka.ecosystem you'll I think you'll find this familiar um although well we do have some uh some differences so I I hope you will find this interesting uh so without further
Ado uh would you mind if I shared my screen because I've I've got some slides uh -huh yeah there's some some stuff I need to okay can you can you see my screen yes that's that's perfect uh so uh the issue is that if when I present this I don't actually see the chat so maybe I will I'll tap quickly actually if I do this it should be it should be all right right yeah okay awesome um so yeah uh so the workshops title is save and robust smart contracts in ink
because I well I wanted to focus and and underline the importance of basically writing safe and and robust code um you know just starting at the level of the of the programming language itself and how you write your code and I think this leads to to better and safer smart contracts um so yeah every time I started a workshop I I quote this definition but um well the point here is that treating a smart contract as a as a contract in a traditional sense is well it's valid to some some extent but but also can be quite misleading so I basically think of them as programs that execute on the
blockchain that that kind of treat the blockchain as a computer uh which is actually quite a quite a good analogy because the blockchain has a run time the blockchain has storage so it's kind of similar to to you know like the mod models of uh of computation that that we that we know from from I don't know computer science courses um so obviously once you equip the blockchain with with smart contract capabilities you you make all the all the logic pro programmable so you can start to build interesting use cases uh of course starting with defy uh so the centralized Finance so kind of like tradition National Finance but without the trusted intermediary
um without uh you know without censorship and uh and with with all the Democracy um and also well this gives way to some some additional additional ideas and additional uh instruments uh a very interesting space where you could actually apply smart contracts is the the whole digital identity area so uh stuff like uh you know kyc and KYB projects are are the distributed ID in in general uh very interesting more on the on the Enterprise side we have Supply Chain management and provenance tracking
um also somewhat of a Hot Topic always I I would say uh certificates of ownership so well I would say traditionally nfts of course but it goes actually you know the the use cases of for nfts can be quite interesting uh starting with art so like you know uh verifying authenticity or ownership of uh interesting art pieces uh ownership of real estate and kind of like shared ownership of real estate uh software licenses and ticketing software can all actually leverage leverage this mechanisms and of course it doesn't end there uh you can easily you know come up with your own use case which is of course what I encourage you to do uh if you if you get interested get interested
with Inc and and and start coding um now as I I well I think it was in the Spider-Man movie that with great power comes great responsibility um so well it's it's the same thing with smart contracts uh the exploits do happen and uh well as as as programmers as defy users it's it's it's good that you know we uh we try to try to limit the impact try to write safer code try to be more um yeah try to be more responsible in the in the actions we take in the web three space uh so you know from the from the programming side I I think we can we can
formulate this and and this is sort of a joke but the the grand theory of hacks so I I think that the the exploits basically happen in the places where you don't know what your code does and uh or or not 100 sure and this sounds very trivial and kind of extreme but it it actually works quite well um so you know the examples of what we would like to avoid and and I'm actually going to show how you know how using a decent language with a decent compiler and adhering to to good programming practices can actually help you you know minimize this this this uncertainty in your code uh but definitely the things to watch out for is our uh input not being validated right so basically
anytime a program not not only in a smart contract but any program accepts user input it needs to be to be validated against the expectations or against what's allowed um you know so classic examples would include some uh JavaScript injections or stuff like or SQL injections but it basically any user input needs to be like really carefully uh validated uh then and uh disclaimer here I come from a functional programming background uh so so I kind of care about this a lot probably more than than the average among programmers but but hey uh let's say it uh I think anything that mutates
the state of the contract or the state of program actually uh is possibly unsafe in in in different in different uh and different meanings so you know either unsafe from a concurrency perspective or unsafe from like the being a vector of exploit uh perspective and uh this might seem even more extreme but any place where the code repeats either you know uh be that uh for Loop or a while loop or especially any sort of recursive um so like a function calling itself directly or indirectly uh or a contract calling other contract and uh this
possibly forming a loop that can be quite dangerous as as we're gonna see in in just a moment and also as we're gonna see in a moment any catch all uh catch all execution flows or fallback methods or implicit operations are possibly very unsafe I'm gonna check the chat real quick okay yeah no questions that's uh that's good but don't hesitate to ask them I'll I'll be checking the the chat once once in a while uh now um so as a as kind of a very motivating example uh I I like to describe the the like the very basics of the Dao hack
that happened a few years back and of course now the the whole the whole landscape looks a bit different the stuff has been since fixed but uh this basically illustrates a very simple re-entrancy attack that was exploited to actually steal a lot of funds from the contract so uh well let's say we have this dial contract that for for the purpose of this example basically has only two methods uh it has the deposit method where you can actually deposit some some eth and it has the withdrawal method that well uh you can withdraw what you've deposited and of course uh yeah we well we have this this attacker
um and I'm calling the idea malice because it's a Twist on the on the classically used you know Alice and Bob in in names in cryptography um but let's say malice uh wants to attack the Dao and uh like I said this is like a high level overview of how this happened more or less um serving only as an example but so what was how the attack uh went through was someone deposited a certain amount of heat uh well let's say it's it's a hundred um just for you know easy easy calculations but uh someone deposited the 100th and then they they wanted to withdraw the the 100th oh but actually
an important uh thing is that it's the the attacker is actually a smart contract itself right so after depositing the the contract asks the dial contract to to withdraw uh the amount they they deposited earlier and uh of course the Dow contract checks if if the balance is enough and then does the transfer of 100 East back to the to the attacker contract as it should but what's what's key here is that the Dow contract only updates the balance of the of the account after the transfer has completed
but in order for the transfer to be completed the it has to be handled on on malice's side um and the way it works in in solidity in in eth is uh a contract have can have a receive method when it when it receives a transfer it can handle the transfer or it can have a fallback method that can actually contain arbitrary logic including uh cross-contract calls so the attackers contract actually in the fallback method contained another withdrawal call and if you recall that the the balance of of the balance account was updated only after this whole thing has finished uh has finished
transferring you will notice that this forms uh an infinite Loop of course the attacker had to check if the balance of the dial contract has not been exhausted down to zero because if it tried to withdraw under under zero of course this would uh throw an exception and abort the whole the whole Loop but but this basically formed this this re-entrancy Loop that allowed them to to drain the the dial contract really fast right so this basically goes to illustrate that you know very simple simple mistakes and sort of like well something that can be very easily improved can actually have a very drastic consequences so
so the point I'm trying to make here is it's actually worth spending a bit more on writing the code than you know fixing the aftermath of exploits and and errors in in production um so now moving on to to the actual the actual smart contracts uh we're going to be looking at ala0 which I already introduced but uh like I said layer layer one proof of stake blockchain actually nominated proof of state blockchain with strong focus on privacy we're creating the liminal privacy framework you can you can read about there's going to be some links in a second uh with sub second finality times and and block times extremely low transaction costs uh so for smart
contract developers this is this is actually quite quite important because well your contract will quite possibly be doing quite a lot of transactions and uh and the gas fees are actually um also also the a factor here so this is very low on that zero and well of course it has smart contracts in ink so we're gonna uh we're gonna introduce Inc and uh ing as a language can be used of course on uh on other chains that that support it now here's a bunch of useful links um the first the first one is the main website about zero and it actually contains references directly on or indirectly to all of the other links the second one is the documentation on uh on
git book and then the developer portal which also contains a handful of of useful links uh test a zero Dev is the developer wallet so maybe not the best user experience but but like feature complete if you want to interact with the chain then the contracts UI so uh graphical user interface way of interacting with the contracts and uh something really useful so the JS API to to talk to the chain to to get some information from the chain or do transactions uh which is gonna be really helpful if you you know you'll deploy your smart contract and want to interact with it from uh from your from your app from your web app then this is probably
the thing you're gonna use um so I'm just posting it here for reference now so Inc what is Inc so in contrast to for example solidity Inc is not a separate language but instead it's an embedded domain specific language built on top of rust but both putting it in in more intuitive terms it's basically a subset of rust uh with with some additional macros uh that are contract specific um so this has some benefits because well for example if you know already know rust uh you can you can basically switch with no effort to to Ink um actually if you know solidity you
also can switch to Ink very quickly because you will find most of the concepts very familiar um but then being a subset of rust it it has the same benefits as rust so being you know a modern language uh like integrating a lot of programming language Research into the language um a very type-safe language as typesafe as a language I would say as typesavers language can be without sacrificing developer experience and uh like uh well and how quickly you can write code uh memory safe with a very interesting and uh and performant approach to to
memory safety the tooling is is is quite good like building on on Rust tooling and um and of course quite quite universally liked by developers as evidenced by the stack Overflow surveys year by year it seems to be the the hype right now um and then what's important about Inc is that it compiles to wasn't so webassembly which of course comes with its own set of benefits um it's it's basically it can run everywhere and it's fast and secure um yeah very nice standard um this this table might seem daunting at first but it's here to illustrate that
basically most of the concepts you will be familiar with from solidity from your experience with solidity can be applied in ink with without uh too many modifications of course there's a different syntax and the different type system but but you should you should feel familiar if you know the ideas um actually a notable difference is the the differences in storage entries so solidity uses 256 bits as the only possible size of a storage entry uh and in ink this can be this can be that an increase can be variable and is variable uh which has some some good
performance performance benefits uh yeah so this again this this is just an illustration actually treat this as a picture because this is like an overview of what you need to do to to jump start your your ink development so you install some dependencies um new install cargo contract which is basically a um build tool and and package manager and everything for uh for Ink Smart contracts it's of course building on top of rust's cargo which is the same thing but for rust uh then you use cargo contract to bootstrap a new contract and it comes as actually uh ready to deploy
contract which is which is actually quite important in in how we approach the the following slides because well you have all the scaffolding after writing the the cargo contract new Command right so you don't really need to memorize all the letters in your contract you actually need to only focus on the on the general idea and uh the rest will be basically provided for you and you can just just modify it and treat it as a reference point so uh even though the number of you know macros and and new syntax can seem daunting at first it actually is not when you when you actually start using uh rusting and cargo contract then you of course a compiler contract
uh well starting with the tests obviously as as good programmers do and and then you run you build it and you can you're ready to upload it to the chain uh yeah so uh yeah it produces like essentially two artifacts so the the actual wasn't file with the with the with the with the code of the contract uh as a webassembly format and the contracts metadata which then the contract explorers and uh the contracts UI and your users in general will use to to know what methods to call on the contract and what they do it's sort of like a documentation
um and uh like a reference for the methods in inside the contract and uh as a convenience that two the two files are bundled as as one contract file um yeah so uh we're gonna take a look at how you upload the contracts to the chain later but yeah so this this joke is is kind of maybe getting old by now uh but yeah we're gonna create a simple erc20 or as we call it PSP 22 is basically the same standard uh token someone's actually now I think made a Bitcoin on oh now at zero so
um yeah uh but but it's basically just uh just a name I picked because my name is Pete and we're making a coin here so a very simple fungible token contract um so now the erc20 standard is basically yeah this this ubiquitous standard for for fungible tokens and this actually a very basic set of methods that or or messages that the contract will have to be able to reply to in order to to be treated as an erc20 contract and we're gonna focus on just a few uh here right now so the total Supply is obviously well just just that a total Supply so the the overall
number of coins in in circulation of your of your token the balance of a specific account is is basically how much of the tokens it has assigned and is able to to transfer spend uh let's let's forget the allowance and uh the most important function is obviously the transfer so uh yeah you need you can transfer some of your own tokens to to someone um yeah events we're gonna talk about later um so yeah jumping right in this is this is what the what the contract looks like uh at a glance there's some there's some macros that are going to be generated by
the cargo contract new command actually depending on the version of of uh of rust and ink you're using you might need to add a no main here after no STD uh but that's that's not very important it's going to be generated for you uh now the important thing is that a contract is basically rust module which is declared like as mod and and then the name uh and the the module is kind of a basically a collection of things so kind of similar to namespaces if you're familiar with C plus plus uh and um and yeah you can you can basically group stuff together under
under a common name uh now in order for this to be a valid in contract it has to be decorated with the ink contract macro which which actually does a lot of stuff behind the scenes uh some of them being enforcing certain invariants as to you know that the contract needs to have at least one method at least one Constructor well at least one message which is which is not the same as we're gonna see in just a just a moment at least one Constructor um yeah it also gives you some uh some handy aliases that we're going to use in just a second uh oh and of course by the way the the
things starting with with hash signs are rust macros those are not comments if you are coming from the python world uh this is how you write rust macros so now of course the most important thing in in your contract aside from the logic is its storage and the way you declare it is you basically use uh regular rust struct which which is basically similar to how you would define a class in in other languages or or actually extract in in language in a language like C or C plus plus um now the important thing is that of course you can access the fields by typing you know the usual syntax so like
the strike strike's name and Dot and the fields name uh but the strats don't have inheritance um which is I think it's a wonderful choice that rust creators made it makes a lot of stuff simpler and actually prohibits writing you know abstractions that are over the top and the important thing for for this is that it has to derive well it has to be marked by the ink storage macro uh and and yeah and it needs to oh I actually don't know if this is this is required but definitely very uh very handy and and you absolutely want to do
that so deriving the default is basically allowing your your strut to have like a default like a zero uh zero instance that you can use to initialize it and only then fill it fill its Fields with with some specific values and for our specific example our our storage will hold the total Supply and uh and basically the sum of no sorry the mapping containing you know the mapping from every account known to the system to its balance uh and the balance and account ID types are are provided to us like for for free by the Inc contract macro that that that
we've seen before and uh oh yeah and to use mapping you want to use this rust use uh statement which is uh you might think of it as an import but but it's actually closer to basically bringing some name into scope uh it actually has no magic involved as Imports in some languages might uh this is just you know saying yeah use use this name and now we're able to use this this mapping type um now after we have our storage we can end our struct we can attach some Behavior to destruct in our case this would this would be the Constructor and the
messages that the contract will be able to to kind of handle um so in Rust you do that by by writing impul and the and the struts name so this this is saying okay this is this is a set of methods that this struct can can can perform or can can respond to uh the first one we're gonna we're gonna take a look at it's gonna be the Constructor uh which is basically a regular rust method with the only difference being that it has to be marked by this ink Constructor macro and it doesn't even have to have a specific name uh by default it's new uh because it kind of just makes sense but you can actually call it anything you
want uh as long as you mark it with the ink Constructor macro um um yeah sorry um yeah so this also means that the the contract can easily have more than one Constructor it needs to have at least one uh that's that's enforced by the by the in contract macro now in our case the construct oh and obviously the Constructor needs to return the instance of our struct we are using this uh well we we could actually instead of self here uh right peat coin but rating itself is kind of a good practice as it
kind of works better in this you know uh trade-based world or it's kind of more generic how about only slightly it's also shorter to type if if you're into this the developer economics um now what we do here is well when someone's creating the uh the contract instantiating they need to call the Constructor so obviously they are the the contracts like owner at least of this this instance that they create um now they need to set the initial total supply of the of the co of the coin of the token uh which will be passed in the in the Constructor as an argument now
we initialize the balances mapping first to the default value uh which for a mapping and actually any container uh is is just an empty uh container of this type um now then we we try to find out what's the color of the contract by using this magic nth method on on the well on the contracts track itself but it's basically like a global environment of this this party okay it's an environment of this particular contract allowing you to for instance as we see here get the color of the contract but also you can uh find out stuff like for example uh what's the account under which this contract is
deployed um now as mentioned previously the color of the Constructor is obviously the owner of the contract so into the balances we insert a a mapping that says okay when someone's creating this contract for the first time they get the whole total Supply if then they decide to do some transfers obviously this is gonna get divided in more entries will be entered into the balances mapping but for now it's just that and then we instantiate this struct it's actually a shorthand syntax because uh you can this is what happens when the values you you put here the variables have the same name as the fields you can also write
like the fields Name colon and then the value you want to assign um now this is kind of a side note but but I I think it's very interesting and uh even though in the contracts you won't have to dive really deep into how a rust manages memory I think this is uh this is interesting and well to some extent it's good to know uh when when writing smart contracts so and that is how rust manages memory um so the important thing is that the way rust is doing that is avoiding the garbage collector altogether so you know garbage collectors come with their own set of problems uh like for example this
Java garbage collector used to be you know like a stop all stop all machine that basically once it fired it basically stopped all the threads and started started cleaning up unused chunks of memory uh the smart pointers on this is also not how how Russ is doing that the smart pointers have lower overhead but uh are kind of not really comfortable to use uh rust is introducing this this idea of the ownership model and it actually has some uh like type theoretical basis if you want to read about it you can you can read about uh linear and actually well assigned types is probably the closest
ones one to this but that's completely optional only 14. for those of you interested in in type Theory I guess um now basically the the whole premise of of the memory management system is that everything you allocate on on the Heap uh has exactly one owner right and the core idea is that if you well okay the owner here is not like a person but more think of it as the owner is a certain scope so like a function or yeah most often a function now the the basic idea is that you only can you can only access the data that you
own um or have been borrowed but that's that's we're gonna see it in a moment and uh basically the rust compiler won't allow you to to touch or access anything that you don't own right so now of course you can transfer the ownership and uh there's two ways to go about that you can move something so this is basically like gifting some some piece of data uh and importantly oh this is actually very similar to pass by value semantics so you just give away your your value and in rest importantly you can no longer
use it if you if you move it if you uh if you give it away and it has a lot of sense like from from a memory safety perspective um you you might be familiar with STD move from from C plus plus now the second one is borrowing which has slightly more I would say involved uh semantics but uh but yeah it's also you can you can it's probably less less restrictive in a way uh so this is very similar to passing by reference from from another languages and now the cool thing about this is that you achieve full memory safety uh that's that's ensured at compile compile time and you
have well virtually zero overhead rust in general has uh has no like runtime overheads as some languages might um now to to show a motivating example I'll be at a very simple one let's consider this like extremely simple program uh it has a struct called Foo with just one field it's some number and um and we have this this function that into the function we are passing a struct like that but you know just a plane passed by value so this this would be the this would be the move semantics right and what we want to do is take the take the field of destruct uh add one to
it and return it no yeah so we we basically in the in the main function which is like the main entry point we try to instantially distract which is of course okay and then we try to call this this function on our on our struct which also should make sense and then we try to print the contents of oh well basically of destruct so yeah it all seems to to make sense and yet we get a compilation error and actually rust compiler uh it can be uh it can be a pain in the ass because it's pretty strict but it also is pretty helpful so it actually tells us exactly what's wrong right uh it says
well you're trying to to borrow a moved value which is basically to say okay uh you're trying to access what you've already given away after after you've given that away so uh and the new one here is that you can actually make this legal if you allow the the food type to be copied but let's let's not focus on that for now uh so like I said once you move the data you're no longer allowed to use it um and uh in the first we can we can try the second method right so we can try to to borrow the data so some kind of pass by reference the same code the only difference being this oh sorry I clicked
uh the only difference being this this Ampersand signed here before the fool which is saying okay this is this is borrowed into this function right so it's the ownership is not transferred it's just allowed to to to mess with this uh structure for a while now in the oh and we are doing a slightly different thing because right now we're modifying this in place um so now uh what happens is okay yeah we're we're passing this by reference and then we're trying to print the field which which would make sense but uh the thing is that right now we're modifying the field and uh rust compiler is saying okay you're modifying this this reference but you didn't tell me it was
mutable so hey this this is an error and you need to Market as as a mutable reference in order to be able to mutate it and uh this is actually uh you know connected to what I said earlier about how mutating the state is it's quite often dangerous and uh like rust is trying to help you here by you know uh making you explicitly say that hey I'm gonna be mutating this this reference uh so now basically a working version of this example is uh it's like that so the pass by reference is now accepting a mutable reference and when you pass this reference you also need to say hey I'm passing this mutable reference and now uh and now it works um yeah so this is basically the idea
behind the the ownership model and Brass memory management there's of course a lot of nuances at play here um like what happens if you borrow a value from someone and then return it from a function so uh like in the real world this wouldn't be a cool thing to do like or something from someone and just give it away so it's it's kind of gets tricky and rust but fortunately when writing smart contracts you I don't I don't think I've ever seen a case where you would have to do do stuff like that so that's that's pretty cool uh aspect of ink that it's a subset that's small enough and the domain actually is small enough that you won't have to worry about it um yeah so coming back to our actual smart contract after this quite quite
long detour into the into rust memory management uh so we have this read these ink messages right so any method on the class that we marked with ink message is basically oh it has to be a public method by the way uh the remark within message is is what our contract can can respond to like you can from an outside world so like from the contracts UI or or from some Explorer you can you can issue basically a transaction to the contract saying okay execute this this message and it will give you something back um so the messages we're looking at here are the simple ones because they only get something from the contract they do
not mutate the contract state uh well sorry um and there's actually quite different in the UI after after you see that um but but yeah the first one is as we've seen in the standard it has to be able to tell you the total Supply so this is simple uh it just you know the self is this is the same as in Python it just uh the the reference to to the contracts storage itself uh but importantly in an ink message the the self has always has to be passed by reference right uh so here we just return the total Supply and notice that in in Rust you have this implicit return uh thing
where you if you you don't need to write return if you're returning a value but basically the last line of the function will get returned um yeah so uh sorry I see that there was some if you avoid using the derive urinal uh yeah I think I think you actually uh you definitely would be able to initialize your strike like that sorry uh uh that's about rami's question um yeah but I'm not sure whether the contract macro actually doesn't require the uh the contract storage to to have a default instance I I don't know because
I never checked I always I always write this default instance I can well check later um so so yeah so the more interesting of these two methods is the balance off because it's actually a simple and beautiful idea that that we'll see at play here um so what this this method balance off does is basically you give it the the an account ID and it will go into the balances mapping and try to find the entry for this particular ID uh so the the balance of of that account and now we are using okay self-balance this is the mapping with the well with the balances and uh we're using the get method uh supplying the owner and we're
trying to get the the balance associating with that owner key now this can either return something if if this this this account is already present in the mapping or it can actually return nothing because well not every account has to be present in this mapping right the contract might not have seen that before so what this method returns is something we're gonna inspect in more detail in in a second but it returns this result type that basically can have two variants either okay with with the actual value of what you're looking for or error with uh with some error oh sorry this actually returns uh an option so like uh
either sum value or nothing but uh anyway we can on this result there's like kind of uh two variants we can use this unwrap or default uh unwrap or a default method which basically says okay if the value is this is this something is this the value we're looking for just return it if not return the default value for that type so if that's uh here that's that's a balance and the default value for balance is is zero right so this is actually a beautiful beautiful idea because uh as we're gonna see in a moment if someone has never used your contract their balance will automatically be kind of treated as zero
which then really helps you when implementing the transfer logic um now now yeah the transfers actually are super simple and I just wanted to do this graphic because I think the presentation looks way cooler with the with the graphics but the transfer is as simple as this so we have two accounts both with balance of 1000p coin and now Alice wants to transfer to Bob 100 PC um so the way we go about it is remember that we call that we have this this balance is mapping so effectively what the transfer is is we take the 100 PC from LS and update her uh her balance accordingly and we add the 100 to Bob
and um and that's all that's required right once we do that the transfer is done and it's actually not that different to what a bank transfer looks like in their databases right um so so with this simple idea we can we can actually implement this and uh you will see two methods here so one is like this public API uh that just takes the the account of the recipient the two account and the value that you want to transfer and the value the account from which you transfer is actually derived again from this end method just taking the color and then you can call this internal method to which is not public to actually transfer from from this
account to another account and then you switched to the argument types are actually switched to references because of how wasm is treating the um well it's basically and uh it's uh sorry it's an optimization to that has to do with how awesome Works internally um but but yeah so oh and importantly notice how okay yeah so let's go through the logic real quick uh oh I use this balance of impul but I just copied it from from my contract sorry should be balanced off for the purpose of this example uh so basically first we need to take the balance of the sender account all right so this is
called from here and of course the balance that you have available needs to be greater than uh than the value you're transferring right you need to have the funds if if it's less then we need to fail with an error and uh this is the the rust result type that I'm talking about so if if something went bad we're returning this error variant that can contain a customer we're going to see that in a moment but notice that we're not throwing any exceptions or uh disrupting the execution flow in any way this is what I call the algebraic way of handling errors which is a lot of benefits I think um now once we've verified that the transfer is actually okay to be made we
can you know update this remember the how we took the the 100 uh coins from from the sender from Alice this is just it so we insert to the to the from account balance basically what it was before decreased by the value that the sender wanted to transfer now we need to take the recipient's balance and this is this is the cool part because if you recall how the balance of implementation uh will return zero if an account is not known imagine you the the two account is an account that this contract has never seen before and uh so the two balance comes as comes back as zero and now when we insert to
the balance is mapping the updated uh updated value if it was previously not present in the mapping the two balance will be zero and now the it will just have the value that was transferred which is which is exactly what we want to do and the last thing we do is emit an event we're gonna talk about this in a second and importantly if everything was okay uh notice that we're returning this this this result type we need to say okay return the okay type that's gonna have some empty value because just everything went okay now and this is I think this is uh a great step towards writing your programs in um in a safer
way so handling your errors in a in a modern way basically it's not actually super modern because it was used in Haskell since well for like 50 years but uh but still it's it's what's uh I think it's considered like up to date now um so what we do basically is we create this this enum so like it's like a variant type it can be the error can be one of the constructors inside so either a customer with some message or Inception balance if if we were trying to make a transfer for more money than we actually have well more tokens uh allowance don't worry about that and zero recipient or sender basically if we if we put some nonsensical value as the
as a recipient it should fail um this is actually I think copied from some reference implementation of a PSP 22 token now this is a re-implementation of the result type that rust has uh called my result so that if you paste it it won't cause any conflicts uh now what's important here is that it's an enum that has two variants so it's a result of some computation which can which could have either went okay it in which case it just contains a value or it could have aired in in which case we received the error variant back containing some some error message it doesn't have to be a string but
sometimes this it can be a custom error and uh basically in the in the pointy brackets here we have the type parameters this goes to say that those are basically generic parameters uh type params uh that can be instantiated to anything anything you want and still will be type checked um the the type keyword is just a type alias2 to make your life easier if you're for example always using string as the error type you can you can write like a shorthand uh notation and use this importantly the type Alias is not type checked um yeah so so I believe this is this is called a sum type so it can either be you know the okay result or some error
um yeah so so I would also like you to know how this is a lot more expressive than the Boolean type that's returned by regular erc20 contracts and uh and they only usually fail through like requires and stuff like that I I don't I don't think that's that's very that's a very good way to handle uh your your errors exceptions have been called the glorified go-to if you're familiar with this very old concept um you know coming back again to our contract an important aspect of the contracts are events uh of course you should be familiar with the events from from solidity if you if you've programmed that before but well in ink basically
I guess what you do a struct as as previously and you need to market with the ink event macro again you should be by now you should be familiar with the ink macros that they put them basically everywhere um now events have destruct has has certain fields and some of them can be marked with ink topic which is basically telling the all the indexers or wallets or explorers that actually ingest the events from the contract to to index these these these events based on that that field to make it easier for you know lookup and what not um oh yeah this is actually if you want to
think about it so this event basically tells us that okay a transfer happened and we yet we Mark the from and two accounts is optional so you can think about the cases in which uh uh in which you know a transfer has happened but for example it has no recipient or it has no uh or it has no sender right it's it's very interesting but but it happens yeah so this is how you emit an event um this is actually a very basic version using the nth variable uh if you if you look through the example code that's uh at our which is Cardinal cryptography or l0 smart contracts or some other smart
contracts you will notice that usually people use a more involved method of emitting events that works better with uh like multi-contract scenarios um oh and by the way this this sum uh type here is basically just like the result but it's a result without the the error message basically so the error information so it's either some happy uh Happy result or basically nothing so this is good for for stuff that may not yield value but if it doesn't it's not really an error so you try to find something in a map and you don't find it so it's it's not really um an error it's just well it wasn't there right so the option type is very useful then
um yeah so like the the remaining stuff that might be interesting and that you might want to look up later because I don't want to type too deep and make this make this too broad is uh making your your methods your messages payable because ink and well actually wasn't smart contracts allow you to transfer some value value understood as the native currency of the chain so in case of r0 this would be a0 or t0 if if we're on the test net so you can transfer the the value to the method alongside the call and then inside the method you can see how much was transferred so you know you can take deposits this way or or charge some
fees for for the functioning of your contract it can be quite useful um now testing testing is very important I cannot stress this enough and actually ink is cool in in that it comes batteries included with with quite a lot of testing functionality so first of all and your kind of first line of defense uh after the compiler itself with its type Checker uh are the unit tests so of course you're familiar with unit test uh here they can be used to kind of test like the very simple granular granular behaviors of of your contract uh you write the tests as you might have guessed uh by using a macro it's ink
test above a method uh you also put the test in a separate module um but yeah so so unit tests are definitely very important and allow you to iterate really quickly and find well actually simpler of the mistakes um and then oh yeah and then you also with the with the version 4.0 of ink and it's getting constantly improved you're getting also the end-to-end tests uh and I'm gonna show you some an interesting bonus later about how to how you can interact with the contracts in an interesting way now this is a bonus uh just because I I really like those you know those those
algebraic errors and those algebraic uh all direct data types adts uh such as the result so as it often happens well when you look at the at how we handle our Errors By returning these results that can either be okay or error you might think okay this this very quickly turns into a completely incomprehensible uh like a ladder of if statements or some pattern matches and uh and I would to that I would say well it would if not for some uh useful shortcuts and syntactic sugars and whatnot so one of them not not the only one but but the
the spectacular one is the is the question mark operator so if you look at this uh we basically have two functions that return in different errors uh and and yeah we could kind of uh do the pattern matches like like in the main method here but it's a lot of work and we actually don't really want to do that um so yeah what we what we can do is we can write this this this uh implementation of a from trade for oh you're gonna see that this is the the first one returns my error one the second one returns my error two so different types incompatible uh we can write the
well a third error class which is going to be like the the umbrella error and we can write conversions from the first error to the third error and from the second error to the third error and now notice that this is usually once once you're using rust and or Inc and his libraries this is usually written for you so well yeah you sometimes need to write it but but usually this is this is way less boilerplate than it would seem now once you have these conversions you can just you know write your computations as if they never failed but only supplying this question mark sign that basically tells the the whole function to okay if it succeeds then it's great just read it as a normal you
know pure computation if it fails just fail the whole function so then you're able to chain a lot of operations that might fail uh very seamlessly and with very little additional code and then you will if you if your conversion functions are okay you will get a very a very uh yeah meaningful error um which well I think is pretty cool um actually some other languages also use the question mark operator and maybe uh maybe not as cool uh now deployment on the Chain I think yeah I think I don't know how how long we actually have
uh but uh but yeah it's like uh 1am already for me so I'm just gonna use my screenshots and not do a live demo uh so this is what the deployment on the Chain looks like and this is the graphical user interface version so there is also the command line version it's all described in our docs uh both are both are cool this one is way nicer for the presentation so you basically go to this uh cargo Dash con sorry contracts Dash UI dot substrate.org I think yeah and and the link was there is there in the presentation I think it will be posted so so it's uh no problem to to get this um so you need to choose the account from which you're deploying you need to
choose a name for your contract um and then you do you do a few steps steps first you select the contract bundle here so the contract file that you get after compiling your well your contract and uh the the bundle will be in your projects folder by the way in the Target slash Inc folder so that you're able to find it easily um now after you do that you have the chance to instantiate the the contract uh note that uploading the contract is not the same as instantiating so uploading is just getting the code to uh to the chain and then you can create
multiple instances from the same like code so but yeah uh here we are just gonna just gonna create a new instance of the contract and uh yeah this basically means calling the Constructor with with the appropriate arguments uh there's some there's some values here which we are not going to focus on uh but importantly the the whole system performs a dry run of your contract so kind of like a simulated run that's not actually you know uh modifying anything on the Chain but will give you the idea for first whether the contract is okay and will not fail during instantiation secondly how much gas will be consumed and uh how
what fees will be incurred now after you do that you need to confirm um and uh yeah submit the transaction sign and then once you do that you're able to interact with your contract uh notice that your contract like I mentioned previously has an account and interestingly here you will notice that for the math for the mail messages that do not modify the storage the the UI doesn't even have to do a transaction to the chain I think it just does an RPC call so that it's almost in happens instantly um if you want to if you want to check the methods that you have available this is the metadata
file parsed here that we mentioned previously and it contains well especially if someone took the time to write the documentation in a well in in a good way then you will have your your document documentation here of all the methods so you can choose you know the right arguments and and the right method to call obviously um if you choose a method that modifies the contract storage s will be the case with the transfer method here which obviously will change the storage mapping uh you will need to choose the account to which to wish to transfer uh by the way side note it's it's useful to have more than
one account if you're developing the contracts because you will probably need a second account to test the recipients and everything um yeah and this actually will require doing a transaction so you will need to sign it and and call the contract uh oh and of course you can inspect the events that get that get displayed now to to finish things off uh there's there's a lot of uh interesting projects being being built on on top of Ink on top of zero on top of on top of substrate uh one notable example and especially useful to to Ink developers actually both newcomers and seasoned
Pros alike is the inkathon boilerplate which basically gives you like a batteries included full stack application that that has some smart contracts able to talk to them you're able to connect your wallet so it's a really good way to to jump start your your development uh it's it's made by uh by one of our ecosystem projects actually by Yeah by Dennis and and one of our because some projects shout out to them awesome awesome projects awesome work uh secondly a de facto standard for uh for creating tokens in ink is the open brush Library really cool um
now it's if you're familiar with open Zeppelin this is this is a very similar thing but for but for Inc so if you're you know starting to write in smart contracts sooner or later you will either use it yourself or encounter a contract that uses it because it's super uh super common in ink ecosystem uh now this is this is a bonus that I wanted to show you just to just to show you what we're working on it's it's public but but it's not really ready to uh yeah we don't advertise it yet but hey especially for you this is a demo of of an awesome thing done by one of our developers this is Inc that doesn't
require a chain to run uh so it's super super fast it's as fast as any any Rebel you've ever used actually one of the faster ones because well there's yeah things just happen so fast I love it Yeah so basically this is the way for you to get to know Inc uh without you know the whole uh kind of cognitive overhead on you know running a chain instance or using a test net uh or or something like that oh how do I yeah okay um
so basically this would be it I'm just gonna check if there are any questions real quick uh okay yeah so so thank you so much it was it was really great to be here uh sorry I couldn't do the workshops in Portuguese if I if I learn it because I I love the sound of the language if I learn it I will definitely come back and do another one so so yeah thank you everyone if there are any questions uh then by all means write them in the chat and and yeah thank you so much thank you Pete did you see if there is like any unanswered questions to be
answered on the chat no okay um thank you very much um for your time for uh helping the community to learn something new uh I think everyone will be able to be in contact with you and if any further questions comes around uh you can talk to people and help them and to everyone that is here we gonna put these Workshop into YouTube with subtitles in Portuguese and trying to and share the presentation with everyone okay thank you very much and have a good
night he