Smart Contracts in Ink!: Not Only for Solidity Developers | Piotr Moczurad - Aleph Zero
Ethereum Denver·Wed, Oct 9, 2024, 12:00 AM
Learn how to write smart contracts in Ink!, the language used on the Aleph Zero blockchain and many other Substrate chains. In this rapid live coding session we'll build a token from scratch, covering the basics of Rust, Ink!, and a few principles of safe contract development. APPLICATIONS FOR ETHDenver 2024: #YearOfTheSpork ARE OPEN APPLY NOW https://ethdenver.com/apply
Transcript
[Music] hey everyone uh it's great to be to be back here for one more year and uh welcome to the workshop about smart contracts in Inc uh targeted not only at De developers coming from solidity but pretty much uh at everyone who wants to give writing smart contracts a try and uh if you've seen the workshop last year this this year is going to be very different uh as you can see there will be no slides there will be just uh me live coding so the best case scenario is that we're all going to have some fun and learn some Ink Smart contracts the worst case scenario is that everything goes wrong and this will be a cautionary tail not to do live coding ever um but yeah let's uh jump right to it so on the on the right hand side here I have a I have a contract that I basically copied over from from solidity uh tutorial documentation and uh it's this very simple very simple fungible token almost an erc20 but but not quite it's missing some functionality and what we're going to try to do and hopefully we succeed is we're going to uh take this exact contract and rewrite the same functionality in Inc uh which is the language that you can use and on some of the substrate blockchains uh first and foremost on the ALF zero blockchain that I have the logo here on my chest um and uh before we start you're you're going to see quite a lot of code um so you might think you know uh why why write this much code well that there's always a trade-off and the trade-off we making here is that we are writing code that's perhaps slightly more involved but a lot safer so uh you're going to see some examples of how how this actually increases the the the safety and robustness of our smart contract so um normally what what we would do to start is basically uh well we we need to install some tooling so I have this cargo contract installed uh in a pretty new version then uh I have of course a rust compiler because Inc is essentially a uh DSL a domain specific language built on top of rust uh so I also have rust in a in the latest stable version um and um yeah that's pretty much all we need to to to get started and normally I would just write cargo contract new and call it probably e Denver I'm not going to do it because I've done it beforehand um just to you know save on some save some time on downloading the contract uh now it's all set up and uh I also removed the the comment and some of the tests just to keep it super super streamlined super focused um so we just have the very Basics this is essentially what you get when you're starting out with uh with Inc um so there's uh the the lines starting with the with the hash signs are not commments as you might be used to from from python or or similar languages these are macros uh that's because the philosophy of Inc is why create a separate language if we can take just take rust which is you know it's a great modern language and with very safe set of features and just add some macros so that it's tailored more towards writing code that's going to be executed on chain um so you're going to see that we're in solidity we write you know the keyword contract and then the name uh here we just write a regular rust module uh if you're not familiar with rust the module is basically a collection of things uh you know kind of like a namespace if from other programming languages and then we need to put the in contract macro on top of the module declaration uh it just basically sorts out several things for us so that we don't have to write as much code and uh makes it Deployable on chain now uh okay so to start let's let's examine what the storage looks like in the solidity contract because well in solidity and in ink as well a contract needs some storage needs to store data on chain uh so here we have the uh the mentor address which I'm probably going to call owner in in our in our code because it's like semantically a bit more correct and then a mapping of from from an address to basically the amount of tokens that someone has and this is how we do you know this very simple fible token so let's do just that in ink um before we start the the way that you declare storage in ink is you basically take a regular rust struct uh which is very similar to well a class in in many object oriented languages uh or basically to an to an object or a trct in C++ for example and we need to uh put the ink storage macro on top just so that the compiler knows that uh you know it needs to figure out the memory layout and how to put it on chain um so so yeah the the the storage macro is necessary what's important is that the contract can only have a single storage struct uh it of course can use many other structs internally but the storage needs to be a single struct of course it can be arbitrarily complex uh so now we don't need the the Boolean value uh we're just going to need an owner which is going to be an account ID you'll notice that I'm not importing the account ID and that's because uh it's one of the things that the ink contract macro does for us right it uh declares some types and aliases for us to use and now uh before I can use the mapping I'm gonna quickly quickly import it and it's not so much an import as as as uh bringing some name into the Nam space right there's no magic happening basically now I can just use this this name uh so I'm just going to say okay balances is a mapping and um same as in our solidity contract it's going to be a mapping from the account address here we are calling it account ID to a balance and uh what we can do is I can put a um I can put a yeah unsigned 128bit uh integer as the as the value that's actually going to hold our balances there's also the balance type you can use but it comes with some some strings attached so I'm just going to use the the unsigned integer type type similarly to what we have in solidity one notable difference is that uh in solidity by default you have 256 bits for for every like storage uh for every number basically uh here the max is 128 uh partially for for performance reasons uh but if you need more there's libraries or you can kind of like model it as an as an array of of two such such numbers or you know four U 64s uh yeah it's it's pretty easy to do now since we've since we've changed our our storage of the of our default contract here uh we're going to take a look now at the Constructor um The Constructor and and all of the methods that we call messages are put inside the implementation block here uh that's this is basically the functionality that we attach to the struct here so the Constructor is one such uh one such method and um similarly to what you have in solidity with a Constructor keyword you have just a regular method here with the in Constructor macro and uh importantly a contract needs to have at least one Constructor but can have arbitrarily many so and they don't have to be named in any specific way but of course you'll want to choose a name that kind of makes sense right like new or maybe I don't know initialize um so we're just going to yeah uh oh if you're not familiar with the syntax of rust functions uh basically the FN keyword is how you define a function fun you can make it public or or by default they are kind of restricted to the module you're declaring them in um and uh here next comes the of course the name of the function the argument list along with types um and the return type here the return type is self uh it's actually the same as writing coin here but self is a bit more generic so so Ras developers tend to use this way and now we need to create our values inside the struct so let's say that uh oh you you declare the values with with let uh the owner is we need to somehow get the get the color so of of this Constructor so obviously the person who's calling the Constructor is the owner of the of the contract right they are creating it uh so just as we would do message sender in solidity here we have a slightly different way we're going to use the magic EnV method on on the class itself and uh and we're going to use the color method it's going to give the the the color of this method unsurprisingly and then the balances what we're going to do is we're going to take the mapping class and create a default mapping which is going to be the the empty mapping basically uh rust has this idea that uh basically you can have default values of of stuff uh if you implement the default trait for for some for some type uh you can specify what's the default value you know usually for number types the default value is zero for uh collection types the default value is an empty collection so for mapping the default mapping will be an empty one which which is kind of uh which is kind of convenient because uh no one has uh well like entered any data yet now we need to return the the instance of our storage so maybe let's format it slightly nicer um so the first field is called the owner and we're going to put the owner here the second field is called balances and we're going to put our balances here and now you'll notice that we're repeating oursel with the name and uh and the value that we put there so actually there's a shorthand syntax like this and uh if the name of the field and the value you're assigning to it match you can you can do it like this it's just a syntactic sugar but but nice uh we don't need the default Constructor because we kind of already have one okay um so we kind kind of have the the the storage taken care of um now we're going to oh we can we can probably remove the flip because the default contract is a simple flipper that just flips a Boolean value but we're going to do the mint method um so in order to create a message so not just any regular function but but a message which is basically a function of your contract that you expose to the outside world that's going to be called by different clients by the users uh you need to create a public function and uh mark it with the ink message micro you're probably beginning to see a pattern here of marking different things with uh with the Inc something macro um so so yeah instead of get uh we're going to have a mint um mint function and uh yeah let's let's see how we can implement it so that it's safe and uh and doesn't fail fail um now for now we're not going to return a Boolean but bear with me um so the first thing that the oh by the way uh an ink contract needs to have at least one message right uh it can have more obviously but at least one needs to be present just as uh at least one Constructor needs to be present now uh the arguments of such a message need to be a a self so this is basically a reference to the to the contract itself to to to its storage uh and it needs to be either a reference to self or a mutable reference to self what that is we'll see in a minute um but then comes the the the rest of the of the argument list so it's uh pretty simple they call it receiver and that will be an account ID I'm just you know like in a very dumb way I'm just kind of rewriting the contract here and there is going to be an amount which is you 128 now the first thing that we do here on the right in solidity is check if the if the person calling the mint function is actually the the Minter or the owner in our case it makes sense if you have a token you don't want to allow anyone to Mint the the coin obviously uh just the admin in this in this case can mint the coin uh so we could uh repeat what solidity does here with the with the require I think we could write just an a macro uh but that's that's kind of not the the rust way of doing things because rust likes to because well what the require does is it basically will abort the whole transaction if if it fails right so um we can take a bit more control of how we handle our Earth and do it in a more well like type type safe way I I would say um so first let's let's kind of just uh similarly to what we did before let's say the col of our message again using the magic method um you might wonder why here we are using self. n and uh in the Constructor we were using kind of like the class name dot do NF uh this is because in the Constructor we didn't have the instance of the contract yet so we were kind of using this special syntax and uh in case of the method that the self is here ready to be used so we can just make use of that okay we have the color uh you can see by the way that my ID is nicely inferring the types here uh I don't need to write them explicitly this is actually a pretty cool feature um so now rewriting again basically if if the color is different from our owner this is by the way how we uh reference the the struct fields just regular dot syntax if the color is different than the owner what do we do well one thing we could do which would be kind of like the solidity way is just to call like Panic here abort everything but we're actually going to do something yeah again uh more rust rust like and uh a bit more type safe and maybe yeah giving you more control uh over the error handling we're going to create an error type okay so we do that but by creating an enum enum you can think of it as basically rust's flavor of like a variant type it can be a type that can you know take several forms so in our case well let's call it uh coin error okay and the coin error will be one of the following things well let's just write uh one variant right now let's call it unauthorized and just leave it like that and now I'm going to do a very dirty trick because um like I said the compiler needs to know for stuff that you actually put on chain or or like return from the contract the compiler needs to know what's the what's the memory layout and so on uh so we have a few handy handy macros that that do this for us um but um to keep this short I'm going to show you kind of how you can do it in your code um without you know like tons of Googling so we're just going to go to to this page uh maybe you can see this is the PSP 22 repo of the Cardinal cryptography um repository which is the company behind the the ALF zero blockchain and uh this is our Implement basically pp22 is like the substrate uh equivalent of the erc20 token so what we're going to do is kind of like steal a line of code from here um so you can see that there's some that there's an error declared and there's some magic magic macros on the top so I'm just going to go ahead and copy that um as as you should probably like reusing is is a good thing um yeah so what this does is it basically automatically derives certain things for you so like the debug is allows you to print your objects in a user friendly way uh partially EQ and EQ basically derive you know the the the ability to compare these objects using equality um so so yeah without getting too much into it uh this is this is what we will need and then this is a handy macro that basically deres the scale encoding of uh of this struct and scale is is a system of that that the substrate blockchain blockchains use it's a system of like assigning weights to to certain instructions and and to certain structs uh to kind of let the let the the blockchain know how much gas will be consumed when uh executing certain instructions or putting certain elements on the blockchain so once we've done that we have the the coin error uh which which is already pretty cool because now what we can do uh is we can say Okay so this this mint method it doesn't return a b Boolean it doesn't return just you know nothing and just throws an exception it returns a result that's a special rust type that I'm going to explain in a second that can I that can a result basically as a type they can they can be one of two things either the happy case or the the error case so in the happy case we want to pretty much return nothing well the minting went well uh we return nothing well nothing in in Rust is written as two empty parentheses um it's similar to some other languages like for example hll um but in in case an error happens what we're going to do is we're going to return oh you've probably guessed it a coin error okay so coming back to our checking of the of the owner if the caller is not an owner what we want to do is we want to return an error variant of the of the result uh that's going to contain a coin error and specifically the unauthorized variant right uh that's cool and um we're going to come back to that a little later but uh this oh maybe actually maybe I will explain a bit more about the result type basically the result type is also an enum that is going to look something like this right it's going to be this or this so essentially a type that can take two forms either an okay with something inside like the the intended result of the computation or an error with any like error message type or like an exception type that that you choose of course these magic letters here are the type parameters because because you can reuse it in various scenarios uh supplying different different types here yeah so we've got the error case handled so now we want to um we we can actually simplify that later but now let's move on to actually updating the the balances so what we're going to do is we're going to check what the receiver balance is right now and we're going to do it by taking our balances mapping and getting getting what's stored under the receiver key right uh but as you can see probably by now rust has a very uh cautious way of handling errors and well when we're getting something from the mapping uh it's entirely possible possible that this thing we're getting is not inside the mapping so instead of just returning a a value or exploding essentially um rust uses a very similar concept to our result type it's basically uh it's called option and it's like it can be something or it can be nothing um so we're going to handle it in a like a shorthand way uh we can say unwrap or uh which is basically saying okay uh take take what's under the receiver key in the mapping right this is exactly the same as solidity does here but we're going to say if if there is no such key so basically an account that hasn't yet used our contract uh we will return zero instead right which makes sense um someone who's not using the the contract has a balance of zero and it actually tracks quite well in the whole like uh you know U bookkeeping analogy here um now what we're going going to do is now we're going to insert uh sorry insert into the balances what we've got previously under the receiver key obviously and the value is going to be well the receiver balance that we have have had previously and the amount okay um this makes sense the the the magic reference here is just the requirement of the of the insert method unless I'm mistaken which we'll find out soon enough um but assuming I got this right and this all went well now we can just return the okay type okay variant of our result and since we declared that inside the result we have a like nothing we need to put nothing here as well okay uh now here is another like aspect of rust that that uh many of you coming from like very D dynamically typed and uh Nimble languages might find annoying but it's actually super helpful in writing safe contracts so basically what rust is saying here I have the uh rust analyzer here uh is Russ is saying wait wait wait hold up you cannot change the balances if you haven't declared that you're going to be changing the storage right um this is important because I would say that uh inadvertently mutating something is like the source of uh a good good portion of the errors that happen in the in the code uh so what we need to do is basically say okay so our contract we need to kind of have a mutable reference to it so that we can you guess it mutate it right now it looks good uh so I think I've talked enough now let's try and compile it uh we're going to do cargo contract build uh cargo because I I think I haven't mentioned is basically like a tool for managing the packages in Rust and building and doing some uh auxiliary operations um if you're used to solidity it actually is quite similar to to using hard hat I would say so cargo contract build and we've got a few problems here um now it says that we don't have a default implementation for coin which is uh well let's let's add it um it's basically the new versions of rust I want you to have default implementations for we can actually you can see that we can actually use this error here to to do a lot of the work for us I can just write default self is going to be just self new this is maybe not too smart but good practice to have default versions of your of your structs and that's okay I'll I'll run it again but you'll see that we have one more error and this is a linting error not necessarily A compilation error but actually super helpful again so um I don't know if anyone in the audience is familiar with the batch overflow hack but um basically what can happen if you're dealing with like fixed length numbers like the U 128 here or actually the the solidity counterpart as well is that if it only can store numbers up to a certain length right if you go over that it kind of uh wraps around and you you start going from zero up again and uh if you're if you're clever you can leverage it to basically get free free tokens if the contract is written without you know sufficient care and here here is actually kind of what could happen here right so we if we made the the amount here sufficiently large we could kind of wrap around and actually insert a very small balance for the receiver so uh it's super helpful it's kind of annoying but also super helpful uh that rust well actually cargo contract makes us um makes us kind of do checked arithmetics here um I'm going to do it the the faster way um so what we're going to do is basically every number type in Rust exposes these uh checked variants of arithmetic operations and we're going to do checked ad amount I'm not sure my parentheses are matched yeah now and um since checked ad well it's basically a safe variant of the arithmetics right if if you add two numbers and they end up not fitting in the in the number type that we're operating on it will return a a non similarly so so like nothing similarly to what you would get from the uh from the mapping if there was no key that you're looking for so um instead of using like unwrap or or something like that we're just going to now we're just going to do with the the easy way and just unwrap it and say if if it if it's too much just just fail the whole contract like personally I wouldn't do it in my code but for the sake of brevity uh what I would do actually is basically Implement another variant of the error here um call it I don't know arithmetic overflow and basically throw this this error here similarly to what we have before but it's actually uh quite educational to to also know of that like the Shand way that will just fail fail the whole transaction if if this happens now fingers crossed I got this right and I did it's amazing um so yeah so we can we can already see a few things here uh there's a there's a few stages um of generating your contract but what you end up with is this this bundle uh that we soon going to upload to the chain and kind of uh play with it uh internally this this contract bundle is actually the the actual binary of the contract which is in in wasm um so web web assembly and the Json metadata which is what instructs all of the all all of the callers uh you know where to find the methods of your contracts in in the binaries and uh what's the documentation so what parameters are accepted and so on it's uh very important yeah so coming back to our example because we're not quite there yet um now going going line by line now we have the in solidity uh the the we declare an error insufficient balance we can actually do the same we already have an error type so we can just add to it add more variant right so let's call it insufficient balance and uh since in solidity it has also the named Fields so let's do the same it's requested it's going to be uh the unsigned in that we used previously and available and is also going to be the unan int um yeah so we've got this so moving on to the next line um let me just get my parenthesis right I think it's here we're going to need a next ink message that we're going to call send and um well since we already see that the scend will need to will need to mutate something around the contract storage we can kind of skip the skip the playing with a compiler and just uh use the mutable reference again if if we forgot it the compiler would complain and this is preventing us from from basically changing something by mistake right if you think it's a stupid mistake it's actually it's not right in my experience it happens quite a lot so again we we actually have uh pretty much the same the same signature receiver account ID and the amount u128 and we're going to do the same thing so we're going to return a result with nothing if if everything goes according to plan so we just have the side effect of mutating the storage and the coin error coin error I don't know why it's not if something goes wrong um first of all you can see that my my ID is uh is complaining that I'm not actually returning any results well that's okay I'm just going to put it here assume the happy case and we're going to come back to that later but let's see what what happens here in in the solidity code so first we check check whether the balance of the sender is is more well we check if it's less than the amount and if it's less then obviously the sender doesn't have enough uh tokens to to send them to anyone so we we need to throw an error and uh what we're going to do is we're going to well do actually pretty much the the same thing let's just get the color real quick I'm not I won't even bother to to copy it because it's super quick and um now let's check the balances right um so I won't copy paste because copy pasting is the root of many problems if you're if you're like me um Center balance is again we're going to get from the balances but now we're going to get oh sorry uh let's call it yeah let's call it sender sender we are going to unwrap again uh just because you know we don't want any errors here if if the cender is not present in the in our balances table it's the same as them having just zero balance um okay now we can do our check so if H let's do the same if amount is greater than the sender balance well so you you already know what we do right we return an error variant of our result saying it's going to be a CO eror insufficient balance and uh well requested will be amount and available will be obviously oh sorry sender balance yeah that's pretty cool we can I would actually probably write it in a slightly nice way uh you in general you don't need to format rust code uh by hand rust fmt will do that for you but just you know keep it very brief okay so if the sender does not have enough funds to actually make the transfer obviously we return an error and the clients can decide what to what to do with with this situation but uh if everything is okay then what we need to do we need to decrease the balance of the sender and increase the balance of the receiver and uh if you know about re-entrancy you know that it's better to First decrease the balance of the sender and later increase the balance of the receiver otherwise uh you could do something similar to the Dow hack that most of you probably will be familiar with now to do that we're going to do the same thing we've done previously with the minting um self balances and now we can insert and it's going to be a very similar code uh it's just going to be the sender as the target here and we're going to do the same thing as we've done before but we're going to take the sender balance and we're going to we're going to do checked checked sub which is well as you can probably guess the same as checked ad but for subtraction and we're going to from theer balance we're going to just subtract the amount and uh again we're going to use the the hack here with unwrap to basically save some time okay um that's pretty cool we decreased the sender balance um let's just save it my my ID is not complaining yet well we haven't used the receiver that's uh that's one of the warnings we got that's very true uh now we need to well let's let's just get the balance of the receiver and this actually we can copy over we can just do this and uh it should it should work just as just as well and now we're going to do the same thing okay I'm going to I'm going to copy from minting here because H it's best if we save time okay uh I think it looks right it looks right to me let's let's quickly check if this compiles because might fail at the linting stage who knows in general I find I find it the most convenient for me to compile the code as often as I as I can uh just because I like to catch the errors early and in general I would say that this is the philosophy of like strongly typed statically typed languages like uh rust and ink here uh that you know a little struggle during uh writing the code during compilation can s can save you a ton of headache uh when the code is already R deployed right so I actually like that the compiler is uh shouting at me and uh you know this allows me to basically fix my errors before they hit before they even hit test net or uh let alone main net um now since since we've got this more or less done the the like the business logic is done we have one more thing here uh we have the events in uh in solidity so in line eight we have the event and we can do the very similar thing in our in our rust code we're just going to do uh sorry P public a public struct as before and uh we're also going to do the same name but importantly as you've probably guessed we need to do an ink event macro uh just so that you know we tell the compiler that this is going to be sent out as an event if if you're not familiar with events it's basically your contract's way of uh communicating with the out outside world like uh telling the outside clients what's happening be that you know wallets indexers and so on um you can use it to kind of react to what's happening in your or someone else's contract uh now if we look at the fields we have the from address to address and the amount so from is going to be an account ID two is going to be an account ID and amount is going to be our number type okay uh one more thing you can do in ink since these events are later ingested by by different clients you can say that hey uh similarly to what you would do in a database hey this is you can say that this field is actually okay to index on and it will you know speed up the the the the kind of like U ingestion of the events or or querying them um importantly you cannot make a Like A Primitive type a topic which which also I think you'll find it uh kind of natural if you're if you have some databases background with indices okay so we have the event struct that's pretty cool now we just need to send it and we're going to again use our magical self EnV method oh by the way the the self en has uh a few very interesting uh like helper methods that you can use like the the account of the contract itself the balance uh you can get the current time stamp and so on uh it's very helpful here we're going to do the emit event macro oh sorry it's not a macro it's a method uh and we're basically going to use our sent event uh which is going to be our from is our sender our to is Our receiver and our amount well it's our amount so we can just write amount okay I think this works quite well let's try building it yeah must be my lucky day because uh so far not too many compilation errors um okay uh I think we're more or less ready for this contract to hit the chain because the the behavior is is the same uh actually you'll notice that what we actually do here is quite a bit safer because we for example are guarding ourselves against arithmetic overflow and I once again encourage you to check out the batch overflow hack to see how deadly uh overflow can be um what we can do right now is make it a little bit more user friendly since I'm seeing that I got 20 minutes so let's make it a bit more user friendly um okay the first thing I'd like to do is well imagine you have a lot of methods you may think well it's super cumbersome to write these uh result uh coin error if all your methods return this well why not use some something something shorter and that's exactly what we're going to do we have the coin error here we can declare something that that's a type alas in in Rust it's basically saying okay from here on out I'm going to call this type differently and let's call call it coin result okay like this right and now instead of writing this here I can quite conveniently use coin result and it's going to be the same thing but with less typing so profit um okay and probably one more thing and actually an interesting piece of rust syntax if if you haven't seen it before is is this pattern here right because you you'll probably have a lot of uh messages a lot of methods that check the owner and uh like could we could we somehow extract it to a to a different to to to like to a method of its own that that it kind of works almost like a like a macro so we can and uh you'll notice that we don't have to only put messages in our contracts we can just put any arbitrary method uh it's not going to be public because we don't want like anyone from the outside calling it it's just our contract that's going to be calling it uh it's going to have a reference to just to self because it's not going to mutate anything it's just going to uh check some stuff and uh actually it's not even going to have any additional arguments what it is going to return it it's going to return a coin result and uh what we're going to do is basically we're going to do this right if the the color similarly figure out who the color is if the color is not an owner we return the error otherwise we just return an okay and now you might think that we we are forced to do you know like if Ure owner or do some pattern matching no we can use a very handy syntax uh that's going to look like this if you're used to writing in JavaScript you may recognize this question mark although here it's a bit uh more type safe and a bit different so what it's going to do is it's going to check the result of this of this method and uh if it is the error variant it's going to return the error from the whole from the whole method and if it's okay it's just gonna it's just going to progress uh which is pretty cool um it doesn't involve any magic actually uh this could be just Rewritten as a very simple pattern match but this uh what it does is it reduces the number of lines of code we need to write and the you know like indentation we need to we need to have here so uh that's pretty cool let's let's see if it compiles and it does right that's that's great I wonder if there's some more stuff we can do well we could try try to abstract away more pieces of of our code but I think we're we're good for now uh so to from a from a like more you know technical uh things uh this is this is how our cargo Tom looks like which is basically a file where we describe our our project and list all of the dependencies you'll notice that we're using just a single dependency here that's the Inc um ink language because it's all nicely packaged as a dependency and uh the rest is just rust itself uh it's a fairly it's a fairly new new version uh and this is what introduces all these cool features that you that you cannot for example do a potentially unsafe addition or subtraction it it kind of guards you against that there's also many more um nice features you can you can read about them at the use. in website which basically by the way I encourage you to check out um okay so since we've let's just compile it once more for good measure okay um so we we have the artifact we are are now ready to deploy our contract and uh what I have here is uh basically the substrate contracts node running uh I don't want to use the ALF zero test net right now just because I don't want to put you know like random stuff on the test net uh I could but I prefer to keep it local uh you know just to make it clean for everyone and for myself um and obviously once you deploy a contract to to the testnet it stays there right so and the the wasm code is public so um you know uh that's worth uh worth keeping in mind so what we're going to do now is we're is we're going to go to the uh substrate contracts UI I'm going to make it a bit larger for everyone to see um you can see that we haven't got any contracts yet so we're going to add a new contract well we're going to upload new contract code uh this is like a developer local instance of the blockchain so I have access to the uh to the developer accounts that already have some funds and um yeah pretty much it's ready to use batteries included if you wanted to deploy on test net you would need um some sort of a like a signer extension like the ALF zero signer or or projs extension and you would need to create an account you would need to get some funds from the faucet um it's it's described in our documentation that I'm going to show you a bit later uh the contract name uh we're going to call it Denver coin because why not and uh I have the coin contract here I hope I've selected the right file okay um you can see that it uploaded the contract bundle so it's the the wasm code and the metadata in Json uh this is how it was able to figure out the uh the names of the methods the type and types and whatnot of course I I've done a very bad thing I haven't included any oh sorry any dog strings in the code uh which normally I would do like you know uh mint uh specified amount or something like that basically um it's important to write the dog strings here because it's going to end up you know as the visible API of well yeah description of the API that your users have at their disposal so it's quite important that you tell exactly what the methods are doing um okay to we're actually doing two steps at once now uh I still have some time so I can explain it uh a very interesting concept in in ink and in in substrate uh is that basically the deployment of a contract is a two-step process first you upload the the code to the chain and it just kind of starts living there and then you can inst spawn multiple instances of the contract from it uh just kind of like you know making pointers to the same code and it's pretty cool because if you I don't know if you're rating a game and have like seven uh PSP 22 contracts to deploy for it for the tokens you don't need to pay for uploading the code seven times you upload it once and then just instantiate it seven times which is which is pretty cool and uh yeah worth worth keeping in mind uh we don't have much Choice when when it comes to the Constructor just the new um yeah it's going to just confirm that we've uh that we've instantiated the code it's it's all here um now of course you could use the command the cgo contract to interact with the contract deploy it and so on uh you could also use PJs the the library uh I'm just going to stick to the to the graphical user interface because I think you've seen enough code already um yeah we can we can choose a method to to Mint okay let's let's mint uh using the the owner of the contract so Alice and the receiver will also be Alice yeah we just want to Mint for ourselves let's mint like thousand tokens I don't know and uh yeah um actually there's quite a lot happening here but probably no time left to explain it but every time you call a contract like that before you call it uh the this system is actually performing a dry run of your contract first uh which allows it to kind of see if it will be successful and estimate the fees that you'll have to to pay for instantiating this contract um fortunately on the ls zero blockchain the fees are negligible like u a fraction of a scent uh but still you know it's uh worth keeping in mind uh and and kind of estimating uh what they will be uh if you're seeing this scary looking cont constants here uh you can use the estimation that's what we got from the dry run but if you want to customize it then basically the ref time limit is intuitively how how long your your call will take to execute and the proof size limit is again in just it's just an intuition how how much space it will take on uh on the chain now since we we've got the mint we can now use the send functionality to send from Alice to Bob and uh let's try something weird let's try sending more than Alice actually has and you see that the contract was rided uh with the error we specified so yeah seems like we've written code that works and quite fast too let's just send a 100 okay yeah that's pretty cool uh seems like it was successful now you will notice that we haven't included a check balance function it's actually one of the things we could do to to make our contract a bit more user friendly let's make it let's make it more uh so we could actually do a do a message and let's call it balance off um ah maybe let's just call it who and it will return our type here and uh let's just do yeah it's going to be quite simple we're just going to get this and I'm wrap or yeah this should work and uh now we could check what's in our contract and we could actually rewrite this to have self balance of receiver and and rewrite it further further like this uh yeah it's a it's a pretty handy shortcut um but we can do one more cool thing and uh actually also a recent addition to to Cargo contract um so let's oh sorry sorry for jumping back and forth but uh of course our contract is deployed under a certain address and we can we can copy Cy this address to our clipboard and we can do you know like for for convenience set it in an Nar and then we can do then we can do use the cargo contract storage command passing the contract as an as an argument the contract address and the path to our this cargo tunnel file that contains the info about our contract and you'll notice that I'm not writing any like websocket address or the address of the of the node of the RPC node I am not because by default it's using the local instance that I'm that I'm using so it's pretty cool and now you can actually quite conveniently examine the storage of your contract um and this allows you to you know learn also a bit how uh the the layout of the memory looks like an ink but uh you'll see you know things that make sense basically uh at the root there's our contract struct that has a mapping and mapping of course has cells uh stored somewhere else in like this kind of sparse layout um and yeah you you you'll remember that we've you know like sent uh minted a thousand coins to Alice but then sent 100 to Bob so it uh contains you know appropriate entries um so everything seems to work and um that's that's pretty much it and the contract I think it's it's pretty safe um so I think it was worth you know like writing writing all this code to to have something that is that is well pretty bomb proof I at least in my opinion um now if you want to learn more about the contracts in nink and Alf zero in general then I definitely encourage you to visit our our homepage alz.org uh you can also do docs. alz.
org for for documentation alz.org Developers for for the developer portal and uh basically you you can take it from there and uh I hope that you know after this I'm going to see some new ink contracts uh deployed on our testnet and later on our main net uh we also have this oh actually for for Builders this is probably the most important information uh we also have this ecosystem funding program where we support uh basically projects who who are building on the ALF Euro blockchain through grants and like tech support uh we also have Partners who can help you with legal stuff with branding marketing business and so on so uh check this out it's all accessible from the alz.org page and um yeah hope to catch you all here at the conference thank you so much for [Applause] listening
Automatic transcript — names and jargon may be misspelled.