I am trying to transact with UTxO from a script address on the pre-production testnet.
I locked the fund ok with Datum, now I get an error when trying to consume that UTxO, it seem that the script is failing. But I am not sure how to get more information on where the problem is coming from, here is the off chain plutus code.
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE NoImplicitPrelude #-}
module FaucetValidatorScript
( FaucetParams (..)
, validator
) where
import Data.Aeson (ToJSON, FromJSON)
import GHC.Generics (Generic)
import Schema (ToSchema)
import Ledger hiding (singleton)
import Ledger.Address
import Ledger.Typed.Scripts
import Ledger.Value as Value
import Ledger.Ada
import qualified PlutusTx
import PlutusTx.Prelude hiding (Semigroup (..), unless)
import Prelude (Show (..))
import qualified Prelude as Pr
-- Simple Faucet validator script
-- Usage:
-- Expect one utxo at each contract.
-- Take that utxo as input
-- Create a new utxo with the "change" as output
-- This contract provides an example of using Validator Parameters.
-- For now, the Datum and Redeemer are not used in contract logic
-- Transactions will still have to match the type Integer for Datum and Redeemer
-- The context matters: we want to see that the PPBLSummer2022 token is in the transaction inputs and outputs.
data FaucetParams = FaucetParams
{ accessTokenSymbol :: !CurrencySymbol
, accessTokenName :: !TokenName
, faucetTokenSymbol :: !CurrencySymbol
, faucetTokenName :: !TokenName
, withdrawalAmount :: !Integer
} deriving (Pr.Eq, Pr.Ord, Show, Generic, ToJSON, FromJSON, ToSchema)
PlutusTx.makeLift ''FaucetParams
{-# INLINEABLE faucetValidator #-}
faucetValidator :: FaucetParams -> Integer -> Integer -> ScriptContext -> Bool
faucetValidator faucet _ _ ctx = traceIfFalse "Input needs PPBLSummer2022 token" inputHasAccessToken &&
traceIfFalse "PPBLSummer2022 token must return to sender" outputHasAccessToken &&
traceIfFalse "Faucet token must be distributed to sender" outputHasFaucetToken &&
traceIfFalse "Must return remaining tokens to contract" faucetContractGetsRemainingTokens &&
traceIfFalse "Do we need to check datum" checkDatumIsOk
where
info :: TxInfo
info = scriptContextTxInfo ctx
receiverPkh :: PubKeyHash
receiverPkh = head $ txInfoSignatories info
allTokens :: [CurrencySymbol]
allTokens = symbols $ valueSpent info
inputHasAccessToken :: Bool
inputHasAccessToken = (accessTokenSymbol faucet) `elem` allTokens
valueToReceiver :: Value
valueToReceiver = valuePaidTo info receiverPkh
outputHasAccessToken :: Bool
outputHasAccessToken = (valueOf valueToReceiver (accessTokenSymbol faucet) (accessTokenName faucet)) >= 1
outputHasFaucetToken :: Bool
outputHasFaucetToken = (valueOf valueToReceiver (faucetTokenSymbol faucet) (faucetTokenName faucet)) >= (withdrawalAmount faucet)
-- The UTXO input from Faucet
ownInput :: TxOut
ownInput = case findOwnInput ctx of
Nothing -> traceError "faucet input missing"
Just i -> txInInfoResolved i
-- The UTXO output back to Faucet
ownOutput :: TxOut
ownOutput = case getContinuingOutputs ctx of
[o] -> o -- There must be exactly ONE output UTXO
_ -> traceError "expected exactly one faucet output"
faucetInputValue :: Value
faucetInputValue = txOutValue ownInput
faucetOutputValue :: Value
faucetOutputValue = txOutValue ownOutput
faucetContractGetsRemainingTokens :: Bool
faucetContractGetsRemainingTokens = (valueOf faucetInputValue (faucetTokenSymbol faucet) (faucetTokenName faucet)) - (withdrawalAmount faucet) <= (valueOf faucetOutputValue (faucetTokenSymbol faucet) (faucetTokenName faucet))
checkDatumIsOk :: Bool
checkDatumIsOk = True
data FaucetTypes
instance ValidatorTypes FaucetTypes where
type DatumType FaucetTypes = Integer
type RedeemerType FaucetTypes = Integer
typedValidator :: FaucetParams -> TypedValidator FaucetTypes
typedValidator faucet =
mkTypedValidator @FaucetTypes
($$(PlutusTx.compile [||faucetValidator||]) `PlutusTx.applyCode` PlutusTx.liftCode faucet)
$$(PlutusTx.compile [||wrap||])
where
wrap = wrapValidator @Integer @Integer
validator :: FaucetParams -> Validator
validator = validatorScript . typedValidator
As you can see both Datum and Redeemer are given as integers, while Datum has to be exactly the one used to get the datum-hash I guess that the redeemer integer can be any? here is the transaction used to unlock it but which fails
CONTRACT_TXIN="7325518aff0270f7ef019236977baa8c301e8213a632996e0852480d5df196eb#1"
AUTH_TOKEN_TXIN="95b5308a55dd1648ea6e8f2325c0a7e307240aef1998777bb3ec860a3c32e55c#1"
FEE_TXIN="95b5308a55dd1648ea6e8f2325c0a7e307240aef1998777bb3ec860a3c32e55c#3"
COLLATERAL="95b5308a55dd1648ea6e8f2325c0a7e307240aef1998777bb3ec860a3c32e55c#2"
PLUTUS_SCRIPT_FILE=output/faucet.plutus
ASSET="fb45417ab92a155da3b31a8928c873eb9fd36c62184c736f189d334c.7467696d62616c"
AUTH_TOKEN="07fd9522f3ea6179415f8934ce0aa71b67fac6aa6024a59013bde6d8.506f72636f526f73736f466175636574546f6b656e"
TOKENS_BACK_TO_CONTRACT=267
CONTRACTADDR="addr_test1wrd5y9tudjkdcaxfy0cnuf042xlx4s9xm4xlq8pqdcyyxxsfr38fl"
DATUMHASH="db2b9e43ba6771c834279febfd091fd8cae78dec7ebe86fd9d729d3ba61e38e4"
SENDER="addr_test1vpjkdcxaxvt04vezk6r7vsdn22w40z094wggnpvvp47sy0cauqn90"
cardano-cli transaction build \
--tx-in $FEE_TXIN \
--tx-in $AUTH_TOKEN_TXIN \
--tx-in $CONTRACT_TXIN \
--tx-in-script-file $PLUTUS_SCRIPT_FILE \
--tx-in-datum-value 168 \
--tx-in-redeemer-value 21 \
--tx-in-collateral $COLLATERAL \
--tx-out $SENDER+"2000000 + 33 $ASSET" \
--tx-out $SENDER+"2000000 + 1 $AUTH_TOKEN" \
--tx-out $CONTRACTADDR+"2000000 + $TOKENS_BACK_TO_CONTRACT $ASSET" \
--tx-out-datum-hash $DATUMHASH \
--change-address $SENDER \
--protocol-params-file protocol.json \
--testnet-magic 1 \
--out-file unlock.raw
Command failed: transaction build Error: The following scripts have execution failures:
the script for transaction input 0 (in the order of the TxIds) 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: PT8
I would appreciate any help on understanding where the problem comes from or direction on how to debug a plutus script.