contract Issuance is
    ERC20,
    RebalancingSetState
{
    using SafeMath for uint256;
    using CommonMath for uint256;

    /* ============ Internal Functions ============ */

    /*
     * Validate call to mint new Rebalancing Set Token
     *
     *  - Make sure caller is Core
     *  - Make sure state is not Rebalance or Drawdown
     */
    function validateMint()
        internal
        view
    {
        validateCallerIsCore();

        validateRebalanceStateIs(RebalancingLibrary.State.Default);
    }

    /*
     * Validate call to burn Rebalancing Set Token
     *
     *  - Make sure state is not Rebalance or Drawdown
     *  - Make sure sender is module when in drawdown, core otherwise
     */
    function validateBurn()
        internal
        view
    {
        validateRebalanceStateIsNot(RebalancingLibrary.State.Rebalance);

        if (rebalanceState == RebalancingLibrary.State.Drawdown) {
            // In Drawdown Sets can only be burned as part of the withdrawal process
            validateCallerIsModule();
        } else {
            // When in non-Rebalance or Drawdown state, check that function caller is Core
            // so that Sets can be redeemed
            validateCallerIsCore();
        }
    }
    /*
     * Calculates entry fees and mints the feeRecipient a portion of the issue quantity.
     *
     * @param  _quantity              The number of rebalancing SetTokens the issuer mints
     * @return issueQuantityNetOfFees Quantity of rebalancing SetToken to mint issuer net of fees
     */
    function handleEntryFees(
        uint256 _quantity
    )
        internal
        returns(uint256)
    {
        // The entryFee is a scaled decimal figure by 10e18. We multiply the fee by the quantity
        // Then descale by 10e18
        uint256 fee = _quantity.mul(entryFee).deScale();

        if (fee > 0) {
            ERC20._mint(feeRecipient, fee);

            emit EntryFeePaid(feeRecipient, fee);
        }

        // Return the issue quantity less fees
        return _quantity.sub(fee);
    }
}
/**
 * @title Issuance
 * @author Set Protocol
 *
 * Default implementation of Rebalancing Set Token propose function
 */
function validateBurn()
    internal
    view
{
    validateRebalanceStateIsNot(RebalancingLibrary.State.Rebalance);

    if (rebalanceState == RebalancingLibrary.State.Drawdown) {
        // In Drawdown Sets can only be burned as part of the withdrawal process
        validateCallerIsModule();
    } else {
        // When in non-Rebalance or Drawdown state, check that function caller is Core
        // so that Sets can be redeemed
        validateCallerIsCore();
    }
}

/*
 * Validate call to burn Rebalancing Set Token
 *
 *  - Make sure state is not Rebalance or Drawdown
 *  - Make sure sender is module when in drawdown, core otherwise
 */