0

I'm trying to create a token that holders can earn some amount contantly by a certain rate. Don't want to depend on transactions to give tokens to holders. An idle contract must constantly do it.

Is there any way to do this without running out of gas ?

Just an example:

  • You buy 100 tokens and go sleep. The contract will reward you at 0.0001 token / hour

Yea I know I can't write anything to the constract storage without spend gas and fees so I can't see how I can do it.

1 Answer 1

1

An approach is to store the time of the last transaction and when needed calculate the balance based on the time elapsed. Those changes aren't stored in the contract until a transfer modifies the balance.

mapping(address => uint256) _balances;
// Last transaction's timestamp 
mapping(address => uint256) _lastBlock;


function balanceOf(address owner) public view returns (uint256) {
   uint256 balance = _balances[owner];
   if (balance > 0) {
       uint256 elapsed = block.timestamp - _lastBlock[owner];
       balance += rate * elapsed;
   }
   return balance;
}

function transfer(address recipient, uint256 amount) public returns (bool) {
   // Adjust balance
   uint256 balance = _balances[msg.sender];
   if (balance > 0) {
       uint256 elapsed = block.timestamp - _lastBlock[msg.sender];
       balance += rate * elapsed;
   }

   [..] // implement transfer


   // Update last transaction timestamp
   _lastBlock[msg.sender] = block.timestamp;
   _lastBlock[recipient] = block.timestamp;
}
5
  • So.... users that are not involved in the transaction are not updated? Can I do a "for" loop and update everyone?
    – Magno C
    May 23, 2021 at 17:34
  • I see the "Safemoon" contract and all your clones like "REAU (Viralata Finance)" updates all holder's balance constantly but I can't see how. The code is messy.
    – Magno C
    May 23, 2021 at 17:37
  • @MagnoC There's no need to update all accounts at once. Look at balanceOf it updates the balance with every block. The increase is made permanent when you transfer the tokens. I'm trying to answer the requirement to update the balance with time. Safemoon and others increment balances when a transfer is made. How Safemoon works is explained here ethereum.stackexchange.com/questions/98622/….
    – Ismael
    May 23, 2021 at 17:57
  • I understood this method you show will update just the balance of the user that trigger "transfer" for some reason. My question is: how to update balance of all holders (when you are asleeping you are not transfering). As I can see in Safemoon I need to stake tokens at some DEX (Uniswap) to earn and share this earned amount between holders. Am I correct?
    – Magno C
    May 23, 2021 at 19:07
  • 1
    @MagnoC It is not feasible to update balances of all token holders because it will be too expensive. One approach is to have a 'virtual' balance and recalculate when needed. Safemoon for example has r values, that are stored in the contract, and the public t values that are recomputed from the r values. Every transfer updates the rate between t and r, so for every account the public balance t will change even when r didn't change.
    – Ismael
    May 23, 2021 at 22:30

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.