user6051: This doesn't work
mkPolicy oref () ctx = traceIfFalse "UTxO not consumed"   hasUTxO           &&
                       traceIfFalse "wrong amount minted" checkMintedAmount
  where
    info :: TxInfo
    info = scriptContextTxInfo ctx

    hasUTxO :: Bool
    hasUTxO = any (\i -> txInInfoOutRef i == oref) $ txInfoInputs info

    checkMintedAmount :: Bool
    checkMintedAmount = case flattenValue (txInfoMint info) of
        [(_, tn, amt)]  -> tn == "" && amt == 1
        _               -> False

and throws
GHC Core to PLC plugin: E042:Error: Unsupported feature: Type constructor: GHC.Prim.Char#
Context: Compiling type: GHC.Prim.Char#
Context: Compiling data constructor type: GHC.Types.C#
Context: Compiling type: GHC.Types.Char
Context: Compiling type: GHC.Base.String
Context: Compiling type: GHC.Base.String
                         -> Data.ByteString.Internal.ByteString
Context: Compiling definition of: Plutus.V1.Ledger.Value.$fIsStringTokenName1
Context: Compiling expr: Plutus.V1.Ledger.Value.$fIsStringTokenName1
Context: Compiling expr: Plutus.V1.Ledger.Value.$fIsStringTokenName1
                           ((GHC.Types.[] @ GHC.Types.Char)
                            `cast` (Sym (Nth:2
                                             (((<GHC.Base.String>_R
                                                ->_R Sym (PlutusTx.Builtins.Internal.N:BuiltinByteString[0]) ; Sym (Plutus.V1.Ledger.Value.N:TokenName[0])) ; Sym (Data.String.N:IsString[0]) <Plutus.V1.Ledger.Value.TokenName>_N) ; Data.String.N:IsString[0] <Plutus.V1.Ledger.Value.TokenName>_N))
                                    :: GHC.Types.Coercible GHC.Base.String GHC.Base.String))
... (a lot of lines skipped here)
Context: Compiling definition of: Week05.Homework2.mkPolicy
Context: Compiling expr: Week05.Homework2.mkPolicy
Context: Compiling expr: Week05.Homework2.mkPolicy oref'_axTu
Context: Compiling expr: PlutusTx.Base.$
                           @ (() -> Plutus.V1.Ledger.Contexts.ScriptContext -> GHC.Types.Bool)
                           @ Ledger.Typed.Scripts.MonetaryPolicies.WrappedMintingPolicyType
                           (Ledger.Typed.Scripts.MonetaryPolicies.wrapMintingPolicy
                              @ () PlutusTx.IsData.Instances.$fUnsafeFromData())
                           (Week05.Homework2.mkPolicy oref'_axTu)
Context: Compiling expr: \ (oref'_axTu :: Plutus.V1.Ledger.Tx.TxOutRef) ->
                           PlutusTx.Base.$
                             @ (() -> Plutus.V1.Ledger.Contexts.ScriptContext -> GHC.Types.Bool)
                             @ Ledger.Typed.Scripts.MonetaryPolicies.WrappedMintingPolicyType
                             (Ledger.Typed.Scripts.MonetaryPolicies.wrapMintingPolicy
                                @ () PlutusTx.IsData.Instances.$fUnsafeFromData())
                             (Week05.Homework2.mkPolicy oref'_axTu)
Context: Compiling expr at "plutus-pioneer-program-week05-0.1.0.0-inplace:Week05.Homework2:(55,8)-(55,85)"

but this works
mkPolicy oref () ctx = traceIfFalse "UTxO not consumed"   hasUTxO           &&
                       traceIfFalse "wrong amount minted" checkMintedAmount
  where
    info :: TxInfo
    info = scriptContextTxInfo ctx

    emptyToken :: TokenName
    emptyToken = TokenName ""

    hasUTxO :: Bool
    hasUTxO = any (\i -> txInInfoOutRef i == oref) $ txInfoInputs info

    checkMintedAmount :: Bool
    checkMintedAmount = case flattenValue (txInfoMint info) of
        [(_, tn, amt)]  -> tn == emptyToken && amt == 1
        _               -> False

I assumed that {-# LANGUAGE OverloadedStrings   #-} would work as TokenName is just a newtype for PlutusTx.Builtins.Internal.BuiltinByteString. From the repl
Prelude Week05.Homework2> :t Plutus.V1.Ledger.Value.TokenName
Plutus.V1.Ledger.Value.TokenName
  :: PlutusTx.Builtins.Internal.BuiltinByteString
     -> Plutus.V1.Ledger.Value.TokenName
Prelude Week05.Homework2> :i Plutus.V1.Ledger.Value.TokenName
type Plutus.V1.Ledger.Value.TokenName :: *
newtype Plutus.V1.Ledger.Value.TokenName
  = Plutus.V1.Ledger.Value.TokenName {Plutus.V1.Ledger.Value.unTokenName :: PlutusTx.Builtins.Internal.BuiltinByteString}
    -- Defined in `Plutus.V1.Ledger.Value'
instance Eq Plutus.V1.Ledger.Value.TokenName
  -- Defined in `Plutus.V1.Ledger.Value'
instance Ord Plutus.V1.Ledger.Value.TokenName
  -- Defined in `Plutus.V1.Ledger.Value'
instance Show Plutus.V1.Ledger.Value.TokenName
  -- Defined in `Plutus.V1.Ledger.Value'


Edit #1
On reading this doc I realised that maybe TokenName is not an instance of IsString. I tried to implement it using:
instance IsString TokenName where
        fromString = unTokenName

but I got this error
src/Week05/Homework2.hs:32:10: error:
    Duplicate instance declarations:
      instance IsString TokenName
        -- Defined at src/Week05/Homework2.hs:32:10
      instance IsString TokenName -- Defined in `Plutus.V1.Ledger.Value'
   |
32 | instance IsString TokenName where
   |          ^^^^^^^^^^^^^^^^^^


Edit #2
The complete Homework file is here.

user6113: After digging into Plutus source, I think I've found why tn == "" crashes at runtime.
The problem might be that the instance of TokenName IsString doesn't use the INLINABLE pragma in the function fromString. Due to this, Plutus core crashes. (As a reminder, every function in order to compiles to Plutus core must have the INLINABLE pragma).
[source: Plutus.V1.Ledger.Value]
instance IsString TokenName where
    fromString = fromText . Text.pack


On other hand, for example traceIfFalse "UTxO not consumed" hasUTxO is resolved properly because the function fromString in IsString BuiltinString uses the INLINABLE mechanism.
[source: PlutusTx.Builtins.Class]
-- We can't put this in `Builtins.hs`, since that force `O0` deliberately, which prevents
-- the unfoldings from going in. So we just stick it here. Fiddly.
instance IsString BuiltinString where
    -- Try and make sure the dictionary selector goes away, it's simpler to match on
    -- the application of 'stringToBuiltinString'
    {-# INLINE fromString #-}
    -- See Note [noinline hack]
    fromString = Magic.noinline stringToBuiltinString

{-# INLINABLE stringToBuiltinString #-}
stringToBuiltinString :: Haskell.String -> BuiltinString
-- To explain why the obfuscatedId is here
-- See Note [noinline hack]
stringToBuiltinString str = obfuscatedId (BuiltinString $ pack str)


Why don't Plutus team use INLINABLE mechanism in the function fromString for TokenName? I don't know, it might be a bug.
EDIT 1
I've raised an issue on Plutus repo.
https://github.com/input-output-hk/plutus/issues/4404
EDIT 2
The issue is (see Plutus team's answer https://github.com/input-output-hk/plutus/issues/4404)

Unfortunately, due to the technical reasons plutus plugin doesn't
support OverloadedStrings with newtypes.

Notice the same thing happens with PubKeyHash (it's a newtype)

6051: <p>This doesn't work</p>
<pre><code>mkPolicy oref () ctx = traceIfFalse &quot;UTxO not consumed&quot;   hasUTxO           &amp;&amp;
                       traceIfFalse &quot;wrong amount minted&quot; checkMintedAmount
  where
    info :: TxInfo
    info = scriptContextTxInfo ctx

    hasUTxO :: Bool
    hasUTxO = any (\i -&gt; txInInfoOutRef i == oref) $ txInfoInputs info

    checkMintedAmount :: Bool
    checkMintedAmount = case flattenValue (txInfoMint info) of
        [(_, tn, amt)]  -&gt; tn == &quot;&quot; &amp;&amp; amt == 1
        _               -&gt; False
</code></pre>
<p>and throws</p>
<pre><code>GHC Core to PLC plugin: E042:Error: Unsupported feature: Type constructor: GHC.Prim.Char#
Context: Compiling type: GHC.Prim.Char#
Context: Compiling data constructor type: GHC.Types.C#
Context: Compiling type: GHC.Types.Char
Context: Compiling type: GHC.Base.String
Context: Compiling type: GHC.Base.String
                         -&gt; Data.ByteString.Internal.ByteString
Context: Compiling definition of: Plutus.V1.Ledger.Value.$fIsStringTokenName1
Context: Compiling expr: Plutus.V1.Ledger.Value.$fIsStringTokenName1
Context: Compiling expr: Plutus.V1.Ledger.Value.$fIsStringTokenName1
                           ((GHC.Types.[] @ GHC.Types.Char)
                            `cast` (Sym (Nth:2
                                             (((&lt;GHC.Base.String&gt;_R
                                                -&gt;_R Sym (PlutusTx.Builtins.Internal.N:BuiltinByteString[0]) ; Sym (Plutus.V1.Ledger.Value.N:TokenName[0])) ; Sym (Data.String.N:IsString[0]) &lt;Plutus.V1.Ledger.Value.TokenName&gt;_N) ; Data.String.N:IsString[0] &lt;Plutus.V1.Ledger.Value.TokenName&gt;_N))
                                    :: GHC.Types.Coercible GHC.Base.String GHC.Base.String))
... (a lot of lines skipped here)
Context: Compiling definition of: Week05.Homework2.mkPolicy
Context: Compiling expr: Week05.Homework2.mkPolicy
Context: Compiling expr: Week05.Homework2.mkPolicy oref'_axTu
Context: Compiling expr: PlutusTx.Base.$
                           @ (() -&gt; Plutus.V1.Ledger.Contexts.ScriptContext -&gt; GHC.Types.Bool)
                           @ Ledger.Typed.Scripts.MonetaryPolicies.WrappedMintingPolicyType
                           (Ledger.Typed.Scripts.MonetaryPolicies.wrapMintingPolicy
                              @ () PlutusTx.IsData.Instances.$fUnsafeFromData())
                           (Week05.Homework2.mkPolicy oref'_axTu)
Context: Compiling expr: \ (oref'_axTu :: Plutus.V1.Ledger.Tx.TxOutRef) -&gt;
                           PlutusTx.Base.$
                             @ (() -&gt; Plutus.V1.Ledger.Contexts.ScriptContext -&gt; GHC.Types.Bool)
                             @ Ledger.Typed.Scripts.MonetaryPolicies.WrappedMintingPolicyType
                             (Ledger.Typed.Scripts.MonetaryPolicies.wrapMintingPolicy
                                @ () PlutusTx.IsData.Instances.$fUnsafeFromData())
                             (Week05.Homework2.mkPolicy oref'_axTu)
Context: Compiling expr at &quot;plutus-pioneer-program-week05-0.1.0.0-inplace:Week05.Homework2:(55,8)-(55,85)&quot;
</code></pre>
<p>but this works</p>
<pre><code>mkPolicy oref () ctx = traceIfFalse &quot;UTxO not consumed&quot;   hasUTxO           &amp;&amp;
                       traceIfFalse &quot;wrong amount minted&quot; checkMintedAmount
  where
    info :: TxInfo
    info = scriptContextTxInfo ctx

    emptyToken :: TokenName
    emptyToken = TokenName &quot;&quot;

    hasUTxO :: Bool
    hasUTxO = any (\i -&gt; txInInfoOutRef i == oref) $ txInfoInputs info

    checkMintedAmount :: Bool
    checkMintedAmount = case flattenValue (txInfoMint info) of
        [(_, tn, amt)]  -&gt; tn == emptyToken &amp;&amp; amt == 1
        _               -&gt; False
</code></pre>
<p>I assumed that <code>{-# LANGUAGE OverloadedStrings   #-}</code> would work as <code>TokenName</code> is just a <code>newtype</code> for <code>PlutusTx.Builtins.Internal.BuiltinByteString</code>. From the repl</p>
<pre><code>Prelude Week05.Homework2&gt; :t Plutus.V1.Ledger.Value.TokenName
Plutus.V1.Ledger.Value.TokenName
  :: PlutusTx.Builtins.Internal.BuiltinByteString
     -&gt; Plutus.V1.Ledger.Value.TokenName
Prelude Week05.Homework2&gt; :i Plutus.V1.Ledger.Value.TokenName
type Plutus.V1.Ledger.Value.TokenName :: *
newtype Plutus.V1.Ledger.Value.TokenName
  = Plutus.V1.Ledger.Value.TokenName {Plutus.V1.Ledger.Value.unTokenName :: PlutusTx.Builtins.Internal.BuiltinByteString}
    -- Defined in `Plutus.V1.Ledger.Value'
instance Eq Plutus.V1.Ledger.Value.TokenName
  -- Defined in `Plutus.V1.Ledger.Value'
instance Ord Plutus.V1.Ledger.Value.TokenName
  -- Defined in `Plutus.V1.Ledger.Value'
instance Show Plutus.V1.Ledger.Value.TokenName
  -- Defined in `Plutus.V1.Ledger.Value'
</code></pre>
<hr />
<h2>Edit #1</h2>
<p>On reading <a href="https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/overloaded_strings.html" rel="nofollow noreferrer">this doc</a> I realised that maybe <code>TokenName</code> is not an instance of <code>IsString</code>. I tried to implement it using:</p>
<pre><code>instance IsString TokenName where
        fromString = unTokenName
</code></pre>
<p>but I got this error</p>
<pre><code>src/Week05/Homework2.hs:32:10: error:
    Duplicate instance declarations:
      instance IsString TokenName
        -- Defined at src/Week05/Homework2.hs:32:10
      instance IsString TokenName -- Defined in `Plutus.V1.Ledger.Value'
   |
32 | instance IsString TokenName where
   |          ^^^^^^^^^^^^^^^^^^
</code></pre>
<hr />
<h2>Edit #2</h2>
<p>The complete Homework file is <a href="https://pastebin.com/8d822sWr" rel="nofollow noreferrer">here</a>.</p>
 6113: <p>After digging into Plutus source, I think I've found why <code>tn == &quot;&quot;</code> crashes at runtime.</p>
<p>The problem might be that the instance of <code>TokenName IsString</code> doesn't use the <strong>INLINABLE</strong> pragma in the function <strong>fromString</strong>. Due to this, Plutus core crashes. (As a reminder, every function in order to compiles to Plutus core must have the <strong>INLINABLE</strong> pragma).</p>
<p>[source: <strong>Plutus.V1.Ledger.Value</strong>]</p>
<pre><code>instance IsString TokenName where
    fromString = fromText . Text.pack

</code></pre>
<p>On other hand, for example <code>traceIfFalse &quot;UTxO not consumed&quot; hasUTxO</code> is resolved properly because the function <strong>fromString</strong> in <code>IsString BuiltinString</code> uses the <strong>INLINABLE</strong> mechanism.</p>
<p>[source: <strong>PlutusTx.Builtins.Class</strong>]</p>
<pre><code>-- We can't put this in `Builtins.hs`, since that force `O0` deliberately, which prevents
-- the unfoldings from going in. So we just stick it here. Fiddly.
instance IsString BuiltinString where
    -- Try and make sure the dictionary selector goes away, it's simpler to match on
    -- the application of 'stringToBuiltinString'
    {-# INLINE fromString #-}
    -- See Note [noinline hack]
    fromString = Magic.noinline stringToBuiltinString

{-# INLINABLE stringToBuiltinString #-}
stringToBuiltinString :: Haskell.String -&gt; BuiltinString
-- To explain why the obfuscatedId is here
-- See Note [noinline hack]
stringToBuiltinString str = obfuscatedId (BuiltinString $ pack str)

</code></pre>
<p>Why don't Plutus team use <strong>INLINABLE</strong> mechanism in the function <strong>fromString</strong> for <strong>TokenName</strong>? I don't know, it might be a bug.</p>
<p><strong>EDIT 1</strong></p>
<p>I've raised an issue on <strong>Plutus</strong> repo.</p>
<p><a href="https://github.com/input-output-hk/plutus/issues/4404" rel="nofollow noreferrer">https://github.com/input-output-hk/plutus/issues/4404</a></p>
<p><strong>EDIT 2</strong></p>
<p>The issue is (see Plutus team's answer <a href="https://github.com/input-output-hk/plutus/issues/4404" rel="nofollow noreferrer">https://github.com/input-output-hk/plutus/issues/4404</a>)</p>
<blockquote>
<p>Unfortunately, due to the technical reasons plutus plugin doesn't
support OverloadedStrings with newtypes.</p>
</blockquote>
<p>Notice the same thing happens with <strong>PubKeyHash</strong> (it's a <strong>newtype</strong>)</p>
