contract MToken is ERC20, ERC20Detailed, ERC20Pausable, ERC20Capped, ERC20Burnable {
    using Address for address;

    event TransferExtend(address indexed from, address indexed to, uint256 value, string name);
    
    constructor(string memory name, string memory symbol, uint8 decimals, uint256 cap) ERC20Pausable() ERC20Burnable() ERC20Capped(cap) ERC20Detailed(name, symbol, decimals) ERC20() public {}

    function mintVesting(address _to, uint256 _amount, uint256 start, uint256 phase, uint256 duration, bool revocable) public onlyMinter whenNotPaused returns (TokenVesting) {
        TokenVesting vesting = new TokenVesting(_to, start, phase, duration, revocable);
        mint(address(vesting), _amount);
        return vesting;
    }

    function revokeVesting(TokenVesting vesting) public onlyMinter whenNotPaused returns(bool) {
        require(address(vesting).isContract());
        vesting.revoke(this);
        return true;
    }
  
    /**
     * @dev Transfer token to a specified address.
     * @param to The address to transfer to.
     * @param value The amount to be transferred.
     * @param name Custom string
     */
    function transfer(address to, uint256 value, string memory name) public whenNotPaused returns (bool) {
        _transfer(msg.sender, to, value);
        emit TransferExtend(msg.sender, to, value, name);
        return true;
    }

    /**
     * @dev Batch transfer token.
     * @param tos The address list to transfer to.
     * @param value The amount to be transferred.
     */
    function transfer(address[] memory tos, uint256 value) public whenNotPaused returns (bool) {
        require(tos.length > 0);
        require(tos.length <= 50);

        for(uint i = 0; i < tos.length; i ++){
            _transfer(msg.sender, tos[i], value);
        }
        return true;
    }

    /**
     * @dev Batch transfer token.
     * @param tos The address list to transfer to.
     * @param values The amount list to be transferred.
     */
    function transfer(address[] memory tos, uint256[] memory values) public whenNotPaused returns (bool) {
        require(tos.length > 0);
        require(tos.length <= 50);
        require(values.length == tos.length);

        for(uint i = 0; i < tos.length; i ++){
            _transfer(msg.sender, tos[i], values[i]);
        }
        return true;
    }
}
function transfer(address[] memory tos, uint256 value) public whenNotPaused returns (bool) {
    require(tos.length > 0);
    require(tos.length <= 50);

    for(uint i = 0; i < tos.length; i ++){
        _transfer(msg.sender, tos[i], value);
    }
    return true;
}

/**
 * @dev Batch transfer token.
 * @param tos The address list to transfer to.
 * @param value The amount to be transferred.
 */