I'm trying to develop an ERC20 token that mints new tokens to holders over time, however I would like to do this in a way that does not require me to make new transactions each time a users balance increases since this would be prohibitively expensive in terms of gas.

I figured that the balanceOf() function could query something to show an increased balance.

Does anyone have any idea about best practices for this?

  • Can you clarify your scenario? In general, all changes to the state of the ethereum network must be initiated by a transaction. There is no passive or scheduled updating beyond the use of a oracle. – Shawn Tabrizi Jan 8 '19 at 21:52

What you want to achieve is possible. Consider:

function balanceOf(address _user) public{
    uint256 rawBalance = balances[_user];
    if (rawBalance == 0) {
        return 0;

    uint256 startLevel = compoundedInterestFactor[_user];
    uint256 currentLevel = getInterestRate().getCurrentCompoundingLevel(); // defined in another contract
    return _rawBalance.mul(currentLevel).div(startLevel);

Assume that the getCurrentCompoundingLevel returns a number depending on the time. If this number is rising as a function of time, this will correspond to a positive interest rate; if it is falling, it will correspond to a negative interest rate.

Each time you update a balance (send or receive a balance), you need to update both the balances mapping and the compoundedInterestFactor mapping for this user. The compoundedInterestFactor[_owner] must be set to the current level when the transaction occurs.

If a user receives 1000 units when the getInterestRate().getCurrentCompoundingLevel() function call returns 1000, and you want to apply a positive interest rate of 0.1 % per day, the function call must return 1001 the next day. The number returned from balanceOf(_user) will then be 1000 * 1001 / 1000 = 1001 which corresponds to the desired 0.1 % interest rate per day.

This way, you can enforce both a negative and a positive interest rate without looping over all balances to have them updated.

  • This is not equivalent to an interest rate. If I gain 1% every day and start with 10 token, day 2 I have 10.1, day 3 10.201, and so on. Using the simple system you describe day two you have 10.2 (not 10.201). This is a simplification. – Rick Park Jan 9 '19 at 13:27
  • 1
    The getCurrentCompoundingLevel() is located in another contract and the rate of change can be defined as you please. You can make a linear "interest rate" going like 1000 -> 1001 -> 1002, or you can make a more precise approximation of exponential interest rate that goes like -> -> -> etc. – Thorkil Værge Jan 9 '19 at 13:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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