 labs. We were the initial builders of Arbitrum, but we also are continuously supporting Arbitrum as a DAO on the research and development side. And one of the most exciting new technologies we have to offer to the Arbitrum ecosystem is what we call Stylus, which is our new WebAssembly and I'll get into that and explain a little bit more about that. But yeah, just wanted to kind of give you a high level of what I want to cover during this talk. I'm going to kind of give you sort of a high level introduction to Rust. If you know any programming language existing, if you just know a little bit about it, you don't have to know all of Rust in order to be productive with Stylus. So I'm going to cover enough to get productive with it and then kind of explain like a basic example and then I think Jose, after me, will go more in depth on a more detailed example. Okay, so with that, let's move on just to kind of reiterate what Stylus is. Stylus is a new virtual machine execution environment for Arbitrum blockchains. And it works off of WebAssembly technology. That means any WebAssembly language is supported technically. Primarily, right now off the bat, we're kind of supporting traditional systems languages like C, C++ and Rust. But there's a lot of niche languages like AssemblyScript and Zig and many other WebAssembly languages that can be supported. There are certain nuances with that. But to start off with, we've kind of built out a very robust Rust SDK. So that's what I'll be covering on this talk today. But just note that Stylus is not limited to Rust. It's just our primary target to launch with. So some of the benefits of Stylus is that it allows up to 70 times more compute versus a standard smart contract. And it allows 1000 times more memory to be accessed for the same amount of gas during a transaction. At the same time, it remains composable with EVM. So you can call Solidity from Rust and you can call Rust from Solidity. You can call C from Rust and vice versa. So it's very composable and it works with the existing Ethereum ecosystem. So it should fit nicely once it rolls out to our main net. Some of the other high-level benefits of Stylus is that when you're using the language like Rust, you get access to general purpose language tooling because Rust is used in a much more broader context outside of smart contract development. So you get access to a lot more tooling, bigger libraries to pull from. So we're trying to tap into a lot of the brilliant open source work that's being done and all these other ecosystems and bring that into smart contract dev and kind of modernize smart contract dev a lot more compared with what you get with Solidity which is a special purpose smart contract language. Other benefits of it like with different programming languages, you get different coding paradigms, maybe you want to code a functional language, you code in a language like Haskell or something, you find a way to compile it to WebAssembly. You could work with it like that but just other patterns just kind of exist and Rust by default compared with Solidity that you're more than welcome to use in your code. It also helps us as an ecosystem onboard more developers from Web2 because then we have more experience with these more traditional languages like C, Rust, Go, Java, etc. You know these types of things that we can more easily support languages that are either quite similar to those or precisely the ones that they're already using and onboard devs through that. We also want to access the broader dev ecosystem. There's millions of devs that are outside smart contract development so it helps us to onboard those developers more easily. So just I kind of covered this in the document like if I think Jason and others at the conference were sharing this document about installation pre-rex on your laptop so this slide is just sort of like reiterating some of that. If you get lost at any point refer to our docs at docs.arbitron.io and if you click the quick start Rust under the stylus section it will help you get your environment set up and kind of reiterate maybe more detail than what's on that document we shared. If you get stuck at any point just go to docs.arbitron.io and everything that I'm about to tell you is located there as well. Also yeah when you want to when you want to develop a smart contract it helps to run a local development environment which we call local dev node that's also under the stylus docs and also included instructions on the cross-age instructions so again if hopefully you've got maybe your local dev node set up if you want to follow along but yeah the example that I'm going to show you later will be run on my local machine but you're also welcome to deploy to the public stylus testnet which is located at stylusdesnet.arbitron.io.rpc but for that you need support. I'm not going to get into that much we'll probably just work with the local dev node but if you have any questions on that feel free to definitely ask Jason he's there in the conference to help you so he can definitely help you get set up. Okay so moving on to like Rust I'm going to again kind of give you some high-level details about Rust enough to get productive with it enough to like write a basic contract with it so some of the primary advantages that Rust has maybe over other languages that it's very strongly typed language it's memory safe this comes in handy a lot of times when you're doing like systems level programming but it's more contract development helps a lot to the compiler tends to prevent a lot of mistakes that would kind of sometimes accidentally be made with a language like Solidity. It also has like a lot of high-level features while it's as fast as almost as fast as a language like C so you get access to a lot of modern programming language features from maybe something that you're used to from Java or Go or one of those but it's as fast as C so it's very good for both smart contract dev and just general systems level programming. The compiler is also it's it will give you very detailed warnings so it can a lot of times catch many many mistakes and things like that that you can learn from the compiler as you're learning Rust itself so it's very descriptive and errors and very helpful in that sense it's got other cool features like powerful pattern matching I might be able to cover a little bit of that later but just to give you a couple of the main benefits of of why Rust. Okay so I'm gonna kind of cover variables and mutability just like high level to explain to you that by default variables in Rust are immutable that means they can't be overwritten after being declared unless they were explicitly declared as mutable so if you see over here on the the top box here it shows that this doesn't compile where I'm just assigning the value five variable X and then afterwards if you try to overwrite that variable it's it's the compiler will throw an error as soon as you try to compile it but to fix that if you want to be on a mutated variable you should see in the second example below I'm just saying let mute X equal five and then assigning six to that variable which you know just again I'm just to claim that variable mutable and then that lets the Rust compiler know that okay this just immutable from this you know after this point and it helps with like things like ownership and determining whether a variable should be allowed to be overwritten or not if somebody else is expecting that it won't change you know this is not details that you have to worry about the much but it's important to note that to declare immutable variable you use that keyword okay so these are some of the like the primitive data types that are available in Rust you've got access to you know unsigned integers signed integers um yeah all the way up to 128 bits so here you got 8 16 32 bit all the way up to 128 bits and then you've got this uh the special type called u size or i size and those variables are just basically going to use size or i size it's just sort of a the keyword for whatever environment you're compiling in whatever it's default or max sizes a lot of times you're going to be compiling in a 64 bit environment that might be you know default to u 64 um wasm itself tends to use 32 bit values so it use size if you use the use size keyword it's probably going to be a u32 um in a wasm environment but you don't need to really use these use sizes better to just explicitly declare what size of the variables that you want so these are the primitives that are kind of available available to you and then below here on the integer literals section kind of see like these different ways of declaring different types of numbers like decimals hex values um binary and notice how the underscores are kind of ignored so like that decimal value that says 98 underscore 222 that's just 98222 the underscores just ignored it's just there for like um to kind of visually break up large numbers that these are really um but yeah just a couple of uh little syntax details about rust other type data types that are available to you or of course booleans uh so uh here where I'm saying let f colon boolecals and uh that's just saying this is a boolean type uh and then um um let me make sure that my audio is working I want to make sure that I'm okay thank you okay I just got an air message so okay um so you can you can use uh you can declare boolean types uh you just use that colon syntax to indicate the type character types tuple types so tuples if you need to do um more than one type at a time and kind of group it up into a single variable you can use tuples so I'm just using that tupe and I'm using that parentheses syntax u32 comma boole and then I'm assigning it that that integer that follows the 500 and the true and that that those values are both available in that too but you can have you know in number of tuples um you can have 10 20 elements in a tuple you're not limited to just like two elements for example and then that's a standard array should look very similar to arrays and tags from many other languages following with this this is how you define functions in Rust um you just got the f in keyword followed by the name of the function um and you see two functions here um notice the another function the second function on this list is using snake uh case that's a default and rust is to declare functions with that snake casing which is just using the underscore separator instead of like traditional language a lot of languages you will use like camel casing where the the second word is the first letter is capitalized um rust tends to use at least for functions it'll use the snake casing style um continuing on with functions if you want to return a value uh you use this arrow syntax if you want to return a value from a function so if you see that this plus one function on the right i'm passing in an i32 as x and then i'm adding one to it and i'm returning an i32 so it's just use that arrow syntax to return it very simple um you can also return more complex types like tuples or structs um and then you just yeah you just name variables uh just like parameter with the x colon that's that's the name of that variable also uh one note is that notice on the plus one function when i'm returning x plus one i'm not using a semicolon there and basically by default and rust uh if uh if you don't use the semicolon here that is the return value for that function if that's the last statement in the function so x plus one is is implicitly returns there where it's just it just knows since that's the very end of the the function statement that it's going to return that x plus one as the return value for i32 you don't have to like type out return unless you want to unless you want to return early like inside an if statement or something like that you can you can explicitly type out the return but otherwise it's just implicit returns okay uh to define different types of data so if you want to structure uh groups certain types of data together and kind of provide like name fields like this rectangle here we've got the width and height and the types are defined so you kind of just it's sort of a schema for data and you just declare struct this is a rectangle with the width u32 height is a u32 so 32 bit integers for the height width and the struct and it's very similar to like objects and existing like object oriented languages um that you're probably used to but there are subtle differences to know with structs um it's just you know i won't get into that in this talk it should but like you can kind of think of structs as objects but they are they're somewhat different and i think you'll learn that as you go but again i kind of just want to teach you the minimum to kind of understand these examples that we're about to explain to you so for now you can kind of think of them as objects um moving on here if you want to declare like if you want to declare instance of a rectangle for example in this main function um i'm just saying that rect one equals rectangle and i'm using the brace curly brace syntax and then i'm so i'm instantiating a rectangular with width 30 and height 50 um so very simple syntax to use to declare um to declare a an instance of a struct that might be different than then um like in an object drawing language a lot of times you'll you'll use this new keyword rust by default does not have any like new keyword defined for instantiating like structs um so you know you just kind of use this named syntax with the fields um and if you uh you know you can optionally declare methods on it if you want but um this is the default uh syntax for instantiation if you wanted to find a method on a struct which is again maybe analogous to defining a method on an object and i know people in which use this input keyword i am pl so notice how i've defined the rectangle up at the top with the width and height and then below that i've got an input rectangle so again i'm just repeating the name of the struct here so input rectangle i'm just repeating the name of the rectangle struct above that's going to let the compiler know that any instance of a rectangle has access to the methods defined inside this ample body and so here i've been i've defined an area method it has this like syntax called and self which is a that is a read only reference to itself again might be similar to op languages where you might be using this or self in op languages um so it's very similar the the key thing to note here is because it's in and it's kind of this amber sandwich is a reference to self that means it's an immutable reference i mean this method um is going to be a read only method so the f in areas is a is an area method it's going to return a u32 and it's just computing the area which is the width times the height okay moving on from there rust also has access to uh enumes you can find enumes here's an example where i'm defining a coin enum and i've got penny nickel dime quarter um these these enums don't necessarily have values attached to them so in this case there is no value really attached like a lot of languages will assign like maybe you know zero one two three four by default to these um enums and rust that that doesn't happen unless it's it's explicitly attached so in this case these these values sort of just kind of only exist at compile time these uh these enums here just something to note so how how you might use this this is an example of how you might use an enum um basically i've got a function here where i'm passing in a coin uh using an enum as a type so i'm referring to that coin type when i define the coin parameter that's being passed in the value and sense and then i'm using this cool uh feature in rust which is a match statement and i'm matching on that parameter and then i'm using this coin colon colon syntax to define all the arms of what um of what a coin might be so a coin has to be either a penny nickel dime or quarter based on based on this definition above so rust compiler also makes sure that you define every possible um when you use a match statement like this you have to define like a branch for every possible enumeration or every possible pattern that it could match um there is a syntax that you can use to kind of use a catchall if you don't want to define it for everyone for every single option but um but the compiler will will let you know um you know if you're missing something so it's something to keep in mind um and then yeah this is just a match statement it's returning an 8-bit integer based on whether it's a penny nickel dime or quarter so very simple function but um pattern matching in rust is a very powerful feature you don't have to understand all that or what that means but as you get to know rust you'll you'll see what i mean um these are some examples of maybe some more um uh like complex like kind of uh control flow this is like two alternate ways to do the same code um so right here on the top i'm defining this config max variable and i'm assigning it this sum which is a type that i'm passing in this uh an 8-bit integer that 3 u8 means it's an 8-bit unsigned integer and it's the number three so i'm passing in the the config max value um now has the value like in the first line has the value sum three and then the match statement below that where you're looking at match config config max um that first branch is saying well if it is some some value and print the line to maximum is configured to be that max okay these again these two boxes are equivalent this is just two different syntaxes for writing the same thing you can either like first assign it to a variable and then match on that variable or rust also has this like sort of like shorthand syntax is doing the same thing where you do this if let statement as if let uh if the max if the basically like if config max it it'll only it'll this if let will only run if it matches that initial branch which is some max okay and then it will print the line um next to it um yep and then okay moving on uh so rust also has this system called traits which are very similar to interfaces that you might find in op languages um so this is just kind of defining behavior or expected behavior that should be defined for a given um struct if you want to implement that trait for a given struct you can also implement traits for anews um that's just something to keep in mind so this is just defining a super basic trait or i'm saying that if a struct has the summary trait then it must have a function a method defined on it called summarize that returns a string so that's just um very very similar to interfaces um but can also kind of have some properties like abstract classes and stuff but again not something to worry about when you're just starting off think of them more like interfaces for now um this is an example of interfaces in in practice so we've got this tweet struct that's defined above we've got a username content reply field retweet field okay so you know these just a couple strings a couple bullions just to define a quick struct to kind of give you a basic example and then if i want to implement summary again this this trait this summary trait means that i have to for a struct to implement this trait i have to find a summarize method so that's what we're doing over here on this slide we're imploring we're implementing you can kind of think of that impulse meaning implementing we're implementing summary the summary trait for the tweet struct and then below that we're defining this summarize method that actually has the concrete implementation where it's it's formatting it's just it's i guess it's just it's just returning a string where it just concatenates username with a colon username and content with a colon in between it so pretty basic um trait there and implementation there but you kind of get the idea where we define this behavior and then we've made the concrete implementation for the tweet struct here okay another important thing to know about rust that you'll come across a lot is this concept of macros um macros are used in lots of features uh you've already seen a couple of them here where this print line for example you've seen in a couple of these examples or that exclamation point when you see that exclamation point at the end like here on this print line statement we see that that means you're invoking a macro and then the arguments that follow it are being passed to that macro but there's a couple different types of macros you see the second one the hashtag derived debug again you know because i'm just trying to explain the beginner rust details you don't really need to fully understand what's happening here except that when you invoke a macro ultimately like when you hit compile it's going to generate code under the hood that does this more complex behavior that you don't even need to really understand at first you kind of just you know high level know okay print line is taking these strings and it's figuring out and it's writing some code underneath the hood to to kind of put out to the console you know and to fill in like wherever you've got these curly braces um to fill in the the name string there for example as the first you know so it's it's just doing complex behavior under the hood that happens at compile time it expands your your code using a macro context if you've ever used any other programming language with the macro feature you'll who get it right away but if you haven't that's okay just understand that under the hood it's doing complex advanced behavior to expand your code to make it more complex to achieve something in a in a in a more you know terse way or like to find something in a in a very short way without having to write a bunch of boilerplate code you know so um it's just something to keep in mind they are fully programmable you can make your own macros they're very very powerful they're also very advanced feature of Rust and very complicated to build um so you don't need to know how to build them up to that just kind of know that when you're invoking with this exclamation point or using this hashtags syntax you your code is using macros under the hood and the Silas SDK uses these macros to like simplify development to to kind of prevent you from needing to write a lot of boilerplate code it's just something to keep in mind okay now i'm going to start kind of covering more of the SDK itself and kind of go into these details about how you might begin to write a smart contract and and Rust and just kind of give you what our high level goals with the SDK were and and continue to be we're going to be continuing to improve on the SDK but um you know we we do operate in an Ethereum EVM dominated context so even though Silas is much more powerful than the EVM the EVM has probably seven or eight years of legacy in the Ethereum ecosystem so there's lots of existing smart contracts that are written in Solidity and you know we want to remain fully compatible with all that so part of how we designed the SDK was to make sure that we were fully compatible and that contracts could be as important back and forth between Rust and Solidity and that you could you know devs could easily kind of understand it if they're coming from that Solidity background if you're coming from like a Web 2 background you may not sometimes understand why the Rust SDK maybe is referring to Solidity but it's important to note that because of the Solidity legacy in the Ethereum ecosystem we have to remain compatible so sometimes you'll see things like you might see some syntaxes slightly different inside of a Silas contract and usually it's using a Solidity macro to make something simpler to define and Rust that might be ported over have been ported over from an old Solidity contract or something like that so to help with that we're using a library called Alloy which is a which is a create a Rust library that makes it easier to do these like type conversions between Rust primitives and Solidity primitives because there's a there's a difference in the standard primitives that come with Solidity and the standard primitives that come with Rust so it's it's just a library that helps us do that so some you know you'll see some of those conversions and decode examples coming up but just something to keep in mind that yeah like Solidity as an example just as one of the basic examples is Solidity works off of 256 bit integers almost by default whereas like Rust currently doesn't have native support for 250 integers you have to use a library to get that kind of support right now it currently only supports up to 128 bits so things like that like converting between you know these 256 values 256 bit values and you know local Rust primitives the Alloy library helps with that just something to keep in mind yeah again it's all about composability and maintaining cross contract functionality okay so when you um if you set up your environment if you followed the the FlossAsia instructions that we've headed out to you and if you've got cargo stylus installed on your system you can run this command which is cargo stylus new and then you can name your contract to be whatever you want you can call it my first contract or whatever you want to call it hello world whatever you want to call it and what it's going to do cargo stylus will create a folder with a couple of files in it and it will have it'll just set up everything you need to get like a basic contract going and I'll show you that live in a second but if you you know if you want to test this out in your terminal you're welcome to do that but I'll show you live in just a few minutes um once you've got your your like basic contract uh set up you can kind of see you can cd into that folder you can run this command called cargo stylus check and that cli command will what it's doing is it's going to make sure your code compiles and it's going to make sure that your program is less than the maximum size that stylus supports so currently we support a maximum program size up to 24 kilobytes but um you know if the the cargo stylus cli tool will let you know it'll try to compress your code and and it'll try to shrink it down as much as possible in order to fit it on chain currently those are those aren't parameters that we necessarily set ourselves we're following the ethereum evm standards with that size limit so your contract does need to be less than 24 kilobyte if you need more than that after compressing you can you can write multiple contracts and kind of split your logic across multiple contracts it's usually how that's handled in um in smart contract development but it's something to keep in mind 24 kilobytes is not a lot it's you you want to be mindful of the size of your programs and the dependencies that you bring into your code um such as something keep in mind on chain resources are quite a bit limited compared with like operating in a desktop environment or like web environment so something keep in mind when you want to deploy your code you'll call cargo stylus deploy um right here i'm i'm on this example you'll see i'm invoking dash dash eflag which is the endpoint flag and i'm using localhost 8 5 4 7 which is a local dev node if you followed the instructions and you've got a local dev node you can deploy contracts against that using this uh argument where you do dashy and the localhost 8 5 4 7 is the default port that uh the stylus dev node uh deploys to um and then this dash dash private key path um you can you just you basically will use what's called a private key to um you'll place that into a text file and i'll show you an example of that because when you deploy local dev node it will it will create a like a development account the standard development account for everybody and it has um east loaded on it you need east and um in arbitrum chains you need east and then kind of if they're in change in order to uh deploy contracts and in order to um invoke any state changes in your contract you always usually need e and so in order to spend the you need uh a private key of an address that contains east in order to spend east out of that account so just kind of something to you know understand just kind of follow along these instructions if this doesn't make sense to you um i think it will over time but like for now you can just like know that you need to pass in either a private key path or private key in order to execute on chain um changes okay more high-level details about the rust SDK um these are some primitive value types again this is this is using that alloy library that i was talking about before that allows for solidity compatibility um expands primitives 256 bits like i said before rust by default only goes up to 128 bits so um that's part of the benefit of the because of the library the other thing is that um data is encoded in a different way so literally versus rust on you know as um i don't know how far along you are in your education if you know what they're getting in big again is versus little in the end there's differences in rust defaults and solidity defaults there so it this library helps like encode things properly so you see here where i'm just uh i'm saying the first line two there i'm i'm just saying let eight bit it's a u8 i'm using this capital u8 here which means i'm pulling that u8 primitive from the alloy library if you looked at my dependencies above this this is just like the inline example but i'd be pulling that capital u8 dependency from the alloy library and then over here on the on the right side of the equal sign where i'm saying u8 quote unquote from one that is saying created alloy eight bit alloy primitive from the number one so it's going to just create an instance of an alloy primitive u8 eight bit integer that has the value one and below that like i'm defining it a 256 bit integer but instead of using the standard decimal syntax i'm using a hex style syntax but that 0x ff and i'm using a 64 bit integer to pass it in but i'm it's instantiating it as a 256 bit integer from the alloy library okay so yeah you can just kind of use that u8 or u256 from syntax kind of as a standard when you're doing a stylus development um it usually just helps to work in alloy primitives a lot of times a lot of times it's easier and then trying to convert back and forth from from rust primitives so a lot of time waterfall it just helps to just use those waterfall another type of value you need to you'll need in your rust in your in your smart contracts is the address type that that's that's an address in ethereum is an account it can also be a smart contract location so addresses can contain e and they can own tokens and they can they can invoke other um other smart contracts and things like that so um just important to know an address could be a user account or it could be a smart contract and then we're pulling that address type from the alloy library um and then i guess this uh this example here i'm i'm creating an address from the 0x11 this is shorthand for what you see in the commented section for like it's basically 20 bytes uh it's 20 bytes of all ones so that's just using some a little bit slicker rust syntax there you don't have to know that necessarily but it's it's it's one way to find an address using this address from 20 bytes slice syntax there all right um um don't moving on to the types of variables so these are the types of variables that that you can use within the context of a smart contract okay so you've got local variables which are those are variables that are defined within a function body those are in-memory variables so purely exist in memory once the program is uh once the contract is has shut down um you know they don't they're not stored anywhere so that's just in-memory local variables so right there in that in that gray box you see let my var equals that's that's uh defining a 32 bit integer with the value 123 the second um statement there is um state variables which is you know those are values that are permanently stored on chain and um those are stored in a database and you can think of them as being stored in a database on chain um i'll show an example of that in the next slide but um you know think of them as database variables it might help you if you're just getting started with this kind of thing the other kind of variables the global variables those are those are variables that are provided by the VM itself okay and those might be things like you might see a reference to message sender or things like that that um that the VM is kind of injecting into the context of the um of the smart contract but there's there's many of those you can kind of look up on the docs to to refer to them um but yeah moving on to an example of like how you define state variables so this is a contract struct and i've got if you notice how the right i've got uh i'm invoking a solidity storage um macro and below that i'm invoking an entry point macro and then i'm declaring a struct called contract and it's got three fields on it initialized owner and max supply okay to the right of each of those fields you've got the types that those fields line up with and these are storage types so instead of using the primitive types that explain before i'm explicitly using these storage types and that's necessary just to maintain um this this compatibility with um with uh solidity for example store things in a solidity a bi compatible way we have to use these these special storage storage types that are part of the SDK so you only use these types for database variables essentially so you're only using these for these like these state variables they're going to be permanently stored on chain so you've got a bullying in address there's there's um there's for every primitive there is a storage type that lines up with that so just something to keep in mind you you really just have to use that in the declaration and you can think of this as like a database schema more or less when you when you use this the style of a struct with the solidity storage macro and then those storage types um on the fields okay um moving on um the uh the Rust SDK so to define an external method okay this is kind of like when you're writing us more contract you'll have certain methods that are exposed to the world that means users or smart contract can invoke these contract these uh methods and in order to define these methods and you can kind of think of them as your public API for your smart contract use this external macro and then on that input below notice uh it's got that input syntax with the counter which would be the name of the struct so an impelling for counter an external method called number and that's that pub function public function number and it's returning you to 256 from storage it's calling self dot number dot get to return the the number field from the um the uh from the storage um struct that was defined like you could think and this isn't the same struct but if it had the number um value on it that's what this would be returning and I'll show you that in detail in a second because this is from the the basic counter example that I'll show you but it's important to note that in order for a method to be externally invocable by a user or smart contract you have to use this external macro and methods can either be read only or they can mutate state and there's just slightly different ways to define a mutable function versus a read only function all right so with that I'm gonna move over to um uh to I'm gonna open um VS code real quick to kind of go over the code real quick um and uh make sure VS code okay can you you guys see that looks like it's starting to work okay cool all right so to um to kind of cover real briefly what you would do to get to this point I'm gonna back out of this and I'm going to uh like let's say I'm in a in a folder and you want to create again to to get to this point you want to do cardo stylus new and then this one I happen to make test 123 but I'm just gonna say whatever hello world hello fos aja let's do that and so I'm just using the cardo stylus cli and I'm using that new command and it's gonna create a um it's gonna create a full uh project and if I cd into uh that hello fos aja there and then maybe I go to them real quick and let's try to zoom in a little bit in case y'all can't see it too well um you know it's it's just created like a folder with a toml file that is this toml file is kind of like you know package.json and a job script you know it's just kind of it declares you know what libraries you need to use your code um and might have things like your keywords of your repo what version you're on all this stuff so that's something you don't have to worry about it gets all set up for you but if you go to source that's where really the main thing to look at is you might think that your code is a main dot rs but it's not that that that file is mainly only used and um these exports of a json api you don't need to worry about that live dot rs what you want to focus on um as you're learning so if you're if you're modifying the the basic example you kind of just like jump into live dot rs kind of scroll down it and um actually I'll pull back out of this but just note that that's that's where it's at so um I'm gonna pull back out of them and go back to VS code real quick so I can kind of walk through so um right now I've got like live dot rs open on the basic counter example that gets created for you um up here at the top these are just purely dependencies so um just kind of call out this alex dependency here a lot just kind of for now copy paste that from the existing examples if you're starting fresh this is just a memory allocator and you could kind of find your own or use your own but by default we use this mini alex which is very compact and uses very minimal space for like memory allocation but these are kind of the more important ones to really kind of know these this is the stylus SDK dependencies so I'm pulling in from the alloy primitives um I'm pulling in this u256 which is 256 bit integer from the alloy primitives library and then I'm also pulling in this storage u256 which is what I just mentioned to you in order to store a value permanently on chain in the on chain database you need to use these storage types all right below this this is repeating what I would have said on that slide before you got the solidity storage macro in this entry point macro and I'm defining that I'm I'm annotating this counter struct with those this entry point lets um lets the stylus SDK know that this is the root of my database schema there should only ever be one entry point struct defined um so this is the root of your database schema important to know and then the solidity storage says that okay in this every field in this struct should implement the storage type for the to make everything compatible with stylus SDK and basically just lets the compiler know that if you try to use a field that is not a storage type it'll bark at you the compiler will let you know so here we are using this u256 storage type that means we've got this number field that we're going to store a value of which is the basic counter value so this is a simple counter contract its only function is sort of to like set a number increment a number and then fetch a number um so it's very very simple contract to kind of understand so we've got a single field storing a single number on that field and then we're creating the external so below this now we're defining the external api for this contract so we're using this external macro syntax with the hashtag with the braces and the keyword external which is coming from the stylus SDK and then we're defining on the counter the sample for the counter this is the same name as as the struct above so this is what kind of you know glues it together um if it we're implying the counter we're implying external methods for the counter so over here every function it needs to be public so that's exposed to the outside world we're defining the name here we're we're just calling this is called the number function it is getting a reference to self which is a reference uh a read only reference to the storage values itself from the counter struct and then this method returns a u256 so it's just going to return a 256 bit integer all right and we're so we're calling self dot number dot get so um in our stylus SDK you kind of have to invoke this like get method in order to like fetch the value from storage and return it um and then like similarly for stat you call dot set and you pass it in so it's just basically kind of getter setter syntax um it's important to note that like when you're working on chain storage variables or state variables or database variables they are the most expensive type of uh value to work with so we kind of make it pretty explicit where when you have to invoke these getters and setters in order to retrieve or set values so that you're not accidentally spending um too much uh eth or gas in order to um set these values so just something to keep in mind um uh this this method below here is note this is so up here we this is a read only function and we passed in this reference to self so this is a mutable reference to self and this is a mutable reference to self so that means we're allowed we use this ammute syntax we're now allowed to mutate variables in storage so that just kind of lets the compiler know and it lets um when we when we uh publish this to users know that this is a function that mutates state and this is a read only function so that ammute self is the you know self it can be when you're doing a when you're defining a method can um the first argument is is um always the self argument that is a reference to the struct itself that this method is being defined on okay so this is a mutable reference to the self to the to the counterstrike and then we're passing in a new number so if we want to this this method here just sets the number to some arbitrary number so we're just passing in a new number and we're setting the database value of self that number to that new number the method below that simply increments it by one so it's it's again it's a mutable method because it's getting a mutable self reference but there's no arguments needed because it's just increments by one so right here it defines a local variable called number um it's just assigning the local number variable to the value from storage so it's getting the database the current database value and it's assigning that to the local variable number and then it's going to set the database number it's going to call it's actually just going to invoke this method so it's going to call self that set number and it's going to say number plus one and again look how it's using this u256 from one uh syntax that's just um that's because this number is going to be by default because we're pulling it from storage it's going to be that alloy type of primitive it's not going to be just a rust primitive if we try to say number plus just the number one without first saying um like if we try to do this without first um saying that it was a um that it's a it's a without first converting this to an alloy type it you know in fact it's the the compiler's already warning us is saying cannot add basic rust integers so first we have to like convert it to that alloy type and then we can add them together just fine okay so just to kind of see this in action real quick um i'm going to use a um when you do utility that's called um cast and cast is a seal like tool that um you can get it from getfoundry.sh um and unfortunately i didn't include it on the instructions for fascia but um if you go to the website getfoundry g-e-t-s-o-u-n-d-r-y dot s-h you can download this program it's a c-l-i tool that kind of helps when you're invoking smart contracts okay jason you got a question go ahead now hey please go ahead hey yes you there can you say my my street uh yeah i can uh yeah i'll wrap it up i'm just gonna show the counter example real quick and then i'll wrap it up and how they can take it from there um okay let me just show like kind of the the mistake real quick and um yeah then i'm sure you'll gotta break a quick break before jose starts but i'm gonna kind of just kind of briefly show this in action just to kind of show you how this works um the counter contract has already been deployed and i'm just going to copy pay some commands here um actually let me uh let me uh real quick let me see what the current value of the number is so right here i'm just using this c-l-i tool called cast passing in to my local dev node private key this is the address that the contract was deployed on and i'm calling this number function i'm expecting a 256 bit integer to be returned if i hit call it's saying that the current value of the counter is 28 now if i want to increment it if i copy paste this it's going to increment it's it it shows this like transaction hash and all these details that means it it executed on chain and if i now call again the number function again um it should return 29 so increment it by one um this the strategy tools a slick kind of tool for like working with smart contracts from the cli it's something i highly recommend whether you can solidity dev or rust dev um let me stop this real quick and let me go back over real quick to this um just to finish wrap it up um to uh again to if you want that access to that tool that foundry tool you can go to get foundry.sh that's this website down here um to reiterate and jose is going to go over this in more detail but if you need any other help on any of this you can you need to go to our docs website docs.arbitrum.io we also have a telegram group at t.me slash arbitrum underscore stylus um and then we have some example code that's available in our if you go to github.com slash octane labs and kind of type in stylus and you can see um you get an awesome stylus you can see some examples there um there's also like a stylus by example uh website with some uh some easy examples um but these are resources for you and you can always ping us either in this telegram group on the discord or whatever to have any question and if you need me i'm on christ go to 502 on telegram or on twitter um but yes let me switch back over and stop presenting and then um i'll let i guess i guess there'll probably be a break and i guess let jason uh guide y'all from here but um thank you for your time and if you i don't know if you have any questions or anything like that feel free to ask them i'll be here in the atrium while um while jose gets set up um i'm going to continue to to present on arbitrum stylus uh i'm going to build upon what threes already mentioned before so in this workshop we are going to see we're going to see an example of a smack contract written in rast or an nft okay well first of all um my name is jose franco i'm also an integration engineer of chain labs here are my twitter and telegram handles in case you want to you want to contact me i don't write a lot on twitter but you can contact me very if you want okay um so i'm going to i'm going to try to be brief on this workshop but still i need to attach on on several things so in this case we're going to talk about nfts first i'm assuming that some of you might know what an nft is some of you might not so we are going to briefly explain what it is we're going to explain sorry what is the erc 721 standard that that defines how to build nfts and then we are going to talk about how to translate that interface that standard into a rast program okay so let's start with the basics what is an nft so an nft is uh it stands for non tangible token so they are different than the tangible tokens those are the erc 20 tokens in that for erc 20 um each token is not different from the others it's the same one like for example if you want if you have one usdc which is a which is a fungible token it's the same as having another usdc for non fungible tokens that's different and each token is different from each other okay so as examples we have for example if this is used for art and collectibles in this slide we have some images of the asuki collection so this collection is an nft and each one of the images is a different token so as you see having the first token is different than the second one and it has it can have different properties different values um yeah they are completely different from each other okay so nfts are also used for gaming assets so for example if you have um if you want to have um a smart contract that uh has all the weapons that are used in a game for example each token might represent a different weapon uh with different attributes different properties etc and it's also used for financial instruments that's another example so if you invest in in a pool you you invest a pair of tokens in a pool you can receive um you can receive an nft that identifies that investment and actually that allows you to be like more liquid because you can actually sell your operation to i don't know to a third party to another person so nfts as i said before follow the erc 721 standard and that's what we are going to see to build our smart contract okay um but yeah well i'm going to touch briefly into these properties of a of an nft so no two tokens are the same so there is some uniqueness going on in that in nfts also tokens can be divided into smaller parts that means that you can't have like 0.1 nft you have to have at least one and portability we mentioned before you can transfer that easily to other parties and authenticity means that um there is always um there's always track of who is the current owner and who has been an owner of a specific token or a specific nft in the blockchain okay that's actually a property of the blockchain in the nft but in this context it is very important so the erc 721 standard this is like the guide to write our smart contract and this is what we are going to use right so this standard um defines an interface for apis of nft smart contracts what does it mean this means that um it tells us what functions that our nft have to have to be able to to be properly like used in the in the blockchain right so it actually attempts to build a standardized way of operating with nfts without having to know the implementation details so you don't as a user you don't really need to know um what is inside uh a function you'll be able to use it you should you should know from a security point of view but as a user it just means you see you don't know like how it is implemented you don't know actually one language it is it is implemented it you just need to know the signature of the function to be able to call it and that's what the standard gives us the same as that's made a mention implementing the implementation details sorry it just gives us a function signature okay we're going to see that now this is an example well not an example this is part of the actual year 6721 standard here we have several functions signatures and this is what the standard tells us so if we want our token to be transferred in a standard way we have to implement the function called transfer from that takes these arguments and well in this case doesn't return anything that's for example a balance sort function takes one argument the owner and returns a u in 256 and so the standard does this with all the functions that the NFT should have as a minimum you can have more functions if you want but as a minimum to be standard you should have these functions with these signatures okay and the standard also gives us signatures for the events that these smart contracts this NFT has to meet okay we're going to talk about events soon and you'll understand why they are important well you have the full specification here if you want and don't worry about copying any of the links because I'm going to share these well I'm going to share later a QR code with that goes to a repository of code that we're going to see today and that has all the resources that we're going to talk about today including this presentation I'm also going to share these in the host Asia specific telegram group I think there is a banner in the workshop room where the QR code that you can scan as much as you want so yeah I'll share that later in the group my colleague already explained this but these are just some resources to start with with styles there's a quick start in the public documentation of Arbitrum that goes to how to set up your environment we've already explained all these so I'm not going to get into details about these there's also this style example portal that gives a lot of examples of how to use graphs to write your smart contract and do several specific things for for styles like for example how do you meet a lot in your smart contract and many other things and the awesome stylus repository that has a lot of examples a lot of resources to to keep exploring the stylus and more examples yeah this is also well something that Chris already explained how to create a stylus project so I'm not going to get into that just the kind of stylus tool it is also explained in the public documentation so in this case we need the free this workshop it is explained all right so let's explain a bit what do we need to keep in mind when creating our stylus smart contract so I'd like to think about all different elements that I need to yeah I need to keep in mind I need to think about when actually the elements that we have to touch on the different functions that we want to add for our environment all right so the first one is the storage layout that means what information we need to store in the smart contract and what type of information that is okay then we need the implementation of the methods obviously what method we need to have and how they are implemented we need to know also the events that we are going to emit and we have to define them in our smart contract and emit them in the methods that we are going to emit them and we need to keep also in mind error handling okay we're going to see all of these with the exam tests that we're going to see today except error handling I'm not going to cover that but there is plenty in the example repository that I'm going to share there are 10 examples as well in the documentation so yeah that's on the next one so a storage layout first thing I'm following up on what Chris explained already with the first thing that I like to think about is what variables do we do I need to store to be able to give the smart contract functionality that I want to get it and and also what variables do we need and where do we store them right where do we put them in the code right so we have these macros solidity storage and soil storage that allows that allows us to do that right so we just use that macro we can use solidity storage if we want to write this struct in using brass syntax or we can use soil storage if we want to use solidity syntax so in this case for simplicity we are going to use solidity and inside the struct that we are going to create we are just going to add whatever storage and storage variable that we need right so in this case it's a mapping of token IDs to owners if you don't know what a mapping is think of it as a similar to an array there are arrays as well in solidity but you can think about you can picture it like an array where you view into 56 is the key of the array and address is the value so we are saying for each token ID which who is the owner who is what is the address of the owner okay and we are storing that in the owner's variable so next is the implementation of methods as Chris already explained we use the this input this input input keyword followed by the by the name of the struct that we declared on the on the storage part and then we just implement define the methods that we want and implement their code there okay events and so sorry events are for those who don't know what an event is isn't they are signals that the smart contract emits when certain actions are performed okay so for example if you are transferring a token an NFT a specific NFT from one user to another user and the smart contract emits an event saying that okay this this NFT has been transferred from this address to that address okay so those are used for example by frontends user interfaces that want to notify users when something happens in the blockchain or I don't know if a user wants to track um what happens in a specific smart contract he can just keep track of of the events that are emitted there okay so the standard the ERC721 standard gives us some events that need to be emitted and yeah we're going to use them here this is an example of an event um the interface the interface uh the standard sorry gives us this event signature and this is how we add it to our drafts code we just use the same like the same signature inside the sol exclamation mark uh macro okay okay so we are now going to to see the specific methods that we need to implement and this QR code points to this repository where the actual code of the of the project that um of the NFT actually exists and I'm going to be I'm going to try to be very explicit about the examples I'm going to show like the code of that that that we need to implement the methods and and find storage variables that we need but if you want to follow along with the code you can scan this QR code and just um following the in that code okay so in that project there's an src folder inside you have two files there's a lib.rs file and an erc721 file most of the functions that we're going to see are in the erc721 file because that's the actual implementation of the standard and the lib file is just importing the interface to create the the tnft all right you don't need to have it but don't follow along just scan it all right so what do we actually need to build our NFT we need two properties a name for our NFT and a symbol and we need several methods we need a transfer method and a proof uh minting NFT burning NFT and a token uri okay so for the properties yeah we just need the name and the symbol a name can be a full name of the token for example stylus nft and the symbol will just an abbreviation of of that token snft for example and um we are going to use these variables to store that information in the contract right so inside the public struct we are going to just use a string name and a string called symbol and that's it we are going to store the the variables okay and the methods in this case we are assuming that the name and the symbol are hard coded in the contract so we just we are just going to to create two getters for those variables okay so we just create one name function that just returns the the name um uh that we store in the variable and the symbol function that just returns the symbol that that we uh that we store in the storage variable okay if we want to change that information why the cons after the contract is deployed we'll need setters for that we're going to see examples of setters later but for now just the getters all right i'm now one of the main part of the nft one of the most important part uh how to transfer the token okay so the transfer function allows us to transfer functions because there are several allows us to transfer a token from one account to one other so when implementing this functionality i i always like to think okay what do i need to keep track of to give this functionality to the contract and there are two things that i need to keep track of what's the balance of each user so how many tokens does a certain user has and who owns what token and any given time okay so um yeah and also the erc 721 standard gives us these signatures for the functions uh one transfer form from function that just takes three inputs from a tool and a token id so this function what it does it just takes this token id a transfers transfers it from the prom address to the two address and two safe transfer from that actually do the same but if the two address is a smart contract it will execute a special function in that smart contract okay we are not going to get into details about about this just so you know that there are three transfer functions the standard also gives us one event that needs to be emitted when transferring a token and that's the event transferred that well emits logs the the three information that we need the three pieces of information that we need the prom address the two address and the token id okay now let's go into rest now let's go into our contract so how do we store the information that we need to keep track of we use two mappings for that one mapping that we saw before actually the owner's mapping that maps for each token id who is the owner and then a balance map so for each address how many tokens do they have with these two mappings we can keep track of everything that we need to keep track of and for the methods we are going to see the transfer from method which is the first method that the standard tells us to implement so for the transfer from we well the standard tells us we need that from a true and a token id and in this case we have divided the execution into two internal functions the first one is require authorized to spend and this is basically going to check if the user who is calling the dysfunction is able this authorized to transfer that token so for example if i have one token well another person shouldn't be able to transfer that token on my behalf right so we are going to take a look at this function in the next section when we're talking when we talk about approving an NFT but for now we just know that this checks if the user who's calling the function is authorized to send that token okay and then we call this internal transfer function that we are going to see now so the transfer function takes the same three arguments and what it what it does is that is going to create a mutable variable for the owner of the of the token so at first the owner will be the current owner of the of the of the token that we want to transfer so we did this this little check here to verify that that actually that token has that that NFT and then we modify the owner to the destination address right then the next thing that we have that we do is that we modify the balances of the from address and the to address from the source address to the destination address from the source address we decrement one from their balance and from the destination address we increment in one their balance okay and finally we emit the log that we get from it okay the safe transfer from functions we are not going to see the details but they basically do the same as transfer from but call the function on ERC721 received on the destination address because those are smart contracts all right so second second important part of an NFT approve the management of an NFT okay so these functions what they do is that they grant another account the ability to manage one specific token ID or all the tokens owned by a specific account okay so for example if I have an NFT I can give another person the ability to manage that token ID for me and manage in this case means they can transfer that token from me so why would I do that for example well if I'm using a platform where I can buy and sell NFTs I I probably want to give the ability to give the platform that platform the ability to move my tokens so they can match buying and selling operations right and move those tokens might be so that's one example for example that many others so what do we need to keep track of in this case we need to know what accounts have been granted rights over specific token IDs and what accounts have been granted rights over all tokens that are that are owned by specific accounts okay so these are the the functions that the standard tells us that we need to implement we have an approved method where we say okay for this address I I want to give this address the ability to manage this token ID that I own obviously and said the proven for all is like says something like I want to give this address the ability to manage all my tokens and I can enable that or disable that with the second parameter so I can first enable the ability to move all my tokens or disable that later if I don't want to to to keep that on okay and then we have two getters for for the same thing for a specific token ID for all the tokens of an order also the standard tells us to meet two events one for when we grant allowance of a specific token with the event approval and one when we grant allowance for all the tokens that I own that is approval for all right so okay let's move to rest now how do we keep track of that what storage variables do we need so we need to we need one for the approvals of a specific token ID so that's a map from token ID and who can transfer that token on my behalf and we need a mapping another mapping for for addresses I mean this address is for all my tokens I want to give the ability to move all my tokens to this address okay and I can enable or disable that that's more or less what it says right so the for the methods we we need one for approving the approved method that we saw before so we take the the owner of the token ID we verify that the user who is calling the function is either the owner or can manage the tokens of that owner remember that MSG sender well remember I don't know if you know that but MSG sender references the user who is calling the function so MSG sender if I'm calling the function that will be my address okay so if my address is not the owner of the token or the the owner of the token hasn't grant me the ability to move their tokens then I can't perform this operation okay I've been this throws an error so if everything is okay then a new entry is added to the approved mapping that we saw before and an analog is emitted for the set approval for all is the same operation here only the owner I mean only I can grant someone else the ability to move my tokens okay so I am the only one who can call this method and well not the only one but when I call this method it's going to create an entry for my address okay and also I meet a lot there we have the getters here for the two mappings get approved and is approved for all I'm moving a bit too fast into these these examples are all in the code in the repository um so you can take a look a closer look later but as we have a short time here with I'm just moving fast through them okay and then the function that we left before without without checking which was required require authorized to spend remember that when we when we when we want to transfer a token we first check if the if the user who is calling the function is able to move that token either because he's the owner of that token or he has been granted approval of uh moving that token all right so this is what this function does so we first get who is the owner of the token and I will check obviously that the owner has the token and then if the owner if that is the is the caller of the function then we turn okay that means that they can they are authorized to spend and we check in the approved for all mapping if the caller of the function is able to manage all the tokens of the owner of that token then we return okay we say okay if you are approved to spend and then we check the specific approved mapping to see if this specific token ID can be managed by the messages and by the caller of the function okay and if none of these conditions are met then we throw an error meaning that the caller of the function is not allowed to transfer this token or to manage this token okay so that's transfer and that's approval and for minting I'm going to explain yeah just minting and yeah and and with the with the with the scripts so minting in this case there is no specific uh interface in the ERC 721 standard that tells us okay you have to create this function to mint because it gives us the ability to say okay you can create all the tokens at the beginning when you deploy the contract or not and you can have a function to meet the token and and have it like have the users pay for pay some money to meet the token but basically minting a token what it's going to do is it's going to create a new token okay so for this function for this functionality we are going to create this function mint and we've added the payable keyword here but for this example it's going to be free to mint and what we need to keep track of is how many tokens have been created minted and what a specific token is going to be created next okay and we're going to see why now so for the storage the only thing that we need is the total supply we need to keep track of how many tokens have been minted and this is also important because in this example and this is also this also happens in many NFTs and we are going to create the tokens incrementally that means that when we deploy the contract so no tokens are created the first one is the first one that is going to be created is the token ID zero then the next one is going to be the one next one is going to be two next one three and so on so forth so for the method we are just going to create this mint function the token ID that we are going to create is actually the total supply that means that well as I said before when we deploy the contract the total supply is zero so the token ID that we are going to create is zero when we create that one the total supply is one so the next one is going to be the token ID one so on so forth so we get the token ID and then we increment the total supply in one okay and then we call the transfer function that we saw before to transfer that new token ID from the default address I'll explain this now to the MSG sender who is the caller of the function so why do we send that from the default address well this is a particular behavior of blockchain actually that means that when we deploy the contract we say that no tokens exist but technically all tokens are owned by the zero address so all tokens are owned by the zero address so when we when we create a new token we transfer that from the zero address to the caller of the function in this case okay and yeah and we also need two two getters which are the balance of that gets a specific entry in the balance mapping that we saw at the beginning and the owner of that yeah it does the same it gets a specific entry of the owner's mapping that we saw at the beginning I'm not going to explain burn an NFT because we don't have a lot of time but basically it just it does the opposite of creating an NFT it just removes the token without decrementing total supply it just sends the token to the default address to the zero address okay all right token URI let me briefly explain this this is this is not actually part of the ERC 721 core standard it's part of an extension of that standard and what it does is that associate a specific URI to every token so we can we can store specific information uh somewhere else that can be on chain off chain whatever so and that information usually is well the name of that specific token the description of that specific token uh properties that that specific token has that might be different from all the tokens and yeah several other information that we couldn't save there and in this case we can do like several different implementations of this but one basic implementation will be just to return a root URL with the token ID.json file that will yeah that will return all the structure the information of that specific token okay all right so before finishing let me briefly talk about how to call these methods and please already touched a bit into how to into Foundry sorry that we can use Foundry to call these these functions and I wanted to show you an example here because you saw that uh I think I can show you and it's exact yeah I can show you an example here if we go to the trans yeah balance off for example so as you see here so we declared this this function this balance of function and as this mentioned we use a snake case to to call this function but when we want to call this contract after it is it's been deployed we are going to use a regular um ABI like Solidity does like we do with Solidity contract okay so if we go to in this repo also this is the one that I'm sharing there is a scripts folder to perform all these operations individually okay so if we want to if we go to the get balance we're going to call that same function using camel case as we see here so um this is because stylus wants to well not stylus actually is to be able to guarantee to the user that they don't need to know the implementation details of any contract we need to provide the same interface to access those contracts regardless of the language they are written in so if they are written in Solidity they are accessed in this way if they are written in Rust they need to be accessed the same way okay so that's why stylus modifies well in this case the SK modifies those snake case functions to to be called using camel case or the standard way that we call smart contract functions okay so this is just one example of foundry that I think Chris wanted to touch a bit upon um we used cast call we pass here the RPC URL this little variable that we have here is preloaded with the with the URL that we are using this case can be your local node can be stylus testnet for example and then we pass the contract address that we want to call this will be the contract where the the contract is deployed the sorry the address where the contract is deployed and then the function that we want to call the inputs that it receives the outputs it returns and when this case you put the inputs of the call that you're going to make after the the signature of the function okay um Jason if you can tell me how much time I have left if I don't have any more left just tell me so um so if you saw I can touch a bit on all the things but basically yeah that's a bit what I wanted to show you today there are still a lot of things that that could be explored here in this QR code it's the same one as before this is the the repo of the NFT contract that we just talked about and we have here several resources I'm going to share this presentation as well with you that's going to be inside the repo and and I think that's it yeah let me know Jason or anyone if I still have some time left if not uh we can finish here okay so while they respond I'm going to show you something else so in this repo and this is the repo that I'm sharing with you this is the NFT contract so we have several scripts right so you can um you can add here several the the variables that you want to use for these scripts if you have used batch before uh or yeah or any terminal this is usually the same with any term with any shell uh you can create here the the find the different variables that you want to use and then you can call the different scripts that are inside this folder so you can see what happens when when you do when you perform certain operation and what instruction you are using what CLI command you're using for for that specific instruction okay so in this case if we want to deploy our contract for example we will just call scripts deploy also these uh all these instructions that I'm sharing here are available in the read me of the repo okay so yeah if uh you can read that from there as well this deploy command what it does is just it deploys in this case it deploys to that to the stylus that's there and it gives us the the the the address of the contract that's been deployed right so in this case it is our NFT so if we want to for example check the balance of of our address we can just call this uh this command right here and we see that the NFT balance is zero and we can meet you can call the meet um so if you can kill call the meet script to meet one token this is sending the transaction to the blockchain now to stylus that's it right perfect if you if you check the balance now again we get the we have one NFT and yeah we can also transfer it to another account we can get the token uri if we want uh for example this is prepared these are all commands that I have prepared here to do the operations with basic contract with with uh sorry with predefined variables for example in this case we're going to get the token uri of the token id zero that we get that the token uri is this one and yeah I think that should be all if you have any questions about stylus you can go to our arbitrary discord there's a specific stylus channel there you can ask those questions there um I'll be sharing these uh there's also a telegram group I think we have all of it here this is specific for arbitrary stylus um there's another specific for first first Asia will be around there as well and and yeah I think that's all yeah Jason I'm I'm done so thank you very much for for being here and yeah hope you enjoy the rest of today thank you hello all right that wraps it up uh thank you very much Jose really appreciate it I don't know it's I don't know it must be an ungodly hour for you to really appreciate you taking the time it's uh it's the auditorium is quite full people so I really appreciate that okay uh I think that wraps it up for us uh well unless either anyone who wants to ask Jose a question before he gets off all right if not uh yeah just thank you very much I know it was a very long day must be tired um so yeah just uh I think we gave you all the links and everything for you to download and come check it out but please uh Jason and I will stick around for maybe 15 minutes or so to answer any questions uh if not I think all the information is on online and please follow us on Twitter and also please join us on telegram thank you very much have a nice day