In the past it was possible to use state-changing modifiers on view and pure functions. It was very useful when used properly because one could work out what the state would be and will be when the same modifier is applied to a state-changing function.

A little deeper dive on the idea of amortized work using the pattern: https://weka.medium.com/dividend-bearing-tokens-on-ethereum-42d01c710657

However, now it is more complicated to get the same effect.

This little contrived example shows the problem.

pragma solidity 0.8.14;

contract Modifiers {

    uint balance;
    uint refreshTime;
    uint rate = 2;
    uint PRECISION = 1e18;

    modifier accrueInterest {
        uint duration = block.timestamp - refreshTime;
        uint interest = duration * rate / PRECISION;
        balance += interest;
        refreshTime = block.timestamp;

    constructor() {
        refreshTime = block.timestamp;

    function balanceOf() public view accrueInterest returns (uint) {
        return balance;

It's not happy:

from solidity:
TypeError: Function cannot be declared as view because this expression (potentially) modifies the state.
  --> Modifiers.sol:22:38:
22 |     function balanceOf() public view accrueInterest returns (uint) {
   |                                      ^^^^^^^^^^^^^^

Is there a way to silence that error when impermanent state changes are the goal? One can silence underflow/overflow errors with an ignore block, so I'm wondering if there is a similar method for this case.

I'm aware that feasible work-arounds exist. Just wondering if there's a better way.



Your Answer

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

Browse other questions tagged or ask your own question.