1+ {-# LANGUAGE NamedFieldPuns #-}
2+ {-# LANGUAGE NumericUnderscores #-}
3+ {-# LANGUAGE OverloadedStrings #-}
4+ {-# LANGUAGE ScopedTypeVariables #-}
5+ {-# LANGUAGE TypeApplications #-}
6+
7+ module Cardano.Testnet.Test.Cli.Plutus.MultiAssetReturnCollateral
8+ ( hprop_collateral_with_tokens
9+ ) where
10+
11+ import Cardano.Api
12+ import Cardano.Testnet
13+
14+ import Prelude
15+ import qualified Data.Aeson as Aeson
16+ import Control.Monad (void )
17+ import Data.Default.Class
18+ import qualified Data.Text as T
19+ import System.FilePath ((</>) )
20+
21+ import Testnet.Components.Configuration
22+ import Testnet.Components.Query
23+ import Testnet.Defaults
24+ import Testnet.Process.Run (execCli' , mkExecConfig )
25+ import Testnet.Property.Util (integrationWorkspace , decodeEraUTxO )
26+ import Testnet.Types
27+
28+ import Hedgehog (Property )
29+ import qualified Hedgehog as H
30+ import qualified Hedgehog.Extras as H
31+
32+ -- @DISABLE_RETRIES=1 cabal test cardano-testnet-test --test-options '-p "/Collateral With Multiassets/"'@
33+ hprop_collateral_with_tokens :: Property
34+ hprop_collateral_with_tokens = integrationWorkspace " collateral-with-tokens" $ \ tempAbsBasePath' -> H. runWithDefaultWatchdog_ $ do
35+ conf@ Conf { tempAbsPath } <- mkConf tempAbsBasePath'
36+ let tempAbsPath' = unTmpAbsPath tempAbsPath
37+ work <- H. createDirectoryIfMissing $ tempAbsPath' </> " work"
38+
39+ let
40+ tempBaseAbsPath = makeTmpBaseAbsPath $ TmpAbsolutePath tempAbsPath'
41+ ceo = ConwayEraOnwardsConway
42+ sbe = convert ceo
43+ era = toCardanoEra sbe
44+ anyEra = AnyCardanoEra era
45+ options = def { cardanoNodeEra = AnyShelleyBasedEra sbe }
46+
47+ TestnetRuntime
48+ { configurationFile
49+ , testnetMagic
50+ , testnetNodes
51+ , wallets= wallet0: wallet1: wallet2: _
52+ } <- createAndRunTestnet options def conf
53+
54+ node <- H. headM testnetNodes
55+ poolSprocket1 <- H. noteShow $ nodeSprocket node
56+ execConfig <- mkExecConfig tempBaseAbsPath poolSprocket1 testnetMagic
57+ H. noteShow_ wallet0
58+ let utxoAddr = T. unpack $ paymentKeyInfoAddr wallet0
59+ utxoSKeyFile = signingKeyFp $ paymentKeyInfoPair wallet0
60+ socketPath = nodeSocketPath node
61+
62+ epochStateView <- getEpochStateView configurationFile socketPath
63+ txin1 <- findLargestUtxoForPaymentKey epochStateView sbe wallet0
64+ txinCollateral <- findLargestUtxoForPaymentKey epochStateView sbe wallet1
65+
66+ void $ execCli' execConfig
67+ [ anyEraToString anyEra, " query" , " utxo"
68+ , " --address" , T. unpack $ paymentKeyInfoAddr wallet0
69+ , " --cardano-mode"
70+ , " --out-file" , work </> " utxo-1.json"
71+ ]
72+
73+ utxo1Json <- H. leftFailM . H. readJsonFile $ work </> " utxo-1.json"
74+ H. noteShowM_ $ decodeEraUTxO sbe utxo1Json
75+ -- Create a simple always-succeeds Plutus V3 script
76+ plutusScript <- H. note $ work </> " always-succeeds-script.plutusV3"
77+ H. writeFile plutusScript $ T. unpack plutusV3Script
78+
79+
80+ -- Get the policy ID
81+ mintingPolicyId <- filter (/= ' \n ' ) <$>
82+ execCli' execConfig
83+ [ anyEraToString anyEra, " transaction"
84+ , " policyid"
85+ , " --script-file" , plutusScript
86+ ]
87+
88+ let assetName = " 7161636f696e" -- "qacoin" in hex
89+
90+ -- Create a Plutus script address
91+ plutusSpendingScriptAddr <-
92+ execCli' execConfig
93+ [ " latest" , " address" , " build"
94+ , " --payment-script-file" , plutusScript
95+ ]
96+
97+
98+ -- STEP 1: Mint tokens and send to an address we control
99+ -- This address will later be used as a collateral UTxO
100+ let maCollateralAddress = T. unpack $ paymentKeyInfoAddr wallet2
101+ mintTokensTxBody = work </> " mint-tokens-tx-body"
102+ mintTokensTx = work </> " mint-tokens-tx"
103+ adaOnlyCollateralAddress = T. unpack $ paymentKeyInfoAddr wallet1
104+ mintValue = mconcat [" 100 " , mintingPolicyId, " ." , assetName]
105+ adaOnlyCollateralValue = mconcat [adaOnlyCollateralAddress, " +" , show @ Int 3_000_000 ]
106+ collateralToBeValue = mconcat [maCollateralAddress, " +" , show @ Int 5_000_000 , " +" , mintValue]
107+ fundPlutusScriptAddrVal = mconcat [plutusSpendingScriptAddr, " +" , show @ Int 2_000_000 ]
108+
109+ void $ execCli' execConfig
110+ [ anyEraToString anyEra, " transaction" , " build"
111+ , " --change-address" , utxoAddr
112+ , " --tx-in" , T. unpack $ renderTxIn txin1
113+ , " --tx-in-collateral" , T. unpack $ renderTxIn txinCollateral
114+ , " --tx-out-return-collateral" , adaOnlyCollateralValue
115+ , " --witness-override" , show @ Int 2
116+ , " --tx-out" , collateralToBeValue
117+ , " --tx-out" , fundPlutusScriptAddrVal
118+ , " --tx-out-datum-hash-value" , " 0"
119+ , " --mint" , mintValue
120+ , " --mint-script-file" , plutusScript
121+ , " --mint-redeemer-value" , " 0"
122+ , " --out-file" , mintTokensTxBody
123+ ]
124+
125+ void $ execCli' execConfig
126+ [ " latest" , " transaction" , " sign"
127+ , " --tx-body-file" , mintTokensTxBody
128+ , " --signing-key-file" , utxoSKeyFile
129+ , " --signing-key-file" , signingKeyFp $ paymentKeyInfoPair wallet1
130+ , " --out-file" , mintTokensTx
131+ ]
132+ let mintTxDebugFile = work </> " mint-tokens-tx-view.json"
133+ void $ execCli' execConfig [" debug" , " transaction" , " view" , " --tx-file" , mintTokensTx, " --out-file" , mintTxDebugFile]
134+
135+ H. note_ " Mint Tokens Tx"
136+ txMintJson :: Aeson. Value <- H. leftFailM . H. readJsonFile $ mintTxDebugFile
137+ H. noteShowPretty_ txMintJson
138+
139+ void $ execCli' execConfig
140+ [ " latest" , " transaction" , " submit"
141+ , " --tx-file" , mintTokensTx
142+ ]
143+
144+
145+ -- STEP 2: Attempt to spend from script with collateral containing tokens
146+ -- This will fail because collateral cannot contain non-ADA tokens
147+
148+ -- Wait for transactions to be processed and find UTxOs
149+ _ <- waitForBlocks epochStateView 1
150+
151+ -- Find the UTxO with tokens at wallet1 (for collateral)
152+ txinCollateralWithTokensM <-
153+ findLargestMultiAssetUtxoWithAddress epochStateView sbe $ T. pack maCollateralAddress
154+ (txinCollateralWithTokens, collateralTxOut) <- H. evalMaybe txinCollateralWithTokensM
155+ H. note_ " Collateral TxOut"
156+ H. noteShow_ collateralTxOut
157+ -- Find the UTxO at the script address
158+ plutusScriptTxIn <- fmap fst . retryUntilJustM epochStateView (WaitForBlocks 10 ) $
159+ findLargestUtxoWithAddress epochStateView sbe $ T. pack plutusSpendingScriptAddr
160+
161+ let spendScriptUTxOTxBody = work </> " spend-script-utxo-tx-body"
162+ spendScriptUTxOTx = work </> " spend-script-utxo-tx"
163+
164+ void $ execCli' execConfig
165+ [ anyEraToString anyEra, " transaction" , " build"
166+ , " --change-address" , T. unpack $ paymentKeyInfoAddr wallet0
167+ , " --tx-in" , T. unpack $ renderTxIn plutusScriptTxIn
168+ , " --tx-in-script-file" , plutusScript
169+ , " --tx-in-datum-value" , " 0"
170+ , " --tx-in-redeemer-value" , " 0"
171+ , " --witness-override" , show @ Int 2
172+ , " --tx-in-collateral" , T. unpack $ renderTxIn txinCollateralWithTokens -- This is the key issue - using collateral with tokens
173+ , " --out-file" , spendScriptUTxOTxBody
174+ ]
175+ let prettyTxBodyFile = work </> " spend-script-utxo-tx-body-view.json"
176+ void $ execCli' execConfig [" debug" , " transaction" , " view" , " --tx-body-file" , spendScriptUTxOTxBody, " --out-file" , prettyTxBodyFile]
177+
178+ txBodyPrettyJson :: Aeson. Value <- H. leftFailM . H. readJsonFile $ prettyTxBodyFile
179+ H. note_ " Tx body"
180+ H. noteShowPretty_ txBodyPrettyJson
181+
182+ void $ execCli' execConfig
183+ [ " latest" , " transaction" , " sign"
184+ , " --tx-body-file" , spendScriptUTxOTxBody
185+ , " --signing-key-file" , signingKeyFp $ paymentKeyInfoPair wallet1
186+ , " --signing-key-file" , signingKeyFp $ paymentKeyInfoPair wallet2
187+ , " --out-file" , spendScriptUTxOTx
188+ ]
189+
190+ let prettyTxFile = work </> " spend-script-utxo-tx-view.json"
191+ void $ execCli' execConfig [" debug" , " transaction" , " view" , " --tx-file" , spendScriptUTxOTx, " --out-file" , prettyTxFile]
192+
193+ txPrettyJson :: Aeson. Value <- H. leftFailM . H. readJsonFile $ prettyTxFile
194+ H. noteShowPretty_ txPrettyJson
195+
196+ void $ execCli' execConfig
197+ [ " latest" , " transaction" , " submit"
198+ , " --tx-file" , spendScriptUTxOTx
199+ ]
200+
201+ H. success
0 commit comments