Locking function for ERC20

Hi everyone,
I have code for the ERC20 token which has freeze, unfreeze, lockUser & unlockUser functions. I want is:

  1. When I lock someone he will be automatically unlocked after x days or,
  2. Scheduled release of locked tokens. For example, 2% each day released.

I want any of these included in my current contract or create a new one for me.
Below Is My Code:

    pragma solidity ^0.5.16;

// ----------------------------------------------------------------------------
// 'DexPortfolio' Token contract
//
// Symbol      : ****
// Name        : *****
// Total supply: *****
// Decimals    : 18
//
// ----------------------------------------------------------------------------


library SafeMath {

  function add(uint256 a, uint256 b) internal pure returns (uint256) {
    return add(a, b, "SafeMath: addition overflow");
  }


  function add(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
    uint256 c = a + b;
    require(c >= a, errorMessage);

    return c;
  }


  function sub(uint256 a, uint256 b) internal pure returns (uint256) {
    return sub(a, b, "SafeMath: subtraction overflow");
  }


  function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
    require(b <= a, errorMessage);
    uint256 c = a - b;

    return c;
  }


  function mul(uint256 a, uint256 b) internal pure returns (uint256) {

    if (a == 0) {
      return 0;
    }

    uint256 c = a * b;
    require(c / a == b, "SafeMath: multiplication overflow");

    return c;
  }

 
  function div(uint256 a, uint256 b) internal pure returns (uint256) {
    return div(a, b, "SafeMath: division by zero");
  }


  function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
    // Solidity only automatically asserts when dividing by 0
    require(b > 0, errorMessage);
    uint256 c = a / b;
    // assert(a == b * c + a % b); // There is no case in which this doesn't hold

    return c;
  }


  function mod(uint256 a, uint256 b) internal pure returns (uint256) {
    return mod(a, b, "SafeMath: modulo by zero");
  }


  function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
    require(b != 0, errorMessage);
    return a % b;
  }
}


contract Context {
  // Empty internal constructor, to prevent people from mistakenly deploying
  // an instance of this contract, which should be used via inheritance.
  constructor () internal { }

  function _msgSender() internal view returns (address payable) {
    return msg.sender;
  }

  function _msgData() internal view returns (bytes memory) {
    this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
    return msg.data;
  }
}



contract Ownable is Context {
  address private _owner;

  event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

  constructor () internal {
    address msgSender = _msgSender();
    _owner = msgSender;
    emit OwnershipTransferred(address(0), msgSender);
  }

  function owner() public view returns (address) {
    return _owner;
  }

  modifier onlyOwner() {
    require(_owner == _msgSender(), "Ownable: caller is not the owner");
    _;
  }

  function renounceOwnership() public onlyOwner {
    emit OwnershipTransferred(_owner, address(0));
    _owner = address(0);
  }

  function transferOwnership(address newOwner) public onlyOwner {
    _transferOwnership(newOwner);
  }

  function _transferOwnership(address newOwner) internal {
    require(newOwner != address(0), "Ownable: new owner is the zero address");
    emit OwnershipTransferred(_owner, newOwner);
    _owner = newOwner;
  }
}

interface BEP20Interface {

  function totalSupply() external view returns (uint256);

  function decimals() external view returns (uint8);

  function symbol() external view returns (string memory);

  function name() external view returns (string memory);

  function getOwner() external view returns (address);

  /**
   * @dev Returns the amount of tokens owned by `account`.
   */
  function balanceOf(address account) external view returns (uint256);
  
  function transfer(address recipient, uint256 amount) external returns (bool);

  function allowance(address _owner, address spender) external view returns (uint256);

  function approve(address spender, uint256 amount) external returns (bool);

  function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

  event Transfer(address indexed from, address indexed to, uint256 value);

  event Approval(address indexed owner, address indexed spender, uint256 value);
}

contract Tokenlock is Ownable {
    /// @notice Indicates if token is locked
    uint8 isLocked = 0;

    event Freezed();
    event UnFreezed();

    modifier validLock {
        require(isLocked == 0, "Token is locked");
        _;
    }
    
    function freeze() public onlyOwner {
        isLocked = 1;
        
        emit Freezed();
    }

    function unfreeze() public onlyOwner {
        isLocked = 0;
        
        emit UnFreezed();
    }
}

// ----------------------------------------------------------------------------
// Contract function to receive approval and execute function in one call
// ----------------------------------------------------------------------------
contract ApproveAndCallFallBack {
    function receiveApproval(address from, uint256 tokens, address token, bytes memory data) public;
}

// ----------------------------------------------------------------------------
// Limit users in blacklist
// ----------------------------------------------------------------------------
contract UserLock is Ownable {
    mapping(address => bool) blacklist;
        
    event LockUser(address indexed who);
    event UnlockUser(address indexed who);

    modifier permissionCheck {
        require(!blacklist[msg.sender], "Blocked user");
        _;
    }
    
    function lockUser(address who) public onlyOwner {
        blacklist[who] = true;
        
        emit LockUser(who);
    }

    function unlockUser(address who) public onlyOwner {
        blacklist[who] = false;
        
        emit UnlockUser(who);
    }
}

contract DEXP is BEP20Interface, Tokenlock, UserLock {
    using SafeMath for uint256;

    /// @notice Official record of token balances for each account
    mapping (address => uint256) private _balances;

    /// @notice Allowance amounts on behalf of others
    mapping (address => mapping (address => uint256)) private _allowances;

    uint256 private _totalSupply;

    uint8 private _decimals;
 
    string private _symbol;

    string private _name;

    event Transfer(address indexed from, address indexed to, uint256 amount);

    event Approval(address indexed owner, address indexed spender, uint256 amount);

    constructor(address account) public {
        _name = "*******";
        _symbol = "******";
        _decimals = 18;
        _totalSupply = 1000000e18;
        _balances[account] = _totalSupply;

        emit Transfer(address(0), account, _totalSupply);
    }

    function getOwner() external view returns (address) {
        return owner();
    }
 
    function decimals() external view returns (uint8) {
        return _decimals;
    }
 
    function symbol() external view returns (string memory) {
        return _symbol;
    }

    function name() external view returns (string memory) {
        return _name;
    }

    function totalSupply() external view returns (uint256) {
        return _totalSupply;
    }

    function balanceOf(address account) external view returns (uint256) {
        return _balances[account];
    }

    function transfer(address recipient, uint256 amount) external validLock permissionCheck returns (bool) {
        emit Transfer(_msgSender(), recipient, amount);
        return true;
    }

    function allowance(address owner, address spender) external view returns (uint256) {
        return _allowances[owner][spender];
    }

    function approve(address spender, uint256 amount) external validLock permissionCheck returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    function approveAndCall(address spender, uint256 amount, bytes memory data) public validLock permissionCheck returns (bool) {
        _approve(_msgSender(), spender, amount);
        ApproveAndCallFallBack(spender).receiveApproval(_msgSender(), amount, address(this), data);
        return true;
    }

    function transferFrom(address sender, address recipient, uint256 amount) external validLock permissionCheck returns (bool) {
        emit Transfer(sender, recipient, amount);
        address spender = _msgSender();
        uint256 spenderAllowance = _allowances[sender][spender];
        if (spenderAllowance != uint256(-1)) {
            _approve(sender, spender, spenderAllowance.sub(amount, "The transfer amount exceeds allowance"));
        }
        return true;
    }
 
    function increaseAllowance(address spender, uint256 addedValue) public validLock permissionCheck returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue, "The increased allowance overflows"));
        return true;
    }

    function decreaseAllowance(address spender, uint256 subtractedValue) public validLock permissionCheck returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "The decreased allowance below zero"));
        return true;
    }

    function burn(uint256 amount) public validLock permissionCheck returns (bool) {
        _burn(_msgSender(), amount);
        return true;
    }

    function _approve(address owner, address spender, uint256 amount) internal {
        require(owner != address(0), "Cannot approve from the zero address");
        require(spender != address(0), "Cannot approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    function _burn(address account, uint256 amount) internal {
        require(account != address(0), "Cannot burn from the zero address");

        _balances[account] = _balances[account].sub(amount, "The burn amount exceeds balance");
        _totalSupply = _totalSupply.sub(amount);
        emit Transfer(account, address(0), amount);

    }}
1 Like

Hi @Md_Sejabur_Rahat,

For Access Control you could look at: https://docs.openzeppelin.com/contracts/3.x/access-control#role-based-access-control

You could look at the discussion on Token Vesting: https://github.com/OpenZeppelin/openzeppelin-contracts/issues/1214

Depending on your use case, you could use TokenTimelock.

When creating token time locks or vesting you should consider prevention strategies for: Bypassing Smart Contract Timelocks .


I saw that you have asked Developer Wanted: Need a developer to do very simple modification on current codes - #3 by Md_Sejabur_Rahat