Smart Contract Development
The course is part of this learning path
This course provides a deep dive into the Solidity programming language which is used to implement smart contracts on blockchain platforms. This course will give you a practical understanding of Solidity and how to develop your own smart contracts.
In the previous lecture, we were talking about arrays. And while arrays are kind of important, there is a better way to handle something like arrays or something like hash maps from other programming languages that are mappings in Solidity. And they are actually preferred not because they are more complex, but because every value that you can imagine is already initialized by default. So all these overhead that you would have normally with hash maps in other programming languages, they are not here in Solidity. And the one property which you want to have with arrays which is the length that they have, you can't really use it because when arrays grow over time then you shouldn't actually iterate over those arrays, so the length doesn't help you a lot. So this is why mappings are actually preferred at all times except for some things where you know in advance that an array wouldn't scale. Like for example a game board, we have a three times three or four times four array where you place some bets on it. But for everything else be it like members where specific properties are safe to the members, there mapping will be preferred. Now, let me explain how a mapping would look like, and that's the content of this lecture. And in the next lecture we're talking about structs because usually mappings and structs they always come together. Let me start with some very, very basic and simple examples of how a mapping would look like. And that example, the first one that I want to use is really just having a Boolean store to an address. So when an address saves its own Boolean to true then this is stored persistently, and then it can go back and change it to false. It's really just a very simple example how a mapping looks like, and then I explain to you how the mapping actually really looks like in a theoretical sense. So a mapping always starts with the keyword mapping, and then in round brackets you have a key type and the sign is to a value type. And in our case we want to have a key which is the address and the value is a Boolean. So we would write the address, map this to Boolean. And then you give the mapping a name. For example, my address bool mapping. And I'm going to make this public because all the public variables are having these automatic data functions from Solidity, which comes in handy at this point. And when I just run this, and you can have a look at the code in the C08 code folder in our repository. Just if you want to follow along. It's a pretty large Solidity file there, so you might want to follow along in the video. So I deploy this smart contract and now I can read. For interest I copy my address here which I just deployed. And I can read my mapping. And it's initially false. So every address that you can imagine from 0x0. I have to type in the whole address, but I'm not going to do this now. So every address that you can imagine is initialized with the default value for a boolean. So this would be corresponding to an array that stores addresses as keys, which is essentially not possible. But with a hash map style data structure, like a mapping, this is possible. And this is exactly what the mapping is doing. So a key type can be pretty much anything except of complex data types, like other mappings structs, which we're going to discuss later. You can't use a key type as a contract. I think you cannot use a key type as a string, but usually you want to use addresses, you want to use u ints, you can use bytes. So all of those which you want to use as a mapping, and which we're going to use as a mapping in our course is available as a key type. And there's a value type where you map the key type to the value, then you can use pretty much anything. You can use other mappings. So you can use mappings of mappings of mappings if you want to have more complex structures, or you can use other contracts, you can use strings, you can use structs and so on. All right, let me tell you how a mapping is being written to. So for example, you want to have a writing function that maps any address to a boolean, and I would say, function, write the boolean mapping, and then we have an address, and we have a boolean and there's this public, and then we say, my address bool mapping. And here we will write it as if you were writing into an array. And we have the key which is our address, and that is our boolean. Let me deploy and try this, so I'm going to remove this one. I deploy the mapping. And now we can say currently our address is false, but if you're going to set this one to true then it becomes true. And you can also follow along on the left side here. You see all my transactions are running through just perfectly. Now, solidity, and we are going to maybe not use this for our project later, but solidity can do function overloading. That means you can have more than one function with the same name, but with different arguments. And solidity can handle itself. Which one it's going to use based on the function signature. So if I have another function, write Bool mapping. And I just say, boolean, then I could also do my address mapping message sender. So I set my own boolean. It's boolean. Okay, deploy this. Set this to true, and it should be true. Now it's true. All right, but you don't have to remember this. It's just a side effect that I wanted to tell you what solidity can do. If you come from other programming languages, you might want to enjoy this quite a bit, that you can do function overloading. Then there is another use case which is a traditional use case from wrappings, where you store a specific balance to an address. So if somebody pays something and we've previously we stored this in a uint balance, but the uint balance is just a single variable, which you can increase and decrease. So if you want to save a balance for a specific address then you maybe can do something like uint balance account 1, uint balance account 2 and so on. And you may save the account somewhere else, and then you have an array which stores which account is which index, in which variable and so on. But it's all pretty cumbersome. Not with the mapping, with the mapping you can simply type mapping and then you store a uint to an address. And I'm going to make this public too, and I call this my balance for address. And when I pay something now, let's say I have a function deposit mapping, that is a public payable function. So I can pay something to this function. And then I can say, my balance for address increases with the value that I sent along. Now, let's give this a try. I deploy this and I deposit, let's first check how much is in my balance mapping. Where is it? Bool mapping balance mapping. So it's currently zero, and then I deposit one ether into that, and then the ether that I deposited into my smart contract are credited to my mapping over here, so I always know which address deposited how many ether into my smart contract. Now with this in mind, we are coming to our coding challenge for this lecture, which is a little bit bigger than the previous coding challenges. Now, we have the balance for an address and now we want to have a withdrawal function. I call this now withdrawal mapping. And it's a public function. And somebody can withdraw to a specific address, a specific amount. And based on our mapping, it's up to you now to find out if the amount that he want to withdraw to the address he specified here is enough that he had credited before or he transferred before to our smart contract. So if he tries to send more than he has in the balance for address mapping, then you would have to deny this withdrawal request or else you just do a to the transfer and then the amount. And don't forget to deduct the amount that he send from the balance for address mapping. It's a little bit of a larger coding challenge. I will show it to you definitely after the coding challenge. So if you want to do the coding challenge, then pause the video now. And right after that I will show you how it's done. All right, with the limited amount of instructions that we have learned so far, we haven't learned about exception handling, will require a ssert and revert. So I will show you how you do it without requiring an assert, but I definitely want you to watch the exceptions in solidity lecture later in the course if you want to have a little bit more of a powerful way how to manage those exceptions. So in our case we want to see first if the balance, my balance for address mapping has enough ether or has enough funds stored for the withdrawal request. So you would say, my balance for address mapping for the person who is trying to withdraw the money must be larger or equal than the amount. And if this is the case, then we are going to first deduct... Deduct the amount from the balance for address mapping, so that he cannot recall this maybe during the same transaction that is running. And then we are going to transfer the amount over to the person he requested to be the beneficiary of this withdrawal request. And that is pretty much everything there is to do. The one thing that might be unclear to beginners is maybe this minus, equal sign, which is the same as my balance for address minus amount. This is the shorthand form, where you just put the minus in front of the equal sign and then it internally does the same as the long version. All right, this is everything for this lecture, and in the next one we are talking about structs, which are very powerful way to define your own data types in solidity. I'm really looking forward to show you that, so you can define some more complex structures in combination with mappings, which really makes sense when you want to smart contract development. Also in the source code, I will show you the two versions: one with exceptions and one without exceptions. So, if you want to follow along, go to the course repository SO1C08 mappings, and then the CO8 mappings struct solidity file, where you can find these functions again with comments from me. And if you run into any problems, rest assured. Just head over to the Q&A, and we're there to help you out. I'll see you in the next lecture.
Tom is a CTO, senior back-end developer, and systems architect with over twenty years of hands-on development experience in a variety of languages and systems. He has a CS master's degree and has been working with Ethereum and blockchain technologies since 2016.