{-# LANGUAGE OverloadedStrings #-}
module Convex.ThreatModel.InvalidScriptPurpose (
invalidScriptPurposeAttack,
invalidScriptPurposeAttackWith,
) where
import Cardano.Api qualified as C
import Convex.ThreatModel
import Convex.ThreatModel.Cardano.Api (IsPlutusScriptInEra)
import Convex.ThreatModel.TxModifier (addPlutusScriptMint)
import GHC.Exts (fromList)
invalidScriptPurposeAttack
:: (IsPlutusScriptInEra lang)
=> C.PlutusScript lang
-> ThreatModel ()
invalidScriptPurposeAttack :: forall lang.
IsPlutusScriptInEra lang =>
PlutusScript lang -> ThreatModel ()
invalidScriptPurposeAttack =
ScriptData
-> AssetName -> Quantity -> PlutusScript lang -> ThreatModel ()
forall lang.
IsPlutusScriptInEra lang =>
ScriptData
-> AssetName -> Quantity -> PlutusScript lang -> ThreatModel ()
invalidScriptPurposeAttackWith
(Integer -> [ScriptData] -> ScriptData
C.ScriptDataConstructor Integer
0 [])
(ByteString -> AssetName
C.UnsafeAssetName ByteString
"deadbeef")
(Integer -> Quantity
C.Quantity Integer
1)
invalidScriptPurposeAttackWith
:: (IsPlutusScriptInEra lang)
=> C.ScriptData
-> C.AssetName
-> C.Quantity
-> C.PlutusScript lang
-> ThreatModel ()
invalidScriptPurposeAttackWith :: forall lang.
IsPlutusScriptInEra lang =>
ScriptData
-> AssetName -> Quantity -> PlutusScript lang -> ThreatModel ()
invalidScriptPurposeAttackWith ScriptData
redeemer AssetName
assetName Quantity
quantity PlutusScript lang
spendingValidator = String -> ThreatModel () -> ThreatModel ()
forall a. String -> ThreatModel a -> ThreatModel a
Named String
"Invalid Script Purpose Attack" (ThreatModel () -> ThreatModel ())
-> ThreatModel () -> ThreatModel ()
forall a b. (a -> b) -> a -> b
$ do
Input
_ <- (Input -> Bool) -> ThreatModel Input
anyInputSuchThat (Bool -> Bool
not (Bool -> Bool) -> (Input -> Bool) -> Input -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AddressAny -> Bool
isKeyAddressAny (AddressAny -> Bool) -> (Input -> AddressAny) -> Input -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Input -> AddressAny
forall t. IsInputOrOutput t => t -> AddressAny
addressOf)
Output
output <- (Output -> Bool) -> ThreatModel Output
anyOutputSuchThat (AddressAny -> Bool
isKeyAddressAny (AddressAny -> Bool) -> (Output -> AddressAny) -> Output -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Output -> AddressAny
forall t. IsInputOrOutput t => t -> AddressAny
addressOf)
let policyId :: PolicyId
policyId = ScriptHash -> PolicyId
C.PolicyId (ScriptHash -> PolicyId) -> ScriptHash -> PolicyId
forall a b. (a -> b) -> a -> b
$ Script lang -> ScriptHash
forall lang. Script lang -> ScriptHash
hashScript (PlutusScriptVersion lang -> PlutusScript lang -> Script lang
forall lang.
IsPlutusScriptLanguage lang =>
PlutusScriptVersion lang -> PlutusScript lang -> Script lang
C.PlutusScript PlutusScriptVersion lang
forall lang.
IsPlutusScriptLanguage lang =>
PlutusScriptVersion lang
plutusScriptVersion PlutusScript lang
spendingValidator)
mintedValue :: Value
mintedValue = [Item Value] -> Value
forall l. IsList l => [Item l] -> l
fromList [(PolicyId -> AssetName -> AssetId
C.AssetId PolicyId
policyId AssetName
assetName, Quantity
quantity)]
newValue :: Value
newValue = Output -> Value
forall t. IsInputOrOutput t => t -> Value
valueOf Output
output Value -> Value -> Value
forall a. Semigroup a => a -> a -> a
<> Value
mintedValue
String -> ThreatModel ()
counterexampleTM (String -> ThreatModel ()) -> String -> ThreatModel ()
forall a b. (a -> b) -> a -> b
$
[String] -> String
paragraph
[ String
"Testing script-purpose confusion by executing a spending validator"
, String
"as a minting policy in the same transaction."
]
String -> ThreatModel ()
counterexampleTM (String -> ThreatModel ()) -> String -> ThreatModel ()
forall a b. (a -> b) -> a -> b
$
[String] -> String
paragraph
[ String
"If this validates, the script accepted MintingScript context where"
, String
"SpendingScript was expected. This can lead to authorization bypass"
, String
"or unintended purpose-dependent behavior."
]
TxModifier -> ThreatModel ()
shouldNotValidate (TxModifier -> ThreatModel ()) -> TxModifier -> ThreatModel ()
forall a b. (a -> b) -> a -> b
$
Output -> Value -> TxModifier
forall t. IsInputOrOutput t => t -> Value -> TxModifier
changeValueOf Output
output Value
newValue
TxModifier -> TxModifier -> TxModifier
forall a. Semigroup a => a -> a -> a
<> PlutusScript lang
-> AssetName -> Quantity -> ScriptData -> TxModifier
forall lang.
IsPlutusScriptInEra lang =>
PlutusScript lang
-> AssetName -> Quantity -> ScriptData -> TxModifier
addPlutusScriptMint PlutusScript lang
spendingValidator AssetName
assetName Quantity
quantity ScriptData
redeemer