6

I've heard arguments both for and against Solidity modifiers.

On the one hand, they make the code very readable, and the intents behind the calls are very clear. On the other, they increase the overall contract size, as the function code is actually inserted inline in place of the _ keyword (as opposed to just calling the function code). Furthermore, since the code is inlined, both the function and the modifier share the same restricted variable stack, which can lead to a Stack Too Deep error if more than a combined total of 16 variables are used.

What do you guys think? Are you with or against the use of modifiers in your code?

1
  • 1
    It's syntactic sugar at the end of the day. Doesn't really make a difference if you use it or not. Do what's best for readability. There will not be any runtime impact. Commented Feb 22, 2019 at 22:02

3 Answers 3

4

I often find I want a software client to be able to check but I also want a modifier for readability, so it often ends up like this:

modifier onlyIfAllowed() {
  require(isAllowed(args));
  _;
}

function isAllowed() public view returns(bool allowed) {
  allowed = ...
}

function safer() public onlyIfAllowed ... 

Of course, it would also be fine to do that in-line.

function inline() public {
  require(isAllowed());
  // carry on

Ultimately, it is a matter of personal preference. I find it more readable to go like this:

function tricky() public onlyOwner onlyIfAllowed onlySomethingElse { ...

... so the actual purpose of the function doesn't get mixed up with repetitive steps. It's more DRY, in my opinion. Not everyone agrees. The Vyper team, for example, consider modifiers an anti-feature that obscures important logic that they feel should be in-line.

Hope it helps.

1
  • 4
    Here is one convention: use modifiers only for state-verification and never for input-verification. I don't necessarily agree with it, but I know that some people do. My approach is to use modifiers only when it enhances readability, since modifiers have no other impact whatsoever (in particularly, runtime impact). My thumb-rule for enhanced readability is when the overall code size in text becomes smaller (i.e., when the number of usages "justifies" the modifier implementation). Commented Feb 23, 2019 at 8:25
3

Since modifiers don't increase overall gas cost, plus they improve code readability, I prefer to use them. It's a really cool and useful solidity feature.

1
  • 3
    Can you share a reference to your statement about gas costs? Commented Apr 3, 2022 at 10:35
0

I am not sure about doing mutation in modifier tho. The following case for example.

modifier updateReward(address account) {
    rewardPerTokenStored = rewardPerToken();
    lastUpdateTime = block.timestamp;

    rewards[account] = earned(account);
    userRewardPerTokenPaid[account] = rewardPerTokenStored;
    _;
}

function stake(uint _amount) external updateReward(msg.sender) {
    _totalSupply += _amount;
    _balances[msg.sender] += _amount;
    stakingToken.transferFrom(msg.sender, address(this), _amount);
}

function withdraw(uint _amount) external updateReward(msg.sender) {
    _totalSupply -= _amount;
    _balances[msg.sender] -= _amount;
    stakingToken.transfer(msg.sender, _amount);
}

function getReward() external updateReward(msg.sender) {
    uint reward = rewards[msg.sender];
    rewards[msg.sender] = 0;
    rewardsToken.transfer(msg.sender, reward);
}
1
  • You can do "process amortization" with in-line functions or modifiers. It can be useful for housekeeping, garbage collection and other valid use-cases. It has become more difficult to implement Nick Johnson's example in later versions of solidity because you can't attach a mutating modifier to a view function So, valid pattern but tougher implementation. weka.medium.com/… Commented May 18, 2022 at 16:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.