Open In App

Solidity – Function Modifiers

Improve
Improve
Like Article
Like
Save
Share
Report

Function behavior can be changed using function modifiers. Function modifier can be used to automatically check the condition prior to executing the function. These can be created for many different use cases. Function modifier can be executed before or after the function executes its code.

  • The modifiers can be used when there is a need to verify the condition automatically before executing a particular function.
  • If the given condition is not satisfied, then the function will not get executed.

How to Create and Use Modifiers?

Function modifiers are created by defining them and invoking the same in the required function. 

Syntax:

modifier  modifier_name 
{
   // action to be taken
}

There are two variations of a function modifier: 

1. Function modifier with an argument:

modifier  modifier_name(unit arg)
{
   // action to be taken
}

2. Function modifier without argument:

modifier  modifier_name()
{
   // action to be taken
}

If the modifier does not have an argument then parentheses () can be omitted.

What is Merge Wildcard?

Consider the below function modifier:

modifier isAdmin
{
   require(msg.sender == admin);
   _;
}

The _; symbol is known as Merge Wildcard and this is replaced by the function definition during execution. 

  • In other words, after this wildcard has been used, the control is moved to the location where the appropriate function definition is located. 
  • This symbol is mandatory for all modifiers.
  • The modifier may contain this wildcard anywhere. 
  • When the wildcard is placed at the end of the modifier, the condition is verified and the appropriate function is executed if it is satisfied. 
  • When it is placed at the beginning, the appropriate function is executed first followed by the condition verification.

Modifiers without Argument

A modifier may not have arguments. If the modifier does not have an argument then parentheses () can be omitted.

Syntax:

modifier  modifier_name ( ) 
{
   // action to be taken
}

OR

modifier  modifier_name 
{
  // action to be taken
}

Here, the modifier is the keyword and modifier_name is the modifier name.

Below is the solidity program to demonstrate the modifier without an argument:

Solidity




// Solidity program to demonstrate
// modifier with argument
//SPDX-License-Identifier:GPL-3.0
pragma solidity >=0.4.22 <0.7.0;
contract modifierWithoutArg {
   address admin; 
  struct employee
  {
    uint emp_id;
    string emp_name;
    uint age;
   }
     
   constructor() public 
   {
     admin = msg.sender;
   }
      
    modifier isAdmin
    {
        require(admin == msg.sender);
        _;
    }
  employee e;
 function enterDetails (uint _empid, string memory _empname, 
                        uint _empage) public isAdmin {
   e.emp_id = _empid;
   e.emp_name = _empname;
   e.age = _empage;
 }
}


Output:

Modifier without argument

 

Explanation:

1. Address initialization: In the above code, constructor is used for initializing the address for admin. In Solidity language, the address of the contract creator will be saved in msg.sender. Hence, the address present in this variable is assigned to admin.

constructor() public 
 {
      admin = msg.sender;
 }

2. Modifier creation: The modifier named isAdmin is created using the following code. This modifier verifies whether the address of the person entering the detail is the address present in admin variable.

modifier isAdmin
{
   require(admin == msg.sender);
    _;
}

3. Function definition: Once the modifier is defined, the modifier is included in the function wherever the above constraint needs to be imposed. In this example, the function enterDetails includes the modifier isAdmin which enables the user to enter the employee details only if the entry is made from the admin address.

function enterDetails (uint _empid, string memory _empname, 
                                   uint _empage) public isAdmin {
  e.emp_id = _empid;
  e.emp_name = _empname;
  e.age = _empage;
}
 

Modifier with Arguments

Modifiers may accept an argument and it is included after the modifier name within parentheses (). 

Syntax:

modifier modifier_name(datatype arg_name)
{
   //action to be taken
}

Below is the solidity program to demonstrate function modifier with arguments:

Solidity




// Solidity program to demonstrate
// modifier with argument
//SPDX-License-Identifier:GPL-3.0
pragma solidity >=0.4.22 <0.7.0;
contract modifierWithArg {
      
  struct employee
  {
    uint emp_id;
    string emp_name;
    uint age;
   }
    
    modifier isExperienced(uint exp)
    {
        if(exp >= 5)
            _;
        else
            revert("Must have a minimum of 5 years of experience");
    }
  employee e;
 function enterDetails (uint _empid, string memory _empname, 
                        uint _empage) public isExperienced(7) {
   e.emp_id = _empid;
   e.emp_name = _empname;
   e.age = _empage;
 }
}


Output: Here, the user with a minimum of 5 years of experience is only allowed to make entry. This is ensured with the help of isExperienced modifier. Because the experience in the example is hard-coded as 7, the details can be entered otherwise for a value less than 5, a message will be displayed “Must have a minimum of 5 years of experience”.

Modifier with argument

 

Explanation:

1. Modifier creation:

modifier isExperienced(uint exp)
{
   if(exp >= 5)
       _;
   else
      revert(“Must have a minimum of 5 years of experience”);
}

The above code creates the modifier named isExperienced which takes the experience of the user as the argument. This modifier allows the function to execute only if the experience is >= 5. If the user has less than 5 years of experience then it prompts the message “Must have a minimum of 5 years of experience”.

2. Modifier invocation: The modifier can be invoked by passing the value for the experience.  In this example, as shown below, the experience is hard coded as 7 years. Hence the details will be recorded.

function enterDetails (uint _empid, string memory _empname, 
                                   uint _empage) public isExperienced(7) {
  e.emp_id = _empid;
  e.emp_name = _empname;
  e.age = _empage;
}

Multiple Modifiers to Function

Multiple modifiers may be present in a function, and each of these conditions must be met in order for the function to be successfully executed.  To verify whether only the administrator with 5 years of experience is editing, two modifiers namely isAdmin and isExperienced are introduced. The function enterDetails will execute only if the user has administrator authorization and has a minimum of 5 years of experience.

Syntax:

modifier modifier_name(datatype arg_name)
{
   // action to be taken
}

function func_name(arg1, arg2, …) public modifier1 modifier2 
{
   // function definition
}

Below is the solidity program to implement multiple modifiers to function:

Solidity




// Solidity program to demonstrate
// multiple modifier to function
//SPDX-License-Identifier:GPL-3.0
pragma solidity >=0.4.22 <0.7.0;
contract multiplemodifier {
  address admin; 
  struct employee
  {
    uint emp_id;
    string emp_name;
    uint age;
   }
     
   constructor() public 
   {
     admin = msg.sender;
   }
      
    modifier isAdmin
    {
        require(admin == msg.sender);
        _;
    }
    modifier isExperienced(uint exp)
    {
        if(exp>=5)
            _;
        else
            revert("Must have a minimum of 5 years of experience");
    }
  employee e;
 function enterDetails (uint _empid, string memory _empname, 
                        uint _empage) public isAdmin isExperienced(7) {
   e.emp_id = _empid;
   e.emp_name = _empname;
   e.age = _empage;
 }
}


Output:

 

Explanation: A function may include multiple modifiers. To impose multiple constraints on a function, the modifiers are invoked as shown below. 

function enterDetails (uint _empid, string memory _empname, 
                                   uint _empage) public isAdmin isExperienced(7) {
  e.emp_id = _empid;
  e.emp_name = _empname;
  e.age = _empage;
}

Thus, the user is allowed to make an entry only if the person is the administrator and has a minimum of 5 years of experience.

Modifier Overriding

Modifiers can be overridden in a similar way to how functions can be overridden. 

Syntax:

contract base{
   modifier overridingmod virtual{
   }
}

contract derived is base {
   modifier overridingmod override{
   }
}

As shown a modifier in the base class is overridden in the derived class with the help of the override keyword. Below is the solidity program to implement method overriding:

Solidity




// Solidity program to demonstrate
// modifier with argument
//SPDX-License-Identifier:GPL-3.0
pragma solidity >=0.4.22 <0.7.0;
contract modifierOverride {
  modifier isExperienced(uint exp) virtual {
    if(exp >= 5)
      _;
    else
      revert("Must have minimum 5 years of experience");
  }
}
contract modifierdest is  modifierOverride {
  struct employee
  {
    uint emp_id;
    string emp_name;
    uint age;
   }
   employee e;
   modifier isExperienced(uint exp) override {
     if(exp >= 5)
        _;
     else
        revert("Must have minimum 5 years of experience");
    }
    
 function enterDetails (uint _empid, string memory _empname, 
                        uint _empage) public isExperienced(7) {
   e.emp_id = _empid;
   e.emp_name = _empname;
   e.age = _empage;
 }
}


Output:

 

In modifier overriding, while deploying the contract we have to deploy the inherited contract. In this example, we must select and deploy modifierdest contract.

Modifier with enums

When an enum variable is declared globally, its value can be verified using a modifier.

Syntax:

enum variablename {inst1, inst2, inst3, …}

variablename v;

modifier modifiername(variablename _v){

require(v==_v);

_;

}

Below is the solidity program to implement enums:

Solidity




//SPDX-License-Identifier:GPL-3.0
pragma solidity >=0.4.22 <0.7.0;
contract modifierWithEnum {
  enum Status{Fresher, Trained, Experienced}
    struct employee
  {
    uint emp_id;
    string emp_name;
    Status s;
   }
   Status s1;
       modifier isValid(Status _entry)
    {
      require(s1==_entry);
      _;
    }
    
  employee e;
 function enterDetails (uint _eno, string memory _ename, Status _s) public isValid(_s)  {
   e.emp_id=_eno;
   e.emp_name=_ename;
   e.s=_s;
 }
}


Output:

Output enums

Modifier with enum

Modifier code examples

This section focuses on discussing a few applications of modifiers:

1. Data Validation: In this example, the input data is validated based on its type.

modifier triggerIfEqualToZero(uint _num)
{
   if(_num == 0) throw;
   _;
}

Similarly, the other type of data can also be verified.

2. Refund Ether send by accident: For every transaction made in the blockchain, some amount of Ether needs to be paid. Also, a facility is there for transferring some amount of Ether to other users. Sometimes, accidentally few transactions may take place. 

modifier refundEther {
   if(msg.value >0) throw;
   _;
}

3. Charge a fee: Modifiers can also be used for verifying whether the user has paid the required fees as shown below:

modifier payFee (uint _fee) {
  if(msg.value >= _fee) throw;
  _;

}

4. Send the change back: Suppose a user wants to send back the extra amount paid by a person, modifiers can be applied to it. The implementation for the same is given below:

modifier sendBackChange(unit _balance)
{
    _;
    if (msg.value > _balance)   
   {
      msg.sender.transfer(msg.value – _balance)
   }
}



Last Updated : 03 Nov, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads