55-- 1.1.0.0 will be enabled in conway
66{-# OPTIONS_GHC -fobject-code -fno-ignore-interface-pragmas -fno-omit-interface-pragmas -fplugin-opt PlutusTx.Plugin:target-version=1.1.0.0 #-}
77{-# OPTIONS_GHC -fplugin-opt PlutusTx.Plugin:defer-errors #-}
8- {-# OPTIONS_GHC -g -fplugin-opt PlutusTx.Plugin:coverage-all #-}
98
10- -- | Scripts used for testing
9+ -- | Scripts used for testing coin-selection
1110module Scripts (
12- v2SpendingScriptSerialised ,
1311 v2SpendingScript ,
1412 v2StakingScript ,
1513 matchingIndexValidatorScript ,
1614 matchingIndexMPScript ,
1715 spendMatchingIndex ,
1816 mintMatchingIndex ,
19-
20- -- * Sample
21- sampleValidatorScript ,
22- spendSample ,
23- Sample. SampleRedeemer (.. ),
24-
25- -- * PingPong (Secure version)
26- pingPongValidatorScript ,
27- playPingPongRound ,
28- pingPongCovIdx ,
29- PingPong. PingPongRedeemer (.. ),
30- PingPong. PingPongState (.. ),
31-
32- -- * PingPong Vulnerable (for threat model demonstration)
33- pingPongVulnerableScript ,
34- playPingPongVulnerableRound ,
35-
36- -- * Bounty (Secure version - resists double satisfaction)
37- bountyValidatorScript ,
38- claimBounty ,
39- Bounty. BountyDatum (.. ),
40- Bounty. BountyRedeemer (.. ),
41-
42- -- * Bounty Vulnerable (for double satisfaction threat model demonstration)
43- bountyVulnerableScript ,
44- claimBountyVulnerable ,
4517) where
4618
47- import Cardano.Api (NetworkId )
4819import Cardano.Api qualified as C
4920import Convex.BuildTx (MonadBuildTx )
5021import Convex.BuildTx qualified as BuildTx
5122import Convex.PlutusTx (compiledCodeToScript )
5223import Convex.Scripts (toHashableScriptData )
53- import Convex.Utils (inAlonzo , inBabbage )
54- import PlutusLedgerApi.Common (SerialisedScript )
24+ import Convex.Utils (inAlonzo )
5525import PlutusLedgerApi.Test.Examples (alwaysSucceedingNAryFunction )
56- import PlutusLedgerApi.V3 qualified as PV3
5726import PlutusTx (BuiltinData , CompiledCode )
5827import PlutusTx qualified
59- import PlutusTx.Builtins qualified as PlutusTx
60- import PlutusTx.Code (getCovIdx )
61- import PlutusTx.Coverage (CoverageIndex )
6228import PlutusTx.Prelude (BuiltinUnit )
63- import Scripts.Bounty qualified as Bounty
64- import Scripts.Bounty.Vulnerable.DoubleSatisfaction qualified as BountyVulnerable
6529import Scripts.MatchingIndex qualified as MatchingIndex
66- import Scripts.PingPong qualified as PingPong
67- import Scripts.PingPong.Vulnerable.UnprotectedScriptOutput qualified as PingPongVulnerable
68- import Scripts.Sample qualified as Sample
6930
31+ -- | V2 spending script (always succeeds, 3 args: datum, redeemer, context)
7032v2SpendingScript :: C. PlutusScript C. PlutusScriptV2
7133v2SpendingScript = C. PlutusScriptSerialised $ alwaysSucceedingNAryFunction 3
7234
73- v2SpendingScriptSerialised :: SerialisedScript
74- v2SpendingScriptSerialised = alwaysSucceedingNAryFunction 3
75-
35+ -- | V2 staking script (always succeeds, 2 args: redeemer, context)
7636v2StakingScript :: C. PlutusScript C. PlutusScriptV2
7737v2StakingScript = C. PlutusScriptSerialised $ alwaysSucceedingNAryFunction 2
7838
@@ -88,28 +48,6 @@ matchingIndexValidatorScript = compiledCodeToScript matchingIndexValidatorCompil
8848matchingIndexMPScript :: C. PlutusScript C. PlutusScriptV3
8949matchingIndexMPScript = compiledCodeToScript matchingIndexMPCompiled
9050
91- sampleValidatorCompiled :: CompiledCode (BuiltinData -> BuiltinUnit )
92- sampleValidatorCompiled = $$ (PlutusTx. compile [|| Sample. validator|| ])
93-
94- sampleValidatorScript :: C. PlutusScript C. PlutusScriptV3
95- sampleValidatorScript = compiledCodeToScript sampleValidatorCompiled
96-
97- pingPongValidatorCompiled :: CompiledCode (BuiltinData -> BuiltinUnit )
98- pingPongValidatorCompiled = $$ (PlutusTx. compile [|| PingPong. validator|| ])
99-
100- pingPongValidatorScript :: C. PlutusScript C. PlutusScriptV3
101- pingPongValidatorScript = compiledCodeToScript pingPongValidatorCompiled
102-
103- pingPongCovIdx :: CoverageIndex
104- pingPongCovIdx = getCovIdx $$ (PlutusTx. compile [|| PingPong. validator|| ])
105-
106- -- | Vulnerable PingPong validator (for threat model demonstration)
107- pingPongVulnerableCompiled :: CompiledCode (BuiltinData -> BuiltinUnit )
108- pingPongVulnerableCompiled = $$ (PlutusTx. compile [|| PingPongVulnerable. validator|| ])
109-
110- pingPongVulnerableScript :: C. PlutusScript C. PlutusScriptV3
111- pingPongVulnerableScript = compiledCodeToScript pingPongVulnerableCompiled
112-
11351{- | Script that passes if the input's index (in the list of transaction inputs)
11452 matches the number passed as the redeemer
11553-}
@@ -144,166 +82,3 @@ mintMatchingIndex policy assetName quantity =
14482 C. NoScriptDatumForMint
14583 (fromIntegral @ Int @ Integer $ BuildTx. findIndexMinted policy txBody)
14684 in BuildTx. setScriptsValid >> BuildTx. addMintWithTxBody policy assetName quantity witness
147-
148- spendSample
149- :: forall era m
150- . (C. IsAlonzoBasedEra era , C. HasScriptLanguageInEra C. PlutusScriptV3 era )
151- => (MonadBuildTx era m )
152- => Sample. SampleRedeemer
153- -> C. TxIn
154- -> m ()
155- spendSample redeemer txi =
156- let witness _ =
157- C. ScriptWitness C. ScriptWitnessForSpending $
158- BuildTx. buildScriptWitness
159- sampleValidatorScript
160- (C. ScriptDatumForTxIn $ Just $ toHashableScriptData () )
161- -- (fromIntegral @Int @Integer $ 9898) -- BuildTx.findIndexSpending txi txBody)
162- redeemer
163- in BuildTx. setScriptsValid >> BuildTx. addInputWithTxBody txi witness
164-
165- plutusScript :: (C. IsPlutusScriptLanguage lang ) => C. PlutusScript lang -> C. Script lang
166- plutusScript = C. PlutusScript C. plutusScriptVersion
167-
168- -- | Convert a cardano-api TxIn to a Plutus TxOutRef
169- txInToTxOutRef :: C. TxIn -> PV3. TxOutRef
170- txInToTxOutRef (C. TxIn txId (C. TxIx ix)) =
171- PV3. TxOutRef
172- { PV3. txOutRefId = PV3. TxId $ PlutusTx. toBuiltin $ C. serialiseToRawBytes txId
173- , PV3. txOutRefIdx = fromIntegral ix
174- }
175-
176- playPingPongRound
177- :: forall era m
178- . ( C. IsBabbageBasedEra era
179- , C. HasScriptLanguageInEra C. PlutusScriptV3 era
180- )
181- => (MonadBuildTx era m )
182- => NetworkId
183- -> C. Lovelace
184- -> PingPong. PingPongRedeemer
185- -> C. TxIn
186- -> m ()
187- playPingPongRound networkId value redeemer txi = do
188- let witness _ =
189- C. ScriptWitness C. ScriptWitnessForSpending $
190- BuildTx. buildScriptWitness
191- pingPongValidatorScript
192- (C. ScriptDatumForTxIn $ Nothing )
193- redeemer
194- BuildTx. setScriptsValid >> BuildTx. addInputWithTxBody txi witness
195- BuildTx. payToScriptInlineDatum
196- networkId
197- (C. hashScript (plutusScript pingPongValidatorScript))
198- ( case redeemer of
199- PingPong. Ping -> PingPong. Pinged
200- PingPong. Pong -> PingPong. Ponged
201- PingPong. Stop -> PingPong. Stopped
202- )
203- C. NoStakeAddress
204- (C. lovelaceToValue value)
205-
206- -- | Play a round using the VULNERABLE PingPong validator (for threat model demo)
207- playPingPongVulnerableRound
208- :: forall era m
209- . ( C. IsBabbageBasedEra era
210- , C. HasScriptLanguageInEra C. PlutusScriptV3 era
211- )
212- => (MonadBuildTx era m )
213- => NetworkId
214- -> C. Lovelace
215- -> PingPongVulnerable. PingPongRedeemer
216- -> C. TxIn
217- -> m ()
218- playPingPongVulnerableRound networkId value redeemer txi = do
219- let witness _ =
220- C. ScriptWitness C. ScriptWitnessForSpending $
221- BuildTx. buildScriptWitness
222- pingPongVulnerableScript
223- (C. ScriptDatumForTxIn $ Nothing )
224- redeemer
225- BuildTx. setScriptsValid >> BuildTx. addInputWithTxBody txi witness
226- BuildTx. payToScriptInlineDatum
227- networkId
228- (C. hashScript (plutusScript pingPongVulnerableScript))
229- ( case redeemer of
230- PingPongVulnerable. Ping -> PingPongVulnerable. Pinged
231- PingPongVulnerable. Pong -> PingPongVulnerable. Ponged
232- PingPongVulnerable. Stop -> PingPongVulnerable. Stopped
233- )
234- C. NoStakeAddress
235- (C. lovelaceToValue value)
236-
237- -- Bounty validators
238-
239- bountyValidatorCompiled :: CompiledCode (BuiltinData -> BuiltinUnit )
240- bountyValidatorCompiled = $$ (PlutusTx. compile [|| Bounty. validator|| ])
241-
242- bountyValidatorScript :: C. PlutusScript C. PlutusScriptV3
243- bountyValidatorScript = compiledCodeToScript bountyValidatorCompiled
244-
245- -- | Vulnerable Bounty validator (for double satisfaction threat model demo)
246- bountyVulnerableCompiled :: CompiledCode (BuiltinData -> BuiltinUnit )
247- bountyVulnerableCompiled = $$ (PlutusTx. compile [|| BountyVulnerable. validator|| ])
248-
249- bountyVulnerableScript :: C. PlutusScript C. PlutusScriptV3
250- bountyVulnerableScript = compiledCodeToScript bountyVulnerableCompiled
251-
252- {- | Claim a bounty using the SECURE validator.
253- The output to the beneficiary must include the spent TxOutRef as inline datum.
254- -}
255- claimBounty
256- :: forall era m
257- . ( C. IsBabbageBasedEra era
258- , C. HasScriptLanguageInEra C. PlutusScriptV3 era
259- )
260- => (MonadBuildTx era m )
261- => C. TxIn
262- -- ^ The bounty UTxO to spend
263- -> C. AddressInEra era
264- -- ^ The beneficiary address (must match datum)
265- -> C. Lovelace
266- -- ^ Amount to pay to beneficiary
267- -> m ()
268- claimBounty txi beneficiaryAddr value = inBabbage @ era $ do
269- let witness _ =
270- C. ScriptWitness C. ScriptWitnessForSpending $
271- BuildTx. buildScriptWitness
272- bountyValidatorScript
273- (C. ScriptDatumForTxIn Nothing )
274- Bounty. Claim
275- BuildTx. setScriptsValid >> BuildTx. addInputWithTxBody txi witness
276- -- SECURE: Output includes the TxOutRef as inline datum
277- -- This prevents double satisfaction as each spend needs its own tagged output
278- let txOutRef = txInToTxOutRef txi
279- dat = C. TxOutDatumInline C. babbageBasedEra (toHashableScriptData txOutRef)
280- val = BuildTx. mkTxOutValue (C. lovelaceToValue value)
281- txo = C. TxOut beneficiaryAddr val dat C. ReferenceScriptNone
282- BuildTx. prependTxOut txo
283-
284- {- | Claim a bounty using the VULNERABLE validator.
285- The output to the beneficiary does NOT include any identifying datum.
286- -}
287- claimBountyVulnerable
288- :: forall era m
289- . ( C. IsBabbageBasedEra era
290- , C. HasScriptLanguageInEra C. PlutusScriptV3 era
291- )
292- => (MonadBuildTx era m )
293- => C. TxIn
294- -- ^ The bounty UTxO to spend
295- -> C. AddressInEra era
296- -- ^ The beneficiary address (must match datum)
297- -> C. Lovelace
298- -- ^ Amount to pay to beneficiary
299- -> m ()
300- claimBountyVulnerable txi beneficiaryAddr value = do
301- let witness _ =
302- C. ScriptWitness C. ScriptWitnessForSpending $
303- BuildTx. buildScriptWitness
304- bountyVulnerableScript
305- (C. ScriptDatumForTxIn Nothing )
306- BountyVulnerable. Claim
307- BuildTx. setScriptsValid >> BuildTx. addInputWithTxBody txi witness
308- -- VULNERABLE: No datum on the output - any output to beneficiary satisfies multiple spends
309- BuildTx. payToAddress beneficiaryAddr (C. lovelaceToValue value)
0 commit comments