contract GHTToken is ERC20, ERC20Detailed {
    mapping (address => uint256) private _lockAmount;
    
    address private multiSigWallet;
    
    /**
     * @dev Emitted when the user's balance is locked by a owner (`account`).
     */
    event LockAmount(address indexed account, uint256 lockAmount);
    
    /**
     * @dev Emitted when the user's balance is unlock by a owner (`account`).
     */
    event UnlockAmount(address indexed account);
    
    event FoundationWalletSet(address previous, address newFoundationAdress);
    
    constructor (string memory name, 
                string memory symbol, 
                uint8 decimals, 
                uint256 totalSupply, 
                address pauser, 
                address minter) public
        ERC20Detailed(name, symbol, decimals)
        Ownable()
        Pausable(pauser)
        Mintable(minter) {
            _mint(_msgSender(), totalSupply);
            multiSigWallet = address(0);
        }
    
    /**
     * @dev Set the user's balance locked amount.
     */
    function setLockAmount(address account, uint256 amount) public onlyOwner returns (bool) {
        _lock(account, amount);
        return true;
    }
    
    /**
     * @dev Increase the user's balance locked amount.
     */
    function increaseLockAmount(address account, uint256 addedAmount) public onlyOwner returns (bool) {
        _lock(account, _lockAmount[account].add(addedAmount));
        return true;
    }
    
    /**
     * @dev Decreas the user's balance locked amount.
     */
    function decreaseLockAmount(address account, uint256 subtractedAmount) public onlyOwner returns (bool) {
        _lock(account, _lockAmount[account].sub(subtractedAmount));
        return true;
    }
    
    /**
     * @dev Unlock user's balance.
     */
    function unlockAmount(address account) public onlyOwner returns (bool) {
        _lockAmount[account] = 0;
        emit UnlockAmount(account);
        return true;
    }
    
    /**
     * @dev Returns the lock amount of tokens owned by `account`.
     */
    function getLockAmount(address account) public view returns (uint256) {
        return _lockAmount[account];
    }
    
    /**
     * @dev Moves tokens `amount` from `sender` to `recipient`.
     *
     * This is internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(address sender, address recipient, uint256 amount) internal virtual override {
        super._transfer(sender, recipient, amount);
        
        require((balanceOf(sender).sub(getLockAmount(sender))) >= 0);
    }
        
    /**
     * @dev See {ERC20-_beforeTokenTransfer}.
     *
     * Requirements:
     *
     * - the contract must not be paused.
     */
    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {
        super._beforeTokenTransfer(from, to, amount);

        require(!paused(), "ERC20Pausable: token transfer while paused");
    }
    
    /**
     * @dev Set the user's balance locked amount.
     */
    function _lock(address account, uint256 amount) internal {
        _lockAmount[account] = amount;
        emit LockAmount(account, _lockAmount[account]);
    }
    
    /**
     * @dev Mints `amount` tokens to the foundation wallet.
     *
     * See {ERC20-_mint}.
     */
    function mint(uint256 amount) public virtual onlyMinter {
        _mint(multiSigWallet, amount);
    }
    
    /**
     * @dev Sets address of the foundation wallet.
     *
     */
    function setFoundationWallet(address _multiSigWallet) public onlyOwner {
        emit FoundationWalletSet(multiSigWallet, _multiSigWallet);
        multiSigWallet = _multiSigWallet;
    }
}
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {
    super._beforeTokenTransfer(from, to, amount);

    require(!paused(), "ERC20Pausable: token transfer while paused");
}

/**
 * @dev See {ERC20-_beforeTokenTransfer}.
 *
 * Requirements:
 *
 * - the contract must not be paused.
 */