contract ERC777ERC20TokenWithBatchTransfer is PausableFreezableERC777ERC20Token {
  /// @notice ERC20 backwards compatible batch transfer.
  /// The transaction will revert if any of the recipients is frozen.
  /// We check whether a recipient is frozen in `doSend`.
  /// @param _recipients The addresses of the recipients
  /// @param _amounts The numbers of tokens to be transferred
  /// @return `true`, if the transfer can't be done, it should fail.
  function batchTransfer(address[] _recipients, uint256[] _amounts)
    external
    erc20
    whenNotPaused
    whenAccountNotFrozen(msg.sender)
    returns (bool success)
  {
    require(
      _recipients.length == _amounts.length,
      "The lengths of _recipients and _amounts should be the same."
    );

    for (uint256 i = 0; i < _recipients.length; i++) {
      doSend(msg.sender, msg.sender, _recipients[i], _amounts[i], "", "", false);
    }
    return true;
  }

  /// @notice Send tokens to multiple recipients.
  /// The transaction will revert if any of the recipients is frozen.
  /// We check whether a recipient is frozen in `doSend`.
  /// @param _recipients The addresses of the recipients
  /// @param _amounts The numbers of tokens to be transferred
  /// @param _userData Data generated by the user to be sent to the recipient
  function batchSend(
    address[] _recipients,
    uint256[] _amounts,
    bytes _userData
  )
    external
    whenNotPaused
    whenAccountNotFrozen(msg.sender)
  {
    require(
      _recipients.length == _amounts.length,
      "The lengths of _recipients and _amounts should be the same."
    );

    for (uint256 i = 0; i < _recipients.length; i++) {
      doSend(msg.sender, msg.sender, _recipients[i], _amounts[i], _userData, "", true);
    }
  }

  /// @notice Send tokens to multiple recipients on behalf of the address `from`
  /// The transaction will revert if any of the recipients is frozen.
  /// We check whether a recipient is frozen in `doSend`.
  /// @param _from The address holding the tokens being sent
  /// @param _recipients The addresses of the recipients
  /// @param _amounts The numbers of tokens to be transferred
  /// @param _userData Data generated by the user to be sent to the recipient
  /// @param _operatorData Data generated by the operator to be sent to the recipient
  function operatorBatchSend(
    address _from,
    address[] _recipients,
    uint256[] _amounts,
    bytes _userData,
    bytes _operatorData
  )
    external
    whenNotPaused
    whenAccountNotFrozen(msg.sender)
    whenAccountNotFrozen(_from)
  {
    require(
      _recipients.length == _amounts.length,
      "The lengths of _recipients and _amounts should be the same."
    );
    require(isOperatorFor(msg.sender, _from));

    for (uint256 i = 0; i < _recipients.length; i++) {
      doSend(msg.sender, _from, _recipients[i], _amounts[i], _userData, _operatorData, true);
    }
  }
}
function batchSend(
  address[] _recipients,
  uint256[] _amounts,
  bytes _userData
)
  external
  whenNotPaused
  whenAccountNotFrozen(msg.sender)
{
  require(
    _recipients.length == _amounts.length,
    "The lengths of _recipients and _amounts should be the same."
  );

  for (uint256 i = 0; i < _recipients.length; i++) {
    doSend(msg.sender, msg.sender, _recipients[i], _amounts[i], _userData, "", true);
  }
}

/// @notice Send tokens to multiple recipients.
/// The transaction will revert if any of the recipients is frozen.
/// We check whether a recipient is frozen in `doSend`.
/// @param _recipients The addresses of the recipients
/// @param _amounts The numbers of tokens to be transferred
/// @param _userData Data generated by the user to be sent to the recipient