How to Write Clean, Elegant Solidity Code Using Function Modifiers

One of the most interesting features in Solidity are function modifiers. When added to a function body they extend it, allowing us to abstract parts of our code and write functions with fewer conditionals checks intertwined with state changes.

Creating a function modifier

The syntax looks similar to declaring a function, except it uses the modifierkeyword. The underscore on indicates how the original function is changed:

modifier assertValueIsOne(uint value) {
  assert(value == 1);
  _; // original function goes at this point
}

function doSomething(uint value)
  assertValueIsOne(value)
{

}

Use cases

Checking for invariants or conditions using require, revert (throw is deprecated, see more here) or assert accordingly:

// For parameterless modifiers, we can omit parenthesis
modifier isAllowed { 
  assert(msg.sender == owner); // contract state
  _;
}

modifier isValidAddress(address target) {
  require(target != 0x0);
  _;
}

modifier isValueBiggerThanZero(uint value) {
  require(value > 0);
  _;
}

function isOwner(address target) constant returns (bool) {
  return target == owner;
}

function simpleFunction(address target)
  isValidAddress(target)
  isValueBiggerThanZero(msg.value)
  isAllowed // omitted parenthesis for parameterless modifiers
  payable
{
    // do something
}
Please note that modifiers are applied to the original function in the order they are presented on the function declaration, i.e: isValidAddress, isValueBiggerThanZero, isAllowed and then payable.

Checking for msg.sender permissions:

modifier isOwner {
  assert(owner == msg.sender);
  _;
}

function finalize()
  isOwner
{
  finalized = true;
}

Raising events before or after a function is called:

event StartEvent();
event FinishEvent();

modifier logEvents {
  StartEvent();
  _;
  FinishEvent();
}

function toggle () 
  logEvents
{
  ...
}

Conclusion

Before formal verification or code coverage, clean code should be the first line of defense. Otherwise, logical flaws and vulnerabilities will have far more places to hide and go unnoticed to the eyes of a reviewer.

It might take a few iterations to achieve and using modifiers won’t magically make your code legible. But when used with care, they become a powerful tool to tame complexity and leverage reusability, making your code cleaner and safer.


Thiago Delgado is a software developer who loves Solidity, JavaScript, and open-source. Based at São Paulo, Brazil.

Fell in love at first sight with Colony and Ethereum, since then, left his cubicle behind and never looked back.