[Ethereum] What are function modifiers

contract-designcontract-developmentsolidity

I am learning solidity. I came across the concept of function modifiers. I am unable to understand it.

Best Answer

Modifiers are compile-time source code roll-ups. Functions can be "modified" by including the named modifier in the function declaration.

The _; line is mandatory. It's a merge wildcard that indicates where "the rest" of the function should go. For example, as @oktapdia suggested,

function test() public onlyOwner { ...

merges the function source with the modifier code at the _;

It is possible to place the _; at the beginning, in the middle or at the end of the modifier code. In practice, especially until you understand it really well, I would suggest the safest usage pattern is to use modifiers for consistent validation checks and only use the pattern with _; at the end. In other words, use modifiers to check some things up front and then carry on.

You can use modifiers in conjunction with getter functions. Here is a contrived example to show how you might use them together to keep code organized while you make the state discoverable to clients and ensure potentially complex logic is consistently applied.

modifier onlyIfOkayAndAuthorized {
  require(isOkay()); 
  require(isAuthorized(msg.sender));
  _;
}

// Let's say we have multiple concerns to mix and match

function isOkay() public view returns(bool isIndeed) {
  // return a check result
  return true;
}

function isAuthorized(address user) public view returns(bool isIndeed) {
  // return a check result
  return true;
}

return true are just placeholders for more meaningful results.

The idea is clients, other contracts, and other internal functions can use the getter functions to fetch/check the individual concerns (if they want to). Functions that should be guarded by a certain combination of concerns can use the modifier so the logic of it all (and your intent) remains very clear to reviewers.

So, you can have several functions like above, and they may have some tricky steps. Hopefully, they can be understood as individual concerns. Then, when used in combination, you can reduce repetition and improve readability with a modifier.

function sensitive() public onlyIfOkayAndAuthorized returns(bool success) {...

In case it isn't clear, you could accomplish something quite similar if instead of a modifier you made a third function to work with the combination and then included a require() in each function that needs it.

A function like:

function isOkayAndIsAuthorized(address user) public view returns(bool isIndeed) {
  require(isOkay());
  require(isAuthorized(user));
  returnt true;
}

Then use it like:

function sensitive() public returns(bool success) {
  require(isOkayAndIsAuthorized(msg.sender));
  // carry on
}

The security/validation concern is part of the function, and although this will work, it is arguably less readable than a modifier and the intent may be less clear.

Hope it helps.

Related Topic