0

I am creating a contract that mints 'x' tokens per block and drops 20% after 'n' blocks. Also these tokens get distributed to the participants of the network. Say Bob and Jen are the only two in the network and Bob joined 3 blocks before Jen then Jen would get rewarded for the blocks that she was in the network for. My main issue is making sure the correct amount of tokens are being minted and correctly rewarded. Also the trigger function in the code below is where the magic happens but is there a way to do this without updated the state of the contract? Anyways I am having trouble testing it in the Ropsten test net from remix and was wondering if anyone has any ideas as to how to approach this? Also is there a way to say have the trigger function be automatically called every say 'z' amount of time after deployment to ensure the tokens are constantly being minted or something along those lines?

Here is my contract so far-

pragma solidity ^0.5.2;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v2.5.0/contracts/token/ERC20/ERC20Mintable.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v2.5.0/contracts/token/ERC20/ERC20Detailed.sol";

// Contract summary - A mintable token rewards interface that mints ‘n’ tokens per block which are distributed equally among the ‘m’ participants decreasing the total minted tokens over time

contract HoneyTest is ERC20Mintable, ERC20Detailed {
    
    using SafeMath for uint256;
    
    uint256 public roundMask; // Cumulative snapshot of TPP(tokens per person) over time for token contract. Rewards = roundMask - participantMask
    uint256 public lastMintedBlockNumber; // The block number on which last ‘n’ tokens were minted
    uint256 public totalParticipants = 0; // Total participants in network 
    uint256 public tokensPerBlock; // The amount of tokens that will be released per block
    uint256 public initalTokenPB; // Initial tokens minted per block
    uint256 public blockFreezeInterval; // The number of blocks that need to pass until the next mint. E.g. if set to 50 and ‘n’ tokens were minted at block ‘b’, the next ‘n’ tokens won’t be minted until ‘b + 50’ blocks have passed
    uint256 public initialTime = 0; // Initial time counter for block minting intervals
    uint256 private initialBlock = block.number; // Initial time of contract deployment
    address public tokencontractAddress = address(this);
    mapping(address => uint256) public participantMask;
    
    /**
     * constructor, initializes variables.
     *  _tokensPerBlock - The amount of token that will be released per block, entered in wei format (E.g. 1000000000000000000)
     *  _blockFreezeInterval -The amount of blocks that need to pass (E.g. 1, 10, 100) before more tokens are brought into the ecosystem.
     */
     constructor(uint256 initialSupply, uint256 _tokensPerBlock, uint256 _blockFreezeInterval) public ERC20Detailed("HoneyTest", "HON", 18){ 
        lastMintedBlockNumber = block.number;
        tokensPerBlock = _tokensPerBlock;
        blockFreezeInterval = _blockFreezeInterval;
        initalTokenPB = _tokensPerBlock;
        _mint(msg.sender, initialSupply);
       
    }
    
    modifier isAuthorized(){  // Check if msg.sender is whitelisted as a minter
        require(isMinter(msg.sender));
        _;
    }
    
    /**
     * Function that adds participants to the network
     * _minter - The address that will mint the tokens
     * returns bool to indicate if the operation was successful
     */
    
    function addMinters(address _minter) external returns (bool) {
        _addMinter(_minter);
        totalParticipants = totalParticipants.add(1);
        updateParticipantMask(_minter);
        return true;
    }
    
    /**
     * Function that removes participants from network
     * _minter - address that will be unable to mint tokens
     * Returns bool to indicate if operation was successful
     */
     
    function removeMinters(address _minter) external returns (bool) {
        totalParticipants = totalParticipants.sub(1);
        _removeMinter(_minter);
        return true;
    }
    
    /**
     * Function that add new tokens to the network
     * returns bool to indicate if it was successful
     */
    function trigger() external isAuthorized returns (bool) {
        uint256 bp = 8000; // bp = 8000 = 20% reduction of minted tokens
        if(totalSupply() < 1000000000){
        /**
         * now - initialNow = total time passed since deployment
         * initialTime = tracks start and endpoints for alloted time 
         */
            if(block.number - initialBlock  >= initialBlock + 90 && block.number - initialBlock < initialBlock + 180  && tokensPerBlock == initalTokenPB){
                tokensPerBlock = initalTokenPB * bp / 10000;
            }
            else if(block.number - initialBlock  >= initialBlock + 180){
                initalTokenPB = tokensPerBlock;
                initialBlock = initialBlock + 180 ;
            }
            bool res = readyToMint();
            if(res == false) {
                return false;
            }
            else {
                mintTokens();
                return true;
            }
            
        }
    }
    
    
    /**
     * Function to withdraw rewarded tokens by participants
     * returns bool of successful
     */
    function withdraw() external isAuthorized returns(bool){
        
        uint256 amount = calculateRewards();
        require(amount > 0);
        ERC20(tokencontractAddress).transfer(msg.sender, amount);
    }
    
    /**
     * Function to check to see if tokens are ready to be minted 
     * returns bool if successful
     */
    function readyToMint() public view returns(bool) {
        uint256 currentBlockNumber = block.number;
        uint256 lastBlockNumber = lastMintedBlockNumber;
        if(currentBlockNumber > lastBlockNumber + blockFreezeInterval){
            return true;
        }
        else {
            return false;
        }
    }
    /**
     * Function to calc the current rewards for a participant 
     * returns uint wiht the reward amount
     */
     
    function calculateRewards() private returns (uint256) {
        uint256 playerMask = participantMask[msg.sender];
        uint256 rewards = roundMask.sub(playerMask); // Rewards for msg.sender roundMask - participantMask
        updateParticipantMask(msg.sender);
        return rewards;
    }
    
    /**
     * Function to mint tokens into economy
     * returns bool if successful
     */
     function mintTokens() private returns(bool) {
         uint256 currentBlockNumber = block.number;
         uint256 tokenReleaseAmount = (currentBlockNumber.sub(lastMintedBlockNumber)).mul(tokensPerBlock);
         lastMintedBlockNumber = currentBlockNumber;
         mint(tokencontractAddress, tokenReleaseAmount);
         calculateTPP(tokenReleaseAmount);
         return true;
     }
     /**
      * Function to calc TPP (token amount per person)
      * returns bool if successful
      */
     function calculateTPP(uint256 tokens) private returns(bool) {
         uint256 tpp = tokens.div(totalParticipants);
         updateRoundMask(tpp);
         return true;
     }
      /**
        * @dev Function to update round mask. 
        * @return A boolean that indicates if the operation was successful.
        */
     function updateRoundMask(uint256 tpp) private returns(bool){
        roundMask = roundMask.add(tpp);
        return true;
     }
     
     /**
      * function to update participant mask (store previous mask)
      * returns Bool is successful
      */
      function updateParticipantMask(address participant) private returns(bool){
          uint256 previousRoundMask = roundMask;
          participantMask[participant] = previousRoundMask;
          return true;
      }
    
    
    
    
    
    
    
    /**
    
    function _mintPerBlock() internal { // Mints n tokens per block
        _mint(block.coinbase, 6944.44);
    }
    
    function _transfer(address from, address to, uint256 value) internal {
        _mintPerBlock();
        super._transfer(from, to, value);
        
    }
    */
    
    
    
}
0

What you need to understand is that there is no such thing as a scheduled task in a contract; it must be invoked externally.

2
  • So if after say block 10 i want to reduce the minted # of tokens by 20% but i ran the trigger function at block 5 and dont run the trigger function again until block 15 how would i make sure the 5 blocks before block ten still mint the correct amount of tokens and the blocks after mint them 20% less per block? Could there be a front end application or script that executes the function periodically? Or could i do something like If(block.number != currentBlockNum){ trigger(); currenBlockNum = block.number;} Will that continually update the contract?
    – Max Mender
    Aug 11 '21 at 15:25
  • You can, of course, use the function to determine the current number of blocks, or the number of blocks since the last call, to execute your logic. You can also use timers to call functions from outside, but external calls are not accurate, so don't rely on them!The logic that makes the contract work should be in the contract, such as the conditions.Also consider security, otherwise someone else will call your contract. I can only say so much, hope to help you, God bless you!😎
    – zmy
    Aug 12 '21 at 2:43

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.