Function And Address In Solidity

In Ethereum smart contract, function and address are broadly used value types. This article talks about the usage of function and address including examples.

In Ethereum smart contract, address and function are broadly used value types. In this article, we'll see the usage of both. If you’re new to here, I would encourage you to read the previous article of Variables and Types in Solidity.
 

Function Type

 
Solidity functions are methods used to perform some specific task. They get invoked during the execution of a smart contract. We've already used functions in previous articles; in our first smart contract of HelloWorld, printHelloWorld was a function.
  1. pragma solidity ^ 0.5 .0;  
  2. contract helloWorld {  
  3.     function printHelloWorld() public pure returns(string memory) {  
  4.         return 'helloWorld';  
  5.     }  
  6. }  

Function Structure

  1. function (<parameter types>) {internal|external|public|private} [pure|view|payable] [returns (<return types>)]   

Function Parameters

Parameter types are the input variables. It can be used as any other local variables with an assignment. In the following example, _a and _b are function parameters.
  1. pragma solidity ^0.5.0;  
  2.   
  3. contract Types {  
  4.     uint sum;  
  5.     function result(uint _a, uint _b) public {  
  6.         sum = _a + _b;  
  7.     }  
  8. }   

Return Variables

Return variables are used to return something from the function. We can pass return variables with "returns" keyword. Let's understand it with an example. In the above function, we've stored the sum of _a and _b to the state variable named "sum". Now, I want to return state variable value and for that, we have to modify the result function as below.
  1. pragma solidity ^0.5.0;  
  2.   
  3. contract Types {  
  4.     uint sum;  
  5.     function result(uint _a, uint _b) public returns(uint){  
  6.         sum = _a + _b;  
  7.         return sum;  
  8.     }  
  9. }    
The return keyword can be omitted, but then you need to mark it as pure. If you have no idea of what pure function is, nothing to worry about; we'll see later in this post.
  1. pragma solidity ^ 0.5 .0;  
  2. contract Types {  
  3.     function result(uint _a, uint _b) public pure returns(uint sum) {  
  4.         sum = _a + _b;  
  5.     }  
  6. }  
In Solidity function, you can also return two or more values.
  1. pragma solidity ^ 0.5 .0;  
  2. contract Types {  
  3.     uint sum;  
  4.     uint mul;  
  5.   
  6.     function result(uint _a, uint _b) public returns(uint, uint) {  
  7.         sum = _a + _b;  
  8.         mul = _a * _b;  
  9.         return (sum, mul);  
  10.     }  
  11. }  

View Function

Functions which will not alter the storage state can be marked as a view function. In simple terms, it is used for viewing the state. 
  1. pragma solidity ^0.5.0;  
  2.   
  3. contract Types {  
  4.     function result(uint a, uint b) public view returns (uint) {  
  5.         return a + b + now; //"now" is current block timestamp in 
  6.                             //seconds in unix epoch format  
  7.     }  
  8. }  
Here, "now" is a state variable, and we're reading the data by using it. As we haven't changed the state, the function result is view only.

Pure Function

A function that does not modify or read the state, is called a pure function.
  1. pragma solidity ^0.5.0;  
  2.   
  3. contract Types {  
  4.     function result(uint a, uint b) public pure returns (uint) {  
  5.         return a * (b + 42);  
  6.     }  
  7. }  
In the example above, we don't have any state variable, and we even not reading the state anyway, therefore result function should be marked as a pure function.
 
Payable Function
 
Payable Functions allows to receive Ethers while it being executed, means that, if someone sends some Ethers to the smart contract, and it doesn't have a payable function, then smart contract won't accept ether and transaction will get failed. To catch that transfer amount, the smart contract needs to have a payable function.
 
For example, in below code, the receiveEther function is not payable, so when you deploy this contract and run the method receiveEther, it will give an error. 
  1. pragma solidity ^ 0.5 .0;  
  2. contract Types {  
  3.     function receiveEther() public {}  
  4. }  
Not payable function execution
 
Now, modify receiveEther with payable and to check contract receive the amount or not, also add a state variable that keeps the Ether value.
  1. pragma solidity ^0.5.0;  
  2.   
  3. contract Types {  
  4.     uint receivedAmount;  
  5.       
  6.     function receiveEther() payable public {  
  7.         receivedAmount = msg.value;  
  8.     }  
  9.       
  10.     function getTotalAmount() public view returns (uint){  
  11.         return receivedAmount;  
  12.     }  
  13. }  
Things to notice
  • receiveEther is payable function and it will receive the Ether amount.
  • We have stored received amount value in state variable called "receivedAmount".
  • To read state we have used view function called "getTotalAmount".
  • msg.value is a member of the message object, and it contains a number of wei sent with the message. (We'll learn more about message object and denominations in a future article).
Deploy the contract and execute as displayed above. It won't give any error this time. Once it's deployed, run the method getTotalAmount. you will see the value of the amount you sent to the contract.
 
Received total amount 
Note that, we have received Ether in its smallest unit called "wei". Currently, just keep in mind that wei is the smallest unit of Ether. 1 Ether = 1e18 wei.
 
Fallback Function
 
Solidity supports a parameterless anonymous function called Fallback function. One contract can have only one fallback function, and it must be defined with external visibility. Generally, a Fallback Function is used to receive Ether with a simple transfer, when someone called it without providing any data. 
  1. function() external payable{              
  2.         //todo    
  3. }    

Function Overloading 

Solidity allows the overloading concept. A contract can have multiple functions with the same name, but the number of parameters should be different.
  1. pragma solidity ^ 0.5 .0;  
  2. contract Types {  
  3.     function f(uint _in) public pure returns(uint out) {  
  4.         out = _in;  
  5.     }  
  6.   
  7.     function f(uint _in, bool _really) public pure returns(uint out) {  
  8.         if (_really) out = _in;  
  9.     }  
  10. }  
However, we cannot overload a function by its return type, just like other programming languages. The following code won't compile.
  1. pragma solidity ^0.5.0;  
  2.   
  3. contract Types {  
  4.   
  5.     function f(uint _in) public pure returns (uint out) {  
  6.         out = _in;  
  7.     }  
  8.   
  9.     function f(uint _in) public pure returns (bool out) {  
  10.         if (_in > 1)  
  11.             return true;  
  12.     }  
  13. }  

Address Type

 
On the Ethereum blockchain, every account and smart contract has an address and it's stored as 20-byte values. It is used to send and receive Ether from one account to another account. You can consider it as your public identity on the Blockchain. To make it more clear, you can think of it as a bank account number, if you want to send some money to me, you need my bank account number, similarly, in the Blockchain, you need an address to send and receive cryptocurrency or make transactions.
 
Also, when you deploy a smart contract to the blockchain, one address will be assigned to that contract, by using that address you can identify and call the smart contract, that we'll see with an example later in this article.
 
In Solidity, address type comes with two flavors, address and address payable. Both address and address payable stores the 20-byte values, but address payable has additional members, transfer and send.
 
Address 
 
Address type defines with address keyword.  
  1. address myAddress;  
An address is used to store the value of any address. In below example, "caller" is an address type.
  1. pragma solidity ^0.5.0;  
  2.   
  3. contract Types {  
  4.   
  5.     address public caller;  
  6.       
  7.     function getCallerAddress() public returns (address) {  
  8.        caller = msg.sender;  
  9.        return caller;  
  10.     }  
  11. }  
OR do to not modify the state and use view function.
  1. pragma solidity ^0.5.0;  
  2.   
  3. contract Types {  
  4.   
  5.     function getCallerAddress() public view returns (address caller) {  
  6.        caller = msg.sender;  
  7.     }  
  8. }  
In above example, we're storing sender address using msg.sender, who is supposed to execute the function getCallerAddress. If you deploy and run the function, you will get the address from which you have executed the getCallerAddress function.
 
We can also get the deployed contract address as following.
  1. pragma solidity ^0.5.0;  
  2.   
  3. contract Types {  
  4.   
  5.     function getAddress() public view returns (address) {  
  6.        address myaddress = address(this); //contract address  
  7.        return myaddress;  
  8.     }  
  9. }  
 get contract address
 
 Get contract Address
Address payable
 
Address payable has an additional keyword "payable"
  1. address payable caller;  
When we want to transfer some funds to the address, we need to use address payable. There are two members to perform a transfer, send and transfer. Both are doing the same thing, but the difference is; when the transaction gets failed, "send" will return a false flag, whereas, "transfer" throws an exception and stop the execution.
 
In below example, there are two functions transferFund and sendFund. When we execute transferFund, it will give an error. However, sendFund will give a false value.
  1. pragma solidity ^0.5.0;  
  2.   
  3. contract Types {  
  4.       
  5.     function transferFund(address payable _address, uint amount) public {  
  6.         _address.transfer(amount);  
  7.     }  
  8.       
  9.     function sendFund(address payable _address, uint amount) public returns(bool){  
  10.         _address.send(amount);  
  11.     }  
  12. }  
 
 
 Output of send and transfer in Solidity
 
In this article, we have discussed two values types - function and address. We've also covered varieties of function and address and their usage. In our next article, we will explore Data locations in Solidity.