Open In App

Solidity – Function Modifiers

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.

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. 

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 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:

 

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 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”.

 

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 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 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:




//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:

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)
   }
}


Article Tags :