1. Home
  2. Training Library
  3. Programming
  4. Programming Courses
  5. Smart Contract Development with Solidity

Global Objects and Payable Functions

Start course

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 this lecture, I really want to talk about where we stopped in the previous one with addresses, which is how to pay a smart contract and how to handle these payments. And then there's also this global objects which I want to slightly touch. It's called the message, send the message value objects, which holds the values that are sent to a smart contract or the address which initialized this transaction. Now, let me start by a very, very simple example which is how to pay a smart contract. And we had this in the previous lecture already. We had a function, let's say payMeSomething, and that is public. Now, in this case, the function payMeSomething cannot receive any ether because it doesn't contain this payable modifier  or this payable keyword here. So, when I run this, I hit 'Deploy', and I say I send one ether along to the payMeSomething function, then it will have this X here, and it said it error revert because the constructor should be payable if you send the value but it's not the constructor  it's actually a function that should be payable. So, once I say payable, redeploy this. Let me send one ether to the smart contract. Then the function goes true. And now the thing is the smart contract contains one ether  because I have one ether less here and the smart contract can handle its own funds. It could do an address, send somewhere and send the funds back to an address. Now, let me give you an example of how this works, function withdraw ()  and I make this public. And I want to withdraw to a specific address, let's say it's going to be an address _to. And I cannot withdraw to this function because as long as I just have address without the payable modifier or the payable keyword. As long as it's that, it's just the 20 bytes value without any members except of the balance. Now, I cannot send anything to this address and I have to add the payable modifier here, the payable keyword.  Then I could do a _to.transfer and then maybe one ether, that is then 10^18 way which is 1000000000000000000. Okay, what happens next is when I hit 'Deploy' here, I have these two functions: payMeSomething and withdrawal. Now, at the moment, my smart contract doesn't contain any ether. It doesn't contain anything because it just deployed my smart contract. When I copy this address here and I paste this address here, then it says it regarded the constructors  should be payable if you send the value, but it's not, and the error message is slightly misleading, but if I could go into the debug field then I see it will stop at the _to.transfer and it cannot continue from there anymore. So, here would be if it's a really large smart contract and I don't know why it stopped the debugging  would come in handy. Now, we don't need to debug here because I already know that it doesn't send me the money because it doesn't have any money in the smart contract. Let me just make sure that it's not because of the double quotes here. Okay, same error message. Now, I have to put in one either first or more in order to get one ether out. And when I send one ether and then I withdraw, this works perfectly fine. I sent one ether there, I got one either back. Let me try this again from this account. I sent 10 ether there and let me copy this account, so I can show it to you in a little bit more clearer detail, and then I say withdraw. Now, I have 101 ether, withdraw, withdraw, withdraw, I have 104 ether, and I can do this as long as I have money in there, and when I have not enough money anymore then I cannot withdraw anything anymore. Now, this is obviously very, very insecure because once this smart contract is deployed and let's say you have put in some money, anybody who can just call this withdrawal function with the right argument can withdraw the money to his own address or to an address of his choice. Now, there are ways to limit this. Let me show you one of these ways. And here comes the message, send the object in, the message sender or the message object with a member called sender, it would be like this message.sender contains the address of the person who initialized this transaction. Now, let's say I want to make this person, something like an administrator of my smart contracts. So, only this person can withdraw money from this smart contract. It doesn't necessarily have to be the to argument, but only this person can decide where this money can be sent to. This can be made very, very easy with the message sender object. Let's say if message sender is not this address, is this address here. Then only this person who is in possession of the private key behind this address who initializes this transaction can actually transfer some funds out or else this will just do nothing, this function. Now, you see this error here which says comparable operator is not compatible with the type address payable and literal string. So, we would have to do it like this. But this one will tell you that this address has an invalid checksum. So, every address is checksummed, and you will see that when you have a normal address then some of the letters, some of the text characters will be in uppercase, some in lowercase, and this way the address can be kind of a checksum to see if the address is correct. Sometimes you send off incorrect addresses, which cannot be, which are not valid based on the private keys that they can have. How can you generate checksum valid address from a checksum invalid address? And there are a couple of tricks, and one of them is what I want to show you now. I can go to etherscan.io and I just search for this address, which is an invalid checksum and voila. The address that will be output here and has a valid checksum, it's the same address 0xCA35b7d9 and so on, 0xCA35b7d9 and so on. But, when I copy this one and paste it over here, remix  and this really compiler will be perfectly fine with it, now it has a checksum. Okay, how does this look like if I execute this? Let me execute the smart contract, and now I can pay five ether here. Pay me something, and I have five ether in my smart contract; that worked very well. You can see it in the transaction log. And now I go to my other account, and let's say this is another person, it's not me, it's somebody else who has access to this smart contract, and he is very intelligent, is here. There's a withdrawal function. Let me withdraw the money to my own account. So, he's copying his own account here and he's calling their withdrawal function. And you can call it as much as he wants, but there is no ether transferred to his account because the only person who can actually do this is the one over here with the right address. Now, you see here's 110 ether, 111. And as long as somebody else is calling it, you cannot really do anything with this ether. Now that you can also do other constructs here  to actually save this address somewhere else. Let's say you have an address called owner  and you've set owner to an address and that is public. And let's say if... Now let's keep it like this. Let's keep it this simple. And the msg.sender == owner. Obviously, you want to have some more control structures or only the other. The old owner can access this variable or you want to set this during the constructor, but we haven't talked about the constructor yet, that comes in the next lectures. So, just bear with me and just have a look at how you can actually manage to automate this behavior where just an owner or admin can access these funds or specific parts of a function. Then you would say I deploy this from here and then this would set the owner to this address. So, I have the fourth account in my account list set to the owner, and now I go and pay five ether to my smart contracts, so five ether to smart contracts. And now this address tries to withdraw the money, but again nothing happens. It must be from the owner. All right. And at the moment obviously, anybody can change the owner. So, you want to change this in a production environment, but this way it is very, very easy to automate access to a smart contract. And if you look at token smart contracts or smart contracts where a specific balance is stored to a specific account, then you usually have this in a variable where you say uint myBalance 0  or you don't even have to do it because it's initialized by default. And once somebody pays something, you increase the balance by what is called the message value. And now you have the message sender and the other one is the message value, which is very important. There are a few more that we're going to discuss later, but those two are the most important parts when it comes to the global objects: the message sender and the message value. And the message value contains the amount of way that are sent along with this specific transaction. So, when I take this account and I send zero ether during payMeSomething, which is the value field here, then message value will be zero. If I pay one ether payMeSomething, then message value will be 1000000000000000000 and so on. So, once I stored this somewhere and I can even store it from whom will send how much either to the smart contract, so, I always know the balance of the smart contract. All right, this is all I wanted to cover in this lecture. And in the next one, we are talking about constructors and modifiers and pretty much go from where we stopped here.

About the Author

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.

Covered Topics