A Tour of Web 3: Ethereum & Smart Contracts with Solidity Reading from Storage Methods
Transcript from the "Reading from Storage Methods" Lesson
>> Let's jump back to the code and I bet you we can explain what's happening here, all right? So first, let's look at what's happening right here, this is the most important, I'm doing an OR operation. What do OR operations do? Flannel guy.
>> They exclude one or the other.
>> That's exclusive, what are ORs used for? Answer for taking out or is our for tracking, putting back in, you put stuff in with ORs, you take stuff out with ans. Ans are meant for selecting, does this thing contain something? Or is our for let me put it into the thing, so I'm obviously putting a value into hero, all right, so what is the value?
[00:00:49] Well, the value of some randomly generated stat between 1 to 18 maximum, but then I do this thing, what is this again? Does everyone remember what that is? It's the equivalence to multiplying by 10, but on a binary level, it's multiplying by 2. Now how many times are we multiplying by 2 by?
[00:01:10] One of these numbers right here, we may be shifting over by 2 12 times, so let me draw what the hero is going to look like. So you'll notice, right away in the code, the first thing I do I say, hero equals class, what are the numbers of class?
[00:01:29] Does anyone remember what are the potential numbers set of class? Zero, 1 and 2, correct? Mage, healer, or barium, there's only three possible values, which means that can be represented by two bits zero,1, or 2. So that means, my hero number, the first two bits are gonna be representing its class.
[00:01:53] If it is a zero, it's image, if it is a 1, it is a healer, if it is a 2, it is a barbarian. All right, well, now I need to be able to store all of this delicious stats inside of it. So that other method, remember how we made binary by simply finding the biggest power of two that could fit within the number.
[00:02:14] And then that's how you can convert a decimal number into a binary? Well, how do you store a decimal number? What is the minimum set of bits you can store a decimal number in? You find the smallest power of two that is larger than the decimal number, so 2 to the 4 is 16, that can't fit 18.
[00:02:33] 2 to the 5 is 32, that can fit 18, so we need 5 bits, to store any of these values, so I put strength in the first position. So that means it's starting at 2, cuz we don't want to clobber any of the class and it ends at 7.
[00:02:54] Man, I'm just so pumped right now, this is like the best part of the whole thing. The next one is health, exact same principle, starts at 7 bits, it ends, of course, just a little bit later, 5 bits further or 12. And then we do dexterity, we do intellect, and we do magic.
[00:03:13] And so here let me just draw each one of these at the drums slightly smaller, cuz I just got too excited and made the other sections too big. They're all taking up five bits, right? So this one ends at 17, this one ends at 22 and now that means strength starts at 2, so let's go back to our code, what's right here?
[00:03:32] 2, so let's say we select the zero with stat, the zero stat is going to represent strength. That means when I select a random value somewhere between 1 to 18, I'm in a bind narrowly shifted over two zeros and then or at in. So let's do a little quick kind of bit of like binary representation here, let's say we selected our class to be barbarian, 01.
[00:04:02] That means the rest of our hero is a bunch of zeros, man, sucks to be a hero, that's a zero. And say we select a strength stat, so the first, the next 5 bits are going to represent strength. Let's say we had a strength stat of 13, so he is kind of a zero barbarian, right?
[00:04:19] Not that much strength, so what is 13 in binary again? Well, it's going to be a 1, I can tell you right away and then it's going to be a 4 and it's going to be an 8, that is our strength. So if I take 13 and I shift it over by 2 or multiply it twice by 2, I get 2652, so what is 52?
[00:04:41] Well, we do the exact same thing, as we can bring it all the way back down or I can just simply write two zeros right here. Now we used the OR operator, remember the OR operator is for putting into the item. That means anything that's a 1 in the original value will remain a 1.
[00:05:02] But anything that is a zero in the original value but a 1 in the value you're ordering into will become a 1. That means when I take this number in order it will save this number, these two effectively are cancelled out and will be whatever is in here.
[00:05:21] And the only thing we're writing into is these items right here, this is not like mind blowing and actually pretty awesome. This is pretty cool, well, let's actually, let's write this thing out just a little bit better. So that means if my current hero value is this and we're writing in strength, and our strength value is 1101 or 13.
[00:05:42] We first take our 13 and we shifted over by 2, right, two sets of 2, which makes our new number look a little bit like this, right? And so now when we OR this number with this number, what we are going to get is 10, class preserved, we have not clobbered our class yet.
[00:06:06] Then we write in our strength cuz we are doing an OR, all ones make it into the final solution. So now our class, though a larger number contains two sets of information, 10, which is the class, and 1101 or 13 or our strength property. Which means, I know it's going to get even better, which means we can jump up here and window function get strength Give it a UNT.
[00:06:33] We'll call it a hero, and this thing can be a public pier returns uint, right? And you could technically return it, all right, we're going to do a unit, that makes sense. We're going to return hero, I'm going to shift it over by 2, right, cuz we don't want those first two bits, right?
[00:06:50] Those first two bits are the class information, then we need to end it, meaning we want to select out only the next five bits, what is five ones? Does anybody know what five ones is? And let's use hexadecimal cuz it's a lot easier.
>> That is the maximum number, so what is 32 minus 1?
>> Boom, I'm gonna show you a really sweet property about binary, man, this is just getting better and better, is this not? So if you have a power of 2, any power of 2, let's just go with that one, 32, right? So 32 is this right, 1,2,4,8,16,32, if we were to minus a single one from this, what happens?
[00:07:35] 111110, so if you want to produce x ones, you simply take, 0x1 shifted over by whatever number you want x and then minus 1. And you now have x ones, wow, that was so cool, right? But luckily, we don't have to do something as silly as 0x1 shifted over by 5, then of course do a minus 1.
[00:08:09] All right, we don't need to do that cuz that's a bit complicated, right, for this one cuz it's a hard coded value. We don't technically need to do that, so instead, we'll do this, 0x1f, cuz remember, f is 15 or 1111, and 1 is just simply 11. So that is five ones in a row in hexadecimal, there we go, we've now selected out the strength property from our hero.
[00:08:36] While we do the exact same opposite operation by oaring it in, and shifting it the other direction, we shift this way, select all five bits. We shift this way and or in five bits, so they're kind of mural operations of each other. So that is how fundamentally, a lot of these NFTs work is, they use this 256 bits and they store much possible information in.
[00:09:05] And then they shift them around, what you'll also notice, I didn't do, any like UN8, right? I could have used the UN8 here, right, I could use the UN8 right here. The reason why I don't do that is you get overflow super simple when it comes to bits, one kind of cautionary tale.
[00:09:22] Let's say we're using a UNT8 and we shifted over by 7 and our value of course is 0x11. So let's shift over by 7, will become zero, it becomes, that's one, two, I know this is painful, three. Let's go up to seven now 1, 2, 3, 4, 5, 6, 7, 1, what do we write right here?
[00:09:49] We're using an eight bit number but we shifted it over by seven, where does this other one go? It's off the bit, we can use it, it's gone, I don't even know what happened, what happens in theory? I don't even know what happens in a theory, but I can tell you this much, it's the wrong answer.
[00:10:03] No matter what it was, the answer is no, and so be very careful when bit shifting. Cuz if you are like, I'm be clever, I'm going to save some space, and then you end up shifting yourself into an overflow. Nothing will work, I have seen this happen how much amount of times, so there you go.
[00:10:21] This is what happened, does anyone have some questions about what's going on here?
>> Can you be certain that stats are initialized to zero or was that explicitly done somewhere in the code?
>> First off, how are stats initialized to zero and how were they explicitly done? Well, look at what I did right here, I set my hero value and I casted the class to a U8.
[00:10:49] Which the class value is 01 or 2, which means it's binary representation is going to be 01, or 10. That means the rest of the other 254 zeros that I have available are all zeros, right? They've been cast to a very specific number, and I notice I'm using UNT, you use the int.
[00:11:09] You're gonna have a different encoding and get some two's complement in there, and everything's gonna get screwed up and you're gonna be unhappy. So always use unsigned integers when doing binary operations, but there you go, that is why I have that, any other questions? Cuz this is a good time to ask questions because most people don't interact with binary on a regular level.
[00:11:26] I tried my best to give you what took me an entire semester in a very small amount of time to be able to fluently work with, yes, Mark.
>> So what we're selecting the next property would it be 0x3ff?
>> No, so would not be, it would not be hexadecimal 75, it would actually be 0x1f, because remember, we're making our bits five long.
[00:11:53] If we wanted to select out a bite, we've used two F's, because two hexadecimal numbers represents eight bits. One represents four bits or a nibble, get a nibble bite has math, there you go, so that's what happens. So we're going to only select out five bits, that's why when we did get strength, we did five bits.
[00:12:17] First, we shifted it into place, meaning, we shifted the class off and now strength represents the first 5 bits. Then we select the 5 bits, which means, if I wanted to come in here and pace in and go Fs and go into health, I would simply shift by 7.
[00:12:33] We shift off the class, then we shift off strength. And now the first five bits in this temporary hero variable is health, and so we can do it again, let's go on here. Fh, and go Dex and we can go of course 12, do it again, paste it in, ffd bingo Intel LACT and go up to Oopsies, 17.
[00:13:00] And of course, one last time, fi magic, there we go, with the J cuz I really love fun spelled items. And then go down here and bring it up, there we go. So now we've literally created every single way we need to select out those values, doing the opposite operation that we did before.
[00:13:20] If we want dexterity, we need to shift off the class, two bits, we need to shift off strength. Fve bits, we need to shift off magic [INAUDIBLE] or our health, which bring another five bits or 12. Shift off the first 12 bits, then we end it, so we only select five bits, if you don't do this, you would not only would you get dexterity.
[00:13:39] You would also get intellect, you would also get health and potentially, any other information that we decide to store in there. And so we got to be very careful about this this is kind of like where the real tricky stuff happens. And so hopefully, this makes a lot of sense, now obviously, we could put these values in the constants and all that.
[00:13:58] But again, you store stuff on this contract is it more or less expensive, more expensive. If you read it from the contract, is it cheap or expensive? Expensive, right, so you gotta, you want to be careful as much as you can. Great software engineering principles don't necessarily map one to one to solidity, so you just kind of gotta keep those things in your brain.