2

I'm trying to write a very simple NFT minting policy myself and I can't get rid of the following error

Program error: GHC Core to PLC plugin: E043:Error: Reference to a name which is not a local, a builtin, or an external INLINABLE function: Variable Ledger.Typed.Scripts.MonetaryPolicies.wrapMintingPolicy
            No unfolding
            
Context: Compiling expr: Ledger.Typed.Scripts.MonetaryPolicies.wrapMintingPolicy

Context: Compiling expr: Ledger.Typed.Scripts.MonetaryPolicies.wrapMintingPolicy
                           @ NFTVM.Validator.ThreadTokenPolicy.TTRedeemer
                           
Context: Compiling expr: Ledger.Typed.Scripts.MonetaryPolicies.wrapMintingPolicy
                           @ NFTVM.Validator.ThreadTokenPolicy.TTRedeemer
                           NFTVM.Validator.ThreadTokenPolicy.$fUnsafeFromDataTTRedeemer

Context: Compiling expr: Ledger.Typed.Scripts.MonetaryPolicies.wrapMintingPolicy
                           @ NFTVM.Validator.ThreadTokenPolicy.TTRedeemer
                           NFTVM.Validator.ThreadTokenPolicy.$fUnsafeFromDataTTRedeemer
                           (NFTVM.Validator.ThreadTokenPolicy.makeThreadTokenLogic
                              utxo_ref' tn')

Context: Compiling expr: \ (tn' :: Plutus.V1.Ledger.Value.TokenName) ->
                           Ledger.Typed.Scripts.MonetaryPolicies.wrapMintingPolicy
                             @ NFTVM.Validator.ThreadTokenPolicy.TTRedeemer
                             NFTVM.Validator.ThreadTokenPolicy.$fUnsafeFromDataTTRedeemer
                             (NFTVM.Validator.ThreadTokenPolicy.makeThreadTokenLogic
                                utxo_ref' tn')

Context: Compiling expr: \ (utxo_ref' :: Plutus.V1.Ledger.Tx.TxOutRef)
                           (tn' :: Plutus.V1.Ledger.Value.TokenName) ->
                           Ledger.Typed.Scripts.MonetaryPolicies.wrapMintingPolicy
                             @ NFTVM.Validator.ThreadTokenPolicy.TTRedeemer
                             NFTVM.Validator.ThreadTokenPolicy.$fUnsafeFromDataTTRedeemer
                             (NFTVM.Validator.ThreadTokenPolicy.makeThreadTokenLogic
                                utxo_ref' tn')

reading this answer from a similar question I understood that this kind of error rises when using a non-inlineable piece of code

from the error message I can also understand that the incriminated code is the following

threadTokenPolicy :: TTParams -> Scripts.MintingPolicy
threadTokenPolicy params = Scripts.mkMintingPolicyScript (
        $$(PlutusTx.compile [|| wrappedMintingPolicy ||])
        `PlutusTx.applyCode` PlutusTx.liftCode params
    )
    where
        wrappedMintingPolicy = Scripts.wrapMintingPolicy @TTRedeemer . makeThreadTokenLogic

and I can confirm my assumption since removing this part removes also the error

can anyone please explain to me which part is the "non-inlineable" part?

I'll leave here the full code in case it can help having more context
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE OverloadedStrings   #-}

{-# LANGUAGE NoImplicitPrelude   #-}

{-# LANGUAGE DeriveAnyClass      #-}
{-# LANGUAGE DeriveGeneric       #-}
{-# LANGUAGE FlexibleContexts    #-}
{-# LANGUAGE NumericUnderscores  #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications    #-}
{-# LANGUAGE TypeFamilies        #-}
{-# LANGUAGE TypeOperators       #-}
{-# OPTIONS_GHC -Wno-unused-imports #-}
{-# LANGUAGE MultiParamTypeClasses #-}


module NFTVM.Validator.ThreadTokenPolicy (
    TTRedeemer(..), -- exporting the type and all his constructors ( Start and Close )
    makeThreadTokenLogic,
    threadTokenPolicy
    )
where

import qualified Plutus.V1.Ledger.Contexts as Ctx
    (
        ScriptContext, scriptContextTxInfo,
        ownCurrencySymbol,
        TxInfo, txInfoSignatories, txInfoMint
    )
import qualified Plutus.V1.Ledger.Value    as Value
    (
        CurrencySymbol,
        TokenName,
        flattenValue
    )
import qualified Plutus.V1.Ledger.Crypto   as Cryptography (PubKeyHash)-- CurrencySymbol
import qualified PlutusTx.Trace            as Trace (traceError, traceIfFalse)-- traceError , traceIfFalse
import qualified PlutusTx
    (
        makeLift,
        makeIsDataIndexed,
        compile, applyCode, liftCode
    )
import Ledger
    (
        scriptHashAddress,
        TxOutRef,
        TxInfo (txInfoInputs),
        TxInInfo (txInInfoOutRef),
        TokenName
    )
import qualified Ledger.Typed.Scripts      as Scripts
    (
        MintingPolicy, wrapMintingPolicy
    )
import qualified Ledger.Scripts            as Scripts
import           PlutusTx.Prelude          as Prelude
    (
        Bool (False), Integer,
        any, length,
        (==), (/=), (&&), (.), (!!),
        head, map, elem
    )
import PlutusTx (makeIsDataIndexed)


data TTParams = TTParams {
    getTokenName :: Value.TokenName,
    getUTxO :: Ledger.TxOutRef
}

PlutusTx.makeLift ''TTParams

data TTRedeemer = Start | Close

PlutusTx.makeIsDataIndexed ''TTRedeemer [
                                            ( 'Start , 0 ), -- Constr 0 [] -- means start, aka mints the thread NFT
                                            ( 'Close , 1 )  -- Constr 1 [] -- means close, aka burns the thread NFT
                                        ]

{-# INLINEABLE makeThreadTokenLogic #-}
makeThreadTokenLogic :: TTParams -> TTRedeemer -> Ctx.ScriptContext -> Bool
makeThreadTokenLogic params action ctx =
    correctUTxO &&
    case action of
        Start -> ensureTokenMinted
        Close -> ensureTokenBurned
        _ -> Trace.traceError "unexpected redeemer"
    where
        txInfos :: Ctx.TxInfo
        txInfos = Ctx.scriptContextTxInfo ctx

        correctUTxO :: Bool
        correctUTxO = getUTxO params `elem` map txInInfoOutRef (txInfoInputs txInfos)

        ensureOnlyThisTokenMinted_ForAmount :: Integer -> Bool
        ensureOnlyThisTokenMinted_ForAmount amtToMint =
            case Value.flattenValue (Ctx.txInfoMint txInfos) of
                -- if the list contains only one minting policy
                [( currSym, tn, amt )] -> amt == amtToMint && currSym == Ctx.ownCurrencySymbol ctx && getTokenName params == tn
                -- else fails
                _ ->  Trace.traceError "txInfoMint value contained more than 1 element; only 1 token minted is allowed"

        ensureTokenMinted :: Bool
        ensureTokenMinted = ensureOnlyThisTokenMinted_ForAmount 1

        ensureTokenBurned :: Bool
        ensureTokenBurned = ensureOnlyThisTokenMinted_ForAmount (-1)

threadTokenPolicy :: TTParams -> Scripts.MintingPolicy
threadTokenPolicy params = Scripts.mkMintingPolicyScript (
        $$(PlutusTx.compile [|| wrappedMintingPolicy ||])
        `PlutusTx.applyCode` PlutusTx.liftCode params
    )
    where
        wrappedMintingPolicy = Scripts.wrapMintingPolicy @TTRedeemer . makeThreadTokenLogic

Update

I do get the same error in the same kind of error compiling the Week05.NFT code from the plutus-pioneer-program; migth that be something wrong with any evironment configuration?

2 Answers 2

1

The name wrappedMintingPolicy in the where statement is not indicated with the INLINABLE pragma. Maybe adding the line

{-# INLINEABLE wrappedMintingPolicy #-}

solves the problem.

2
  • If that was the case shouldn't I have the same error inside the makeThreadTokenLogic function?
    – Michele
    Mar 24 at 13:41
  • Maybe GHC applies the INLINEABLE hint to all where clauses as well. And then wrappedMintingPolicy is the only function not "covered by it". Apr 29 at 10:14
0

As a second answer, you can also try to inline wrappedMintingPolicy by hand by doing:

threadTokenPolicy :: TTParams -> Scripts.MintingPolicy
threadTokenPolicy params = Scripts.mkMintingPolicyScript (
        $$(PlutusTx.compile [|| \x -> Scripts.wrapMintingPolicy @TTRedeemer (makeThreadTokenLogic x) ||])
        `PlutusTx.applyCode` PlutusTx.liftCode params
    )

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.