Smart contracts are comprised mainly of functions so it is important to understand how to construct one and all the various options available.

From the solidity documentation, the syntax of a function is as follows:

function FunctionName([parameters]) {public|private|internal|external} [pure|constant|view|payable] [modifiers] [returns (<return types>)]

What this means is that when creating a function, here are the required steps.

  1. Use the function keyword
  2. Provide a function name
  3. Provide parameters if required
  4. Set the function’s visibility. There’s 4 options to choose from. public, private, internal, or external:
  5. Set the behaviour of the function. Choose from view, pure, or payable.
  6. Add any applicable modifiers
  7. Add any applicable return types/parameters

Here is a brief explanation of the different visibilities.

Public: All (contracts can a call the function)
Private: Only this contract
Internal – only this contract and contracts deriving from it
External – Cannot be accessed internally, only externally.

Private is a subset of internal and external is a subset of public. For a more detailed and intriguing analysis of the difference between public and external check this. (TLDR: public uses more gas because it uses memory instead of calldata). (Check the docs for more details).

The behaviours are defined as:

View: Can read the state but will not modify storage state in any way.
Pure: More restrictive than view and does not read or write to the storage state
Payable: Accepts incoming payments

As noted in the docs, statements that are considered modifying state include:

  1. Writing to state variables.
  2. Emitting events.
  3. Creating other contracts.
  4. Using selfdestruct.
  5. Sending Ether via calls.
  6. Calling any function not marked view or pure.
  7. Using low-level calls.
  8. Using inline assembly that contains certain opcodes.

View and pure replaces the “constant” keyword and indicates to the compiler that storage data would not be written as a result of the function call. Therefore  network verification is not required. This means no transaction to mine, resulting in no gas needed to be spent. These functions were essentially look-ups for data held in or derived from a contract’s state.

Pure functions are completely independent of outside state, are the simplest reusable building blocks of code in a program, and are recommended to be used. For further reading, check this out: https://www.youfoundron.com/blog/solidity-constant-vs-view-vs-pure/

Let’s ignore modifiers for now. For return type, if the function returns something this is required. Let’s look at some examples.

function getMessage() public view returns (string memory) {
   return message;
}

Here is a simple function. Let’s use our checklist.

  1. Use the function keyword. YES
  2. Provide a function name. getMessage
  3. Provide parameters if required. No parameters here. 
  4. Set the function’s visibility. Public
  5. Set the behaviour of the function. View
  6. Add any applicable modifiers. No modifiers
  7. Add any applicable return types/parameters. Returns 1 parameter of type string located in memory. NB: in v5.0+ data location needs to be specified. 

Payable functions

A payable function is one where ether can be sent to it. This is how ether can be sent to a smart contract. Examples include:

function deposit() payable {};

function payme() payable{
  amount += msg.value;
}

NB: It is not possible to have payable as a function name as it is a reserved keyword.

Here is a full contract to try:

pragma solidity ^0.5.1;

contract HelloWorld {
  string message = "Welcome";

  function getMessage() public view returns (string memory) {
    return message;
  }

  function getBalance() public view returns (uint256){
    return address(this).balance;
  }

  function acceptPayment() public payable{ }
}

Fallback function

There is a special feature in a solidity smart contract where it can have precisely one unnamed function which cannot have any arguments or return anything back. This is called a fallback function. This fall back function gets executed when a contract is called and no other function matches, or if no data is supplied.

pragma solidity 0.5.1;

contract fallingback {
    
    function () external {
        
    }
}

Note that in v0.5 and above, fallback functions need to be defined as external. This fallback function doesn’t do anything useful. The following is more useful.

pragma solidity 0.5.1;

contract fallingback {
    
    // fall back function
    function () external payable {
    }
    
    // getter function
    function getBalance() public payable returns (uint256) {
        return address(this).balance;
    }
}

Deploy this in Remix and run the fallback function and don’t forget to include a value of say 1 ether. Then call the getBalance function.

1 thought on “Understanding basic functions in solidity

Leave a Reply

Your email address will not be published. Required fields are marked *