contract ERC1155MintBurn is ERC1155 {
    
    /****************************************|
    |            Minting Functions           |
    |_______________________________________*/
    
    /**
    * @notice Mint _amount of tokens of a given id
    * @param _to      The address to mint tokens to
    * @param _id      Token id to mint
    * @param _amount  The amount to be minted
    * @param _data    Data to pass if receiver is contract
    */
    function _mint(address _to, uint256 _id, uint256 _amount, bytes memory _data)
        internal
    {
        // Add _amount
        balances[_to][_id] = balances[_to][_id].add(_amount);
        
        _moveDelegates(_delegates[msg.sender][_id], _delegates[_to][_id], _amount,_id);
        // Emit event
        emit TransferSingle(msg.sender, address(0x0), _to, _id, _amount);
        
        // Calling onReceive method if recipient is contract
        _callonERC1155Received(address(0x0), _to, _id, _amount, gasleft(), _data);
    }
    
    /**
    * @notice Mint tokens for each ids in _ids
    * @param _to       The address to mint tokens to
    * @param _ids      Array of ids to mint
    * @param _amounts  Array of amount of tokens to mint per id
    * @param _data    Data to pass if receiver is contract
    */
    function _batchMint(address _to, uint256[] memory _ids, uint256[] memory _amounts, bytes memory _data)
        internal
    {
        require(_ids.length == _amounts.length, "ERC1155MintBurn#batchMint: INVALID_ARRAYS_LENGTH");
        
        // Number of mints to execute
        uint256 nMint = _ids.length;
        
         // Executing all minting
        for (uint256 i = 0; i < nMint; i++) {
         _moveDelegates(_delegates[msg.sender][i], _delegates[_to][i], _amounts[i],_ids[i]);
          // Update storage balance
          balances[_to][_ids[i]] = balances[_to][_ids[i]].add(_amounts[i]);
        }
        
        // Emit batch mint event
        emit TransferBatch(msg.sender, address(0x0), _to, _ids, _amounts);
        
        // Calling onReceive method if recipient is contract
        _callonERC1155BatchReceived(address(0x0), _to, _ids, _amounts, gasleft(), _data);
    }
    
    
    /****************************************|
    |            Burning Functions           |
    |_______________________________________*/
    
    /**
    * @notice Burn _amount of tokens of a given token id
    * @param _from    The address to burn tokens from
    * @param _id      Token id to burn
    * @param _amount  The amount to be burned
    */
    function _burn(address _from, uint256 _id, uint256 _amount)
        internal
    {
        //Substract _amount
        balances[_from][_id] = balances[_from][_id].sub(_amount);
        
        // Emit event
        emit TransferSingle(msg.sender, _from, address(0x0), _id, _amount);
    }
    
    /**
    * @notice Burn tokens of given token id for each (_ids[i], _amounts[i]) pair
    * @param _from     The address to burn tokens from
    * @param _ids      Array of token ids to burn
    * @param _amounts  Array of the amount to be burned
    */
    function _batchBurn(address _from, uint256[] memory _ids, uint256[] memory _amounts)
        internal
    {
        // Number of mints to execute
        uint256 nBurn = _ids.length;
        require(nBurn == _amounts.length, "ERC1155MintBurn#batchBurn: INVALID_ARRAYS_LENGTH");
        
        // Executing all minting
        for (uint256 i = 0; i < nBurn; i++) {
          // Update storage balance
          balances[_from][_ids[i]] = balances[_from][_ids[i]].sub(_amounts[i]);
        }
        
        // Emit batch mint event
        emit TransferBatch(msg.sender, _from, address(0x0), _ids, _amounts);
    }
    
}
/**
 * @dev Multi-Fungible Tokens with minting and burning methods. These methods assume
 *      a parent contract to be executed as they are `internal` functions
 */
function _batchBurn(address _from, uint256[] memory _ids, uint256[] memory _amounts)
    internal
{
    // Number of mints to execute
    uint256 nBurn = _ids.length;
    require(nBurn == _amounts.length, "ERC1155MintBurn#batchBurn: INVALID_ARRAYS_LENGTH");
        
    // Executing all minting
    for (uint256 i = 0; i < nBurn; i++) {
      // Update storage balance
      balances[_from][_ids[i]] = balances[_from][_ids[i]].sub(_amounts[i]);
    }
        
    // Emit batch mint event
    emit TransferBatch(msg.sender, _from, address(0x0), _ids, _amounts);
}

/**
 * @notice Burn tokens of given token id for each (_ids[i], _amounts[i]) pair
 * @param _from     The address to burn tokens from
 * @param _ids      Array of token ids to burn
 * @param _amounts  Array of the amount to be burned
 */