0

UPDATE: I'm making progress. It is apparent the TxOutRef stored on-chain has some extra-structure. For evidence I "printed" the TxOutRef's of the 'utxo' hard-wired in my minting policy and the one stored onchain. For the former/latter I uncommented the first/second comment in

hasUTxO :: Bool
hasUTxO = case txInfoInputs info of
--  [i] -> traceError . decodeUtf8 . getTxId . txOutRefId $ oref
--  [i] -> traceError . decodeUtf8 . getTxId . txOutRefId . txInInfoOutRef $ i
  _   -> traceError "many inputs"

The "printouts", given by the transaction errors returned by cardano-cli were, respectively:

1.

Command failed: transaction build  Error: The following scripts have execution failures:
<ommited stuff>
The machine terminated because of an error, either from a built-in function or from an explicit use of 'error'.
Script debugging logs: Redeemer decoded successfully
Script context decoded successfully
9c087132a325f6483aca8398bab1a56eda1390e762984ba054c25cafd738486c
Command failed: transaction build  Error: The following scripts have execution failures:
<ommited stuff>
The machine terminated because of an error, either from a built-in function or from an explicit use of 'error'.
Caused by: [
  (builtin decodeUtf8)
  (con
    bytestring #9c087132a325f6483aca8398bab1a56eda1390e762984ba054c25cafd738486c
  )
]
Script debugging logs: Redeemer decoded successfully
Script context decoded successfully

It is apparent that in 2. the relevant txOutRefId is buried inside some extra structure. The question now is, how can I extract the txOutRefId from all this structure?

ORIGINAL POST:

This simple minting policy should serve to mint an NFT by consuming a UTxO parametrized by TxOutRef:

{-# INLINABLE mkPolicy #-}
mkPolicy :: TxOutRef -> () -> ScriptContext -> Bool
mkPolicy utxo () ctx = traceIfFalse "UTxO not consumed" hasUTxO
  where
    info :: TxInfo
    info = scriptContextTxInfo ctx

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

(To simplify, we don’t even check that the number of minted tokens is one, since that is a non-issue here.)

I have been unable to deploy a concrete instance of this minting policy using cardano-cli. I now describe my procedure. Hopefully somebody can point out where the mistake is!

The UPLC policy and corresponding currency symbol are obtained with:

policy :: TxOutRef -> MintingPolicy
policy oref = mkMintingPolicyScript $
  $$(PlutusTx.compile [|| mkUntypedMintingPolicy . mkPolicy ||])
  `PlutusTx.applyCode`
  PlutusTx.liftCode oref

curSymbol :: TxOutRef -> CurrencySymbol
curSymbol = Scripts.scriptCurrencySymbol . policy

Meanwhile I have a wallet on Testnet PreProd with one UTxO:

[bash]$ cardano-cli query utxo --address $(cat wallet1.addr) --testnet-magic 1
                           TxHash                                 TxIx        Amount
--------------------------------------------------------------------------------------
9c087132a325f6483aca8398bab1a56eda1390e762984ba054c25cafd738486c     1        9784666930 lovelace + TxOutDatumNone

so I define an instance of my minting policy with:

oref_1 :: TxOutRef
oref_1 = TxOutRef
  { txOutRefId = TxId "9c087132a325f6483aca8398bab1a56eda1390e762984ba054c25cafd738486c"
  , txOutRefIdx = 1
  }

policy_1 :: MintingPolicy
policy_1 = policy oref_1

curSymbol_1 :: CurrencySymbol
curSymbol_1 = curSymbol oref_1

(Note that I have enabled the language extension OverloadedStrings.)

Now I serialize the minting policy and currency symbol, as well as the unit redeemer, with:

Prelude Deploy SimpleMinting> writePolicy "ledger/mint_1.plutus" policy_1
Right ()
Prelude Deploy SimpleMinting> writeCS "ledger/mint_1.hex" curSymbol_1 
Prelude Deploy SimpleMinting> writeUnit "ledger/unit.json"

where the commands writePolicy, writeCS and writeUnit are defined in this Deploy.hs.

Now, also inside directory 'ledger', I wrote the shell script 'mint.sh':

cardano-cli transaction build \
        --babbage-era \
        --testnet-magic 1 \
        --tx-in $(cat oref1.tmp) \
        --tx-in-collateral $(cat oref1.tmp) \
        --tx-out $(cat wallet1.addr)+"2000000 lovelace"+"1 $(cat mint_1.hex).$(cat tokenName.hex)" \
        --change-address $(cat wallet1.addr) \
        --mint "1 $(cat mint_1.hex).$(cat tokenName.hex)" \
        --mint-script-file mint_1.plutus \
        --mint-redeemer-file unit.json \
        --protocol-params-file protocol-params.json \
        --out-file tx.body

('tokenName.hex' was generated with echo -n "FUNKYTOKEN" | xxd -ps > tokenName.hex.)

Let us verify that 'oref1.tmp' stores the correct TxOutRef as queried above with cardano-cli:

[bash]$ cat oref1.tmp ; echo
9c087132a325f6483aca8398bab1a56eda1390e762984ba054c25cafd738486c#1

which is indeed correct. So we try to build the transaction by executing:

[bash]$ ./mint.sh
Command failed: transaction build  Error: The following scripts have execution failures:
the script for policyId 0 (in the order of the PolicyIds) failed with: 
The Plutus script evaluation failed: An error has occurred:  User error:
The machine terminated because of an error, either from a built-in function or from an explicit use of 'error'.
Script debugging logs: Redeemer decoded successfully
Script context decoded successfully
UTxO not consumed
PT5

The "UTxO not consumed" error message implies that my Minting Policy fails to recognize the TxOutRef. I am really puzzled about what am I doing wrong.

For reference, here is the complete haskell code for the plutus minting policy: SimpleMinting.hs.

0

2 Answers 2

1

Ok, I think I have it...

oref_1 = TxOutRef
  { txOutRefId = TxId "9c087132a325f6483aca8398bab1a56eda1390e762984ba054c25cafd738486c"
  , txOutRefIdx = 1
  }

This is not doing what you expect... you must do some conversions, if not its converting your hex string into something else.

You can do like this:

import qualified Data.Maybe as DataMaybe(fromJust)
import qualified Data.Text as DataText
import qualified PlutusTx.Builtins.Class as TxBuiltinsClass
import qualified Prelude as P
import qualified Text.Hex as TextHex

stringToStrictText :: P.String -> DataText.Text
stringToStrictText = DataText.pack

txOutRef = TextHex.decodeHex P.$ stringToStrictText "9c087132a325f6483aca8398bab1a56eda1390e762984ba054c25cafd738486c"
txOutRef' = TxBuiltinsClass.toBuiltin P.$ DataMaybe.fromJust txOutRef

oref_1 = TxOutRef { txOutRefId = TxId txOutRef', txOutRefIdx = 1 }

For using TextHex you must add this in your cabal file:

  build-depends: 
  hex-text
3
  • This works indeed. Awesome! As a side note, it is frustrating that it was so hard to deploy this simple example (taken from PPP week 5) to the blockchain.
    – a_juggler
    Commented Feb 20, 2023 at 4:59
  • Yes, I known, to put all the parts in move in the beginning take some time, but the good part is that after that most of the rest is reuse them in different ways. Good Luck! Commented Feb 20, 2023 at 15:24
  • You can also do it without DataText.Text, but using function from Plutus.V1.Ledger.Bytes instead. See github.com/input-output-hk/plutus-apps/blob/…
    – james
    Commented Feb 21, 2023 at 9:48
0

Did you try to have at least two utxos and use one for the mint and one different for collateral?

--tx-in $(cat oref1.tmp)
--tx-in-collateral $(cat oref2.tmp)

2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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