contract LockableToken is MintableToken {

    mapping (address => uint256) private _locked;

    event Locked(address indexed account, uint256 amount, address indexed by);
    event Unlocked(address indexed account, uint256 amount, address indexed by);

    /**
     * @dev prevent any transfer of locked tokens.
     */
    modifier canTransfer(address from, uint256 value) {
        if (_locked[from] > 0) {
            require(balanceOf(from).sub(value) >= _locked[from]);
        }
        _;
    }

    /**
     * @dev lock tokens of array of addresses.
     * Available only to the owner.
     * @param accounts array of addresses.
     * @param amounts array of amounts of tokens.
     */
    function lock(address[] calldata accounts, uint256[] calldata amounts) external onlyOwner {
        for (uint256 i = 0; i < accounts.length; i++) {
            _locked[accounts[i]] = _locked[accounts[i]].add(amounts[i]);
            emit Locked(accounts[i], amounts[i], msg.sender);
        }
    }

    /**
     * @dev unlock tokens of array of addresses.
     * Available only to the owner.
     * @param accounts array of addresses.
     * @param amounts array of amounts of tokens.
     */
    function unlock(address[] calldata accounts, uint256[] calldata amounts) external onlyOwner {
        for (uint256 i = 0; i < accounts.length; i++) {
            _locked[accounts[i]] = _locked[accounts[i]].sub(amounts[i]);
            emit Unlocked(accounts[i], amounts[i], msg.sender);
        }
    }

    /**
     * @dev amount of locked tokens of specific address.
     * @param account holder address.
     * @return amount of locked tokens.
     */
    function lockedOf(address account) external view returns(uint256) {
        return _locked[account];
    }

    /**
     * @dev modified internal transfer function that prevents any transfer of locked tokens.
     * @param from address The address which you want to send tokens from.
     * @param to The address to transfer to.
     * @param value The amount to be transferred.
     */
    function _transfer(address from, address to, uint256 value) internal canTransfer(from, value) {
        super._transfer(from, to, value);
    }

}
/**
 * @title LockableToken
 */
function lock(address[] calldata accounts, uint256[] calldata amounts) external onlyOwner {
    for (uint256 i = 0; i < accounts.length; i++) {
        _locked[accounts[i]] = _locked[accounts[i]].add(amounts[i]);
        emit Locked(accounts[i], amounts[i], msg.sender);
    }
}

/**
 * @dev lock tokens of array of addresses.
 * Available only to the owner.
 * @param accounts array of addresses.
 * @param amounts array of amounts of tokens.
 */