{-# LANGUAGE TemplateHaskell #-}

{- |
Module     : Agora.Effect.GovernorMutation
Maintainer : connor@mlabs.city
Description: An effect that mutates governor settings.

An effect for mutating governor settings.
-}
module Agora.Effect.GovernorMutation (
  -- * Haskell-land
  MutateGovernorDatum (..),

  -- * Plutarch-land
  PMutateGovernorDatum (..),

  -- * Scripts
  mutateGovernorValidator,
) where

import Agora.Effect (makeEffect)
import Agora.Governor (
  Governor,
  GovernorDatum,
  PGovernorDatum,
  governorDatumValid,
 )
import Agora.Governor.Scripts (
  authorityTokenSymbolFromGovernor,
  governorSTAssetClassFromGovernor,
 )
import Agora.Plutarch.Orphans ()
import Agora.Utils (
  isScriptAddress,
  mustBePDJust,
  mustBePJust,
 )
import GHC.Generics qualified as GHC
import Generics.SOP (Generic, I (I))
import Plutarch.Api.V1 (
  PTxOutRef,
  PValidator,
  PValue,
 )
import Plutarch.Api.V1.ScriptContext (ptryFindDatum)
import "liqwid-plutarch-extra" Plutarch.Api.V1.Value (pvalueOf)
import Plutarch.DataRepr (
  DerivePConstantViaData (..),
  PDataFields,
  PIsDataReprInstances (PIsDataReprInstances),
 )
import Plutarch.Extra.TermCont (pguardC)
import Plutarch.Lift (PConstantDecl, PLifted, PUnsafeLiftDecl)
import PlutusLedgerApi.V1 (TxOutRef)
import PlutusLedgerApi.V1.Value (AssetClass (..))
import PlutusTx qualified

--------------------------------------------------------------------------------

{- | Haskell-level datum for the governor mutation effect script.

     @since 0.1.0
-}
data MutateGovernorDatum = MutateGovernorDatum
  { MutateGovernorDatum -> TxOutRef
governorRef :: TxOutRef
  -- ^ Referenced governor state UTXO should be updated by the effect.
  , MutateGovernorDatum -> GovernorDatum
newDatum :: GovernorDatum
  -- ^ The new settings for the governor.
  }
  deriving stock (Int -> MutateGovernorDatum -> ShowS
[MutateGovernorDatum] -> ShowS
MutateGovernorDatum -> String
(Int -> MutateGovernorDatum -> ShowS)
-> (MutateGovernorDatum -> String)
-> ([MutateGovernorDatum] -> ShowS)
-> Show MutateGovernorDatum
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [MutateGovernorDatum] -> ShowS
$cshowList :: [MutateGovernorDatum] -> ShowS
show :: MutateGovernorDatum -> String
$cshow :: MutateGovernorDatum -> String
showsPrec :: Int -> MutateGovernorDatum -> ShowS
$cshowsPrec :: Int -> MutateGovernorDatum -> ShowS
Show, (forall x. MutateGovernorDatum -> Rep MutateGovernorDatum x)
-> (forall x. Rep MutateGovernorDatum x -> MutateGovernorDatum)
-> Generic MutateGovernorDatum
forall x. Rep MutateGovernorDatum x -> MutateGovernorDatum
forall x. MutateGovernorDatum -> Rep MutateGovernorDatum x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep MutateGovernorDatum x -> MutateGovernorDatum
$cfrom :: forall x. MutateGovernorDatum -> Rep MutateGovernorDatum x
GHC.Generic)
  deriving anyclass (All @[Type] (SListI @Type) (Code MutateGovernorDatum)
All @[Type] (SListI @Type) (Code MutateGovernorDatum)
-> (MutateGovernorDatum -> Rep MutateGovernorDatum)
-> (Rep MutateGovernorDatum -> MutateGovernorDatum)
-> Generic MutateGovernorDatum
Rep MutateGovernorDatum -> MutateGovernorDatum
MutateGovernorDatum -> Rep MutateGovernorDatum
forall a.
All @[Type] (SListI @Type) (Code a)
-> (a -> Rep a) -> (Rep a -> a) -> Generic a
to :: Rep MutateGovernorDatum -> MutateGovernorDatum
$cto :: Rep MutateGovernorDatum -> MutateGovernorDatum
from :: MutateGovernorDatum -> Rep MutateGovernorDatum
$cfrom :: MutateGovernorDatum -> Rep MutateGovernorDatum
Generic)

PlutusTx.makeIsDataIndexed ''MutateGovernorDatum [('MutateGovernorDatum, 0)]

--------------------------------------------------------------------------------

{- | Plutarch-level version of 'MutateGovernorDatum'.

     @since 0.1.0
-}
newtype PMutateGovernorDatum (s :: S)
  = PMutateGovernorDatum
      ( Term
          s
          ( PDataRecord
              '[ "governorRef" ':= PTxOutRef
               , "newDatum" ':= PGovernorDatum
               ]
          )
      )
  deriving stock
    ( -- | @since 0.1.0
      (forall x.
 PMutateGovernorDatum s -> Rep (PMutateGovernorDatum s) x)
-> (forall x.
    Rep (PMutateGovernorDatum s) x -> PMutateGovernorDatum s)
-> Generic (PMutateGovernorDatum s)
forall x. Rep (PMutateGovernorDatum s) x -> PMutateGovernorDatum s
forall x. PMutateGovernorDatum s -> Rep (PMutateGovernorDatum s) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall (s :: S) x.
Rep (PMutateGovernorDatum s) x -> PMutateGovernorDatum s
forall (s :: S) x.
PMutateGovernorDatum s -> Rep (PMutateGovernorDatum s) x
$cto :: forall (s :: S) x.
Rep (PMutateGovernorDatum s) x -> PMutateGovernorDatum s
$cfrom :: forall (s :: S) x.
PMutateGovernorDatum s -> Rep (PMutateGovernorDatum s) x
GHC.Generic
    )
  deriving anyclass
    ( -- | @since 0.1.0
      All @[Type] (SListI @Type) (Code (PMutateGovernorDatum s))
All @[Type] (SListI @Type) (Code (PMutateGovernorDatum s))
-> (PMutateGovernorDatum s -> Rep (PMutateGovernorDatum s))
-> (Rep (PMutateGovernorDatum s) -> PMutateGovernorDatum s)
-> Generic (PMutateGovernorDatum s)
Rep (PMutateGovernorDatum s) -> PMutateGovernorDatum s
PMutateGovernorDatum s -> Rep (PMutateGovernorDatum s)
forall a.
All @[Type] (SListI @Type) (Code a)
-> (a -> Rep a) -> (Rep a -> a) -> Generic a
forall {s :: S}.
All @[Type] (SListI @Type) (Code (PMutateGovernorDatum s))
forall (s :: S).
Rep (PMutateGovernorDatum s) -> PMutateGovernorDatum s
forall (s :: S).
PMutateGovernorDatum s -> Rep (PMutateGovernorDatum s)
to :: Rep (PMutateGovernorDatum s) -> PMutateGovernorDatum s
$cto :: forall (s :: S).
Rep (PMutateGovernorDatum s) -> PMutateGovernorDatum s
from :: PMutateGovernorDatum s -> Rep (PMutateGovernorDatum s)
$cfrom :: forall (s :: S).
PMutateGovernorDatum s -> Rep (PMutateGovernorDatum s)
Generic
    )
  deriving anyclass
    ( -- | @since 0.1.0
      PIsData PMutateGovernorDatum
PlutusType PMutateGovernorDatum
PlutusType PMutateGovernorDatum
-> PIsData PMutateGovernorDatum
-> (forall (s :: S).
    PMutateGovernorDatum s
    -> Term s (PDataSum (PIsDataReprRepr PMutateGovernorDatum)))
-> (forall (s :: S) (b :: PType).
    Term s (PDataSum (PIsDataReprRepr PMutateGovernorDatum))
    -> (PMutateGovernorDatum s -> Term s b) -> Term s b)
-> PIsDataRepr PMutateGovernorDatum
forall (s :: S).
PMutateGovernorDatum s
-> Term s (PDataSum (PIsDataReprRepr PMutateGovernorDatum))
forall (s :: S) (b :: PType).
Term s (PDataSum (PIsDataReprRepr PMutateGovernorDatum))
-> (PMutateGovernorDatum s -> Term s b) -> Term s b
forall (a :: PType).
PlutusType a
-> PIsData a
-> (forall (s :: S). a s -> Term s (PDataSum (PIsDataReprRepr a)))
-> (forall (s :: S) (b :: PType).
    Term s (PDataSum (PIsDataReprRepr a))
    -> (a s -> Term s b) -> Term s b)
-> PIsDataRepr a
pmatchRepr :: forall (s :: S) (b :: PType).
Term s (PDataSum (PIsDataReprRepr PMutateGovernorDatum))
-> (PMutateGovernorDatum s -> Term s b) -> Term s b
$cpmatchRepr :: forall (s :: S) (b :: PType).
Term s (PDataSum (PIsDataReprRepr PMutateGovernorDatum))
-> (PMutateGovernorDatum s -> Term s b) -> Term s b
pconRepr :: forall (s :: S).
PMutateGovernorDatum s
-> Term s (PDataSum (PIsDataReprRepr PMutateGovernorDatum))
$cpconRepr :: forall (s :: S).
PMutateGovernorDatum s
-> Term s (PDataSum (PIsDataReprRepr PMutateGovernorDatum))
PIsDataRepr
    )
  deriving
    ( -- | @since 0.1.0
      PCon PMutateGovernorDatum
PMatch PMutateGovernorDatum
PCon PMutateGovernorDatum
-> PMatch PMutateGovernorDatum
-> (forall (s :: S) (b :: PType).
    PMutateGovernorDatum s -> Term s (PInner PMutateGovernorDatum b))
-> (forall (s :: S) (b :: PType).
    Term s (PInner PMutateGovernorDatum b)
    -> (PMutateGovernorDatum s -> Term s b) -> Term s b)
-> PlutusType PMutateGovernorDatum
forall (s :: S) (b :: PType).
Term s (PInner PMutateGovernorDatum b)
-> (PMutateGovernorDatum s -> Term s b) -> Term s b
forall (s :: S) (b :: PType).
PMutateGovernorDatum s -> Term s (PInner PMutateGovernorDatum b)
forall (a :: PType).
PCon a
-> PMatch a
-> (forall (s :: S) (b :: PType). a s -> Term s (PInner a b))
-> (forall (s :: S) (b :: PType).
    Term s (PInner a b) -> (a s -> Term s b) -> Term s b)
-> PlutusType a
pmatch' :: forall (s :: S) (b :: PType).
Term s (PInner PMutateGovernorDatum b)
-> (PMutateGovernorDatum s -> Term s b) -> Term s b
$cpmatch' :: forall (s :: S) (b :: PType).
Term s (PInner PMutateGovernorDatum b)
-> (PMutateGovernorDatum s -> Term s b) -> Term s b
pcon' :: forall (s :: S) (b :: PType).
PMutateGovernorDatum s -> Term s (PInner PMutateGovernorDatum b)
$cpcon' :: forall (s :: S) (b :: PType).
PMutateGovernorDatum s -> Term s (PInner PMutateGovernorDatum b)
PlutusType
    , -- | @since 0.1.0
      (forall (s :: S).
 Term s (PAsData PMutateGovernorDatum)
 -> Term s PMutateGovernorDatum)
-> (forall (s :: S). Term s PMutateGovernorDatum -> Term s PData)
-> PIsData PMutateGovernorDatum
forall (s :: S).
Term s (PAsData PMutateGovernorDatum)
-> Term s PMutateGovernorDatum
forall (s :: S). Term s PMutateGovernorDatum -> Term s PData
forall (a :: PType).
(forall (s :: S). Term s (PAsData a) -> Term s a)
-> (forall (s :: S). Term s a -> Term s PData) -> PIsData a
pdataImpl :: forall (s :: S). Term s PMutateGovernorDatum -> Term s PData
$cpdataImpl :: forall (s :: S). Term s PMutateGovernorDatum -> Term s PData
pfromDataImpl :: forall (s :: S).
Term s (PAsData PMutateGovernorDatum)
-> Term s PMutateGovernorDatum
$cpfromDataImpl :: forall (s :: S).
Term s (PAsData PMutateGovernorDatum)
-> Term s PMutateGovernorDatum
PIsData
    , -- | @since 0.1.0
      (forall (s :: S).
 Term s PMutateGovernorDatum
 -> Term s (PDataRecord (PFields PMutateGovernorDatum)))
-> PDataFields PMutateGovernorDatum
forall (s :: S).
Term s PMutateGovernorDatum
-> Term s (PDataRecord (PFields PMutateGovernorDatum))
forall (a :: PType).
(forall (s :: S). Term s a -> Term s (PDataRecord (PFields a)))
-> PDataFields a
ptoFields :: forall (s :: S).
Term s PMutateGovernorDatum
-> Term s (PDataRecord (PFields PMutateGovernorDatum))
$cptoFields :: forall (s :: S).
Term s PMutateGovernorDatum
-> Term s (PDataRecord (PFields PMutateGovernorDatum))
PDataFields
    , -- | @since 0.1.0
      (forall (s :: S).
 Term s PMutateGovernorDatum
 -> Term s PMutateGovernorDatum -> Term s PBool)
-> PEq PMutateGovernorDatum
forall (s :: S).
Term s PMutateGovernorDatum
-> Term s PMutateGovernorDatum -> Term s PBool
forall (t :: PType).
(forall (s :: S). Term s t -> Term s t -> Term s PBool) -> PEq t
#== :: forall (s :: S).
Term s PMutateGovernorDatum
-> Term s PMutateGovernorDatum -> Term s PBool
$c#== :: forall (s :: S).
Term s PMutateGovernorDatum
-> Term s PMutateGovernorDatum -> Term s PBool
PEq
    )
    via (PIsDataReprInstances PMutateGovernorDatum)

-- | @since 0.1.0
instance PUnsafeLiftDecl PMutateGovernorDatum where type PLifted PMutateGovernorDatum = MutateGovernorDatum

-- | @since 0.1.0
deriving via (DerivePConstantViaData MutateGovernorDatum PMutateGovernorDatum) instance (PConstantDecl MutateGovernorDatum)

-- | @since 0.1.0
deriving via PAsData (PIsDataReprInstances PMutateGovernorDatum) instance PTryFrom PData (PAsData PMutateGovernorDatum)

--------------------------------------------------------------------------------

{- | Validator for the governor mutation effect.

     This effect is implemented using the 'Agora.Effect.makeEffect' wrapper,
     meaning that the burning of GAT is checked in said wrapper.

     In order to locate the governor, the validator is parametrized with a 'Agora.Governor.Governor'.

     All the information it needs to validate the effect is encoded in the 'MutateGovernorDatum',
      so regardless what redeemer it's given, it will check:

     - No token is minted/burnt other than GAT.
     - Nothing is being paid to the the effect validator.
     - The governor's state UTXO must be spent:

         * It carries exactly one GST.
         * It's referenced by 'governorRef' in the effect's datum.

     - A new state UTXO is paid to the governor:

         * It contains the GST.
         * It has valid governor state datum.
         * The datum is exactly the same as the 'newDatum'.

     @since 0.1.0
-}
mutateGovernorValidator :: Governor -> ClosedTerm PValidator
mutateGovernorValidator :: Governor -> ClosedTerm PValidator
mutateGovernorValidator Governor
gov = CurrencySymbol
-> (forall (s :: S).
    Term s PCurrencySymbol
    -> Term s PMutateGovernorDatum
    -> Term s PTxOutRef
    -> Term s (PAsData PTxInfo)
    -> Term s POpaque)
-> ClosedTerm PValidator
forall (datum :: PType).
(PIsData datum, PTryFrom PData (PAsData datum)) =>
CurrencySymbol
-> (forall (s :: S).
    Term s PCurrencySymbol
    -> Term s datum
    -> Term s PTxOutRef
    -> Term s (PAsData PTxInfo)
    -> Term s POpaque)
-> ClosedTerm PValidator
makeEffect (Governor -> CurrencySymbol
authorityTokenSymbolFromGovernor Governor
gov) ((forall (s :: S).
  Term s PCurrencySymbol
  -> Term s PMutateGovernorDatum
  -> Term s PTxOutRef
  -> Term s (PAsData PTxInfo)
  -> Term s POpaque)
 -> ClosedTerm PValidator)
-> (forall (s :: S).
    Term s PCurrencySymbol
    -> Term s PMutateGovernorDatum
    -> Term s PTxOutRef
    -> Term s (PAsData PTxInfo)
    -> Term s POpaque)
-> ClosedTerm PValidator
forall a b. (a -> b) -> a -> b
$
  \Term s PCurrencySymbol
_gatCs (Term s PMutateGovernorDatum
datum :: Term _ PMutateGovernorDatum) Term s PTxOutRef
_ Term s (PAsData PTxInfo)
txInfo -> TermCont @POpaque s (Term s POpaque) -> Term s POpaque
forall (a :: PType) (s :: S). TermCont @a s (Term s a) -> Term s a
unTermCont (TermCont @POpaque s (Term s POpaque) -> Term s POpaque)
-> TermCont @POpaque s (Term s POpaque) -> Term s POpaque
forall a b. (a -> b) -> a -> b
$ do
    HRec
  ((':)
     @(Symbol, Type)
     '("governorRef", Term s (PAsData PTxOutRef))
     ((':)
        @(Symbol, Type)
        '("newDatum", Term s (PAsData PGovernorDatum))
        ('[] @(Symbol, Type))))
datumF <- ((HRec
    ((':)
       @(Symbol, Type)
       '("governorRef", Term s (PAsData PTxOutRef))
       ((':)
          @(Symbol, Type)
          '("newDatum", Term s (PAsData PGovernorDatum))
          ('[] @(Symbol, Type))))
  -> Term s POpaque)
 -> Term s POpaque)
-> TermCont
     @POpaque
     s
     (HRec
        ((':)
           @(Symbol, Type)
           '("governorRef", Term s (PAsData PTxOutRef))
           ((':)
              @(Symbol, Type)
              '("newDatum", Term s (PAsData PGovernorDatum))
              ('[] @(Symbol, Type)))))
forall a (s :: S) (r :: PType).
((a -> Term s r) -> Term s r) -> TermCont @r s a
tcont (((HRec
     ((':)
        @(Symbol, Type)
        '("governorRef", Term s (PAsData PTxOutRef))
        ((':)
           @(Symbol, Type)
           '("newDatum", Term s (PAsData PGovernorDatum))
           ('[] @(Symbol, Type))))
   -> Term s POpaque)
  -> Term s POpaque)
 -> TermCont
      @POpaque
      s
      (HRec
         ((':)
            @(Symbol, Type)
            '("governorRef", Term s (PAsData PTxOutRef))
            ((':)
               @(Symbol, Type)
               '("newDatum", Term s (PAsData PGovernorDatum))
               ('[] @(Symbol, Type))))))
-> ((HRec
       ((':)
          @(Symbol, Type)
          '("governorRef", Term s (PAsData PTxOutRef))
          ((':)
             @(Symbol, Type)
             '("newDatum", Term s (PAsData PGovernorDatum))
             ('[] @(Symbol, Type))))
     -> Term s POpaque)
    -> Term s POpaque)
-> TermCont
     @POpaque
     s
     (HRec
        ((':)
           @(Symbol, Type)
           '("governorRef", Term s (PAsData PTxOutRef))
           ((':)
              @(Symbol, Type)
              '("newDatum", Term s (PAsData PGovernorDatum))
              ('[] @(Symbol, Type)))))
forall a b. (a -> b) -> a -> b
$ forall (fs :: [Symbol]) (a :: PType) (s :: S) (b :: PType)
       (ps :: [PLabeledType]) (bs :: [ToBind]).
(PDataFields a,
 (ps :: [PLabeledType]) ~ (PFields a :: [PLabeledType]),
 (bs :: [ToBind]) ~ (Bindings ps fs :: [ToBind]),
 BindFields ps bs) =>
Term s a -> (HRecOf a fs s -> Term s b) -> Term s b
pletFields @'["newDatum", "governorRef"] Term s PMutateGovernorDatum
datum
    HRec
  ((':)
     @(Symbol, Type)
     '("inputs", Term s (PAsData (PBuiltinList (PAsData PTxInInfo))))
     ((':)
        @(Symbol, Type)
        '("outputs", Term s (PAsData (PBuiltinList (PAsData PTxOut))))
        ((':)
           @(Symbol, Type)
           '("mint", Term s (PAsData (PValue 'Sorted 'NoGuarantees)))
           ((':)
              @(Symbol, Type)
              '("datums",
                Term
                  s (PAsData (PBuiltinList (PAsData (PTuple PDatumHash PDatum)))))
              ('[] @(Symbol, Type))))))
txInfoF <- ((HRec
    ((':)
       @(Symbol, Type)
       '("inputs", Term s (PAsData (PBuiltinList (PAsData PTxInInfo))))
       ((':)
          @(Symbol, Type)
          '("outputs", Term s (PAsData (PBuiltinList (PAsData PTxOut))))
          ((':)
             @(Symbol, Type)
             '("mint", Term s (PAsData (PValue 'Sorted 'NoGuarantees)))
             ((':)
                @(Symbol, Type)
                '("datums",
                  Term
                    s (PAsData (PBuiltinList (PAsData (PTuple PDatumHash PDatum)))))
                ('[] @(Symbol, Type))))))
  -> Term s POpaque)
 -> Term s POpaque)
-> TermCont
     @POpaque
     s
     (HRec
        ((':)
           @(Symbol, Type)
           '("inputs", Term s (PAsData (PBuiltinList (PAsData PTxInInfo))))
           ((':)
              @(Symbol, Type)
              '("outputs", Term s (PAsData (PBuiltinList (PAsData PTxOut))))
              ((':)
                 @(Symbol, Type)
                 '("mint", Term s (PAsData (PValue 'Sorted 'NoGuarantees)))
                 ((':)
                    @(Symbol, Type)
                    '("datums",
                      Term
                        s (PAsData (PBuiltinList (PAsData (PTuple PDatumHash PDatum)))))
                    ('[] @(Symbol, Type)))))))
forall a (s :: S) (r :: PType).
((a -> Term s r) -> Term s r) -> TermCont @r s a
tcont (((HRec
     ((':)
        @(Symbol, Type)
        '("inputs", Term s (PAsData (PBuiltinList (PAsData PTxInInfo))))
        ((':)
           @(Symbol, Type)
           '("outputs", Term s (PAsData (PBuiltinList (PAsData PTxOut))))
           ((':)
              @(Symbol, Type)
              '("mint", Term s (PAsData (PValue 'Sorted 'NoGuarantees)))
              ((':)
                 @(Symbol, Type)
                 '("datums",
                   Term
                     s (PAsData (PBuiltinList (PAsData (PTuple PDatumHash PDatum)))))
                 ('[] @(Symbol, Type))))))
   -> Term s POpaque)
  -> Term s POpaque)
 -> TermCont
      @POpaque
      s
      (HRec
         ((':)
            @(Symbol, Type)
            '("inputs", Term s (PAsData (PBuiltinList (PAsData PTxInInfo))))
            ((':)
               @(Symbol, Type)
               '("outputs", Term s (PAsData (PBuiltinList (PAsData PTxOut))))
               ((':)
                  @(Symbol, Type)
                  '("mint", Term s (PAsData (PValue 'Sorted 'NoGuarantees)))
                  ((':)
                     @(Symbol, Type)
                     '("datums",
                       Term
                         s (PAsData (PBuiltinList (PAsData (PTuple PDatumHash PDatum)))))
                     ('[] @(Symbol, Type))))))))
-> ((HRec
       ((':)
          @(Symbol, Type)
          '("inputs", Term s (PAsData (PBuiltinList (PAsData PTxInInfo))))
          ((':)
             @(Symbol, Type)
             '("outputs", Term s (PAsData (PBuiltinList (PAsData PTxOut))))
             ((':)
                @(Symbol, Type)
                '("mint", Term s (PAsData (PValue 'Sorted 'NoGuarantees)))
                ((':)
                   @(Symbol, Type)
                   '("datums",
                     Term
                       s (PAsData (PBuiltinList (PAsData (PTuple PDatumHash PDatum)))))
                   ('[] @(Symbol, Type))))))
     -> Term s POpaque)
    -> Term s POpaque)
-> TermCont
     @POpaque
     s
     (HRec
        ((':)
           @(Symbol, Type)
           '("inputs", Term s (PAsData (PBuiltinList (PAsData PTxInInfo))))
           ((':)
              @(Symbol, Type)
              '("outputs", Term s (PAsData (PBuiltinList (PAsData PTxOut))))
              ((':)
                 @(Symbol, Type)
                 '("mint", Term s (PAsData (PValue 'Sorted 'NoGuarantees)))
                 ((':)
                    @(Symbol, Type)
                    '("datums",
                      Term
                        s (PAsData (PBuiltinList (PAsData (PTuple PDatumHash PDatum)))))
                    ('[] @(Symbol, Type)))))))
forall a b. (a -> b) -> a -> b
$ forall (fs :: [Symbol]) (a :: PType) (s :: S) (b :: PType)
       (ps :: [PLabeledType]) (bs :: [ToBind]).
(PDataFields a,
 (ps :: [PLabeledType]) ~ (PFields a :: [PLabeledType]),
 (bs :: [ToBind]) ~ (Bindings ps fs :: [ToBind]),
 BindFields ps bs) =>
Term s a -> (HRecOf a fs s -> Term s b) -> Term s b
pletFields @'["mint", "inputs", "outputs", "datums"] Term s (PAsData PTxInfo)
txInfo

    let mint :: Term _ (PBuiltinList _)
        mint :: Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol)
        (PAsData (PMap 'Sorted PTokenName (PInteger @S)))))
mint = Term
  s
  (PInner
     (PInner (PValue 'Sorted 'NoGuarantees) (Any @PType)) (Any @PType))
-> forall (b :: PType).
   Term
     s
     (PInner
        (PInner
           (PInner (PValue 'Sorted 'NoGuarantees) (Any @PType)) (Any @PType))
        b)
forall (s :: S) (a :: PType).
Term s a -> forall (b :: PType). Term s (PInner a b)
pto (Term
   s
   (PInner
      (PInner (PValue 'Sorted 'NoGuarantees) (Any @PType)) (Any @PType))
 -> forall (b :: PType).
    Term
      s
      (PInner
         (PInner
            (PInner (PValue 'Sorted 'NoGuarantees) (Any @PType)) (Any @PType))
         b))
-> Term
     s
     (PInner
        (PInner (PValue 'Sorted 'NoGuarantees) (Any @PType)) (Any @PType))
-> forall (b :: PType).
   Term
     s
     (PInner
        (PInner
           (PInner (PValue 'Sorted 'NoGuarantees) (Any @PType)) (Any @PType))
        b)
forall a b. (a -> b) -> a -> b
$ Term s (PInner (PValue 'Sorted 'NoGuarantees) (Any @PType))
-> forall (b :: PType).
   Term
     s (PInner (PInner (PValue 'Sorted 'NoGuarantees) (Any @PType)) b)
forall (s :: S) (a :: PType).
Term s a -> forall (b :: PType). Term s (PInner a b)
pto (Term s (PInner (PValue 'Sorted 'NoGuarantees) (Any @PType))
 -> forall (b :: PType).
    Term
      s (PInner (PInner (PValue 'Sorted 'NoGuarantees) (Any @PType)) b))
-> Term s (PInner (PValue 'Sorted 'NoGuarantees) (Any @PType))
-> forall (b :: PType).
   Term
     s (PInner (PInner (PValue 'Sorted 'NoGuarantees) (Any @PType)) b)
forall a b. (a -> b) -> a -> b
$ Term s (PValue 'Sorted 'NoGuarantees)
-> forall (b :: PType).
   Term s (PInner (PValue 'Sorted 'NoGuarantees) b)
forall (s :: S) (a :: PType).
Term s a -> forall (b :: PType). Term s (PInner a b)
pto (Term s (PValue 'Sorted 'NoGuarantees)
 -> forall (b :: PType).
    Term s (PInner (PValue 'Sorted 'NoGuarantees) b))
-> Term s (PValue 'Sorted 'NoGuarantees)
-> forall (b :: PType).
   Term s (PInner (PValue 'Sorted 'NoGuarantees) b)
forall a b. (a -> b) -> a -> b
$ Term s (PAsData (PValue 'Sorted 'NoGuarantees))
-> Term s (PValue 'Sorted 'NoGuarantees)
forall (a :: PType) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData HRec
  ((':)
     @(Symbol, Type)
     '("inputs", Term s (PAsData (PBuiltinList (PAsData PTxInInfo))))
     ((':)
        @(Symbol, Type)
        '("outputs", Term s (PAsData (PBuiltinList (PAsData PTxOut))))
        ((':)
           @(Symbol, Type)
           '("mint", Term s (PAsData (PValue 'Sorted 'NoGuarantees)))
           ((':)
              @(Symbol, Type)
              '("datums",
                Term
                  s (PAsData (PBuiltinList (PAsData (PTuple PDatumHash PDatum)))))
              ('[] @(Symbol, Type))))))
txInfoF.mint

    Term s (PString @S) -> Term s PBool -> TermCont @POpaque s ()
forall {r :: PType} (s :: S).
Term s (PString @S) -> Term s PBool -> TermCont @r s ()
pguardC Term s (PString @S)
"Nothing should be minted/burnt other than GAT" (Term s PBool -> TermCont @POpaque s ())
-> Term s PBool -> TermCont @POpaque s ()
forall a b. (a -> b) -> a -> b
$
      Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol)
        (PAsData (PMap 'Sorted PTokenName (PInteger @S))))
   :--> PInteger @S)
forall (list :: PType -> PType) (a :: PType) (s :: S).
PIsListLike list a =>
Term s (list a :--> PInteger @S)
plength Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol)
        (PAsData (PMap 'Sorted PTokenName (PInteger @S))))
   :--> PInteger @S)
-> Term
     s
     (PBuiltinList
        (PBuiltinPair
           (PAsData PCurrencySymbol)
           (PAsData (PMap 'Sorted PTokenName (PInteger @S)))))
-> Term s (PInteger @S)
forall (s :: S) (a :: PType) (b :: PType).
Term s (a :--> b) -> Term s a -> Term s b
# Term
  s
  (PBuiltinList
     (PBuiltinPair
        (PAsData PCurrencySymbol)
        (PAsData (PMap 'Sorted PTokenName (PInteger @S)))))
mint Term s (PInteger @S) -> Term s (PInteger @S) -> Term s PBool
forall (t :: PType) (s :: S).
PEq t =>
Term s t -> Term s t -> Term s PBool
#== Term s (PInteger @S)
1

    -- Only two script inputs are alloed: one from the effect, one from the governor.
    Term s (PString @S) -> Term s PBool -> TermCont @POpaque s ()
forall {r :: PType} (s :: S).
Term s (PString @S) -> Term s PBool -> TermCont @r s ()
pguardC Term s (PString @S)
"Only self and governor script inputs are allowed" (Term s PBool -> TermCont @POpaque s ())
-> Term s PBool -> TermCont @POpaque s ()
forall a b. (a -> b) -> a -> b
$
      Term
  s
  ((PAsData PTxInInfo :--> (PInteger @S :--> PInteger @S))
   :--> (PInteger @S
         :--> (PBuiltinList (PAsData PTxInInfo) :--> PInteger @S)))
forall (list :: PType -> PType) (a :: PType) (s :: S) (b :: PType).
PIsListLike list a =>
Term s ((a :--> (b :--> b)) :--> (b :--> (list a :--> b)))
pfoldr
        # phoistAcyclic
          ( plam $ \inInfo count ->
              let address = pfield @"address" #$ pfield @"resolved" # inInfo
               in pif
                    (isScriptAddress # address)
                    (count + 1)
                    count
          )
        # (0 :: Term _ PInteger)
        # pfromData txInfoF.inputs
        #== 2

    -- Find the governor input by looking for GST.
    let inputWithGST :: Term s (PAsData PTxInInfo)
inputWithGST =
          Term
  s
  (PString @S
   :--> (PMaybe (PAsData PTxInInfo) :--> PAsData PTxInInfo))
forall (a :: PType) (s :: S).
Term s (PString @S :--> (PMaybe a :--> a))
mustBePJust Term
  s
  (PString @S
   :--> (PMaybe (PAsData PTxInInfo) :--> PAsData PTxInInfo))
-> Term s (PString @S)
-> Term s (PMaybe (PAsData PTxInInfo) :--> PAsData PTxInInfo)
forall (s :: S) (a :: PType) (b :: PType).
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PString @S)
"Governor input not found" Term s (PMaybe (PAsData PTxInInfo) :--> PAsData PTxInInfo)
-> Term s (PMaybe (PAsData PTxInInfo))
-> Term s (PAsData PTxInInfo)
forall (s :: S) (a :: PType) (b :: PType).
Term s (a :--> b) -> Term s a -> Term s b
#$ Term
  s
  ((PAsData PTxInInfo :--> PBool)
   :--> (PBuiltinList (PAsData PTxInInfo)
         :--> PMaybe (PAsData PTxInInfo)))
forall (l :: PType -> PType) (a :: PType) (s :: S).
PIsListLike l a =>
Term s ((a :--> PBool) :--> (l a :--> PMaybe a))
pfind
            # phoistAcyclic
              ( plam $ \inInfo ->
                  let value = pfield @"value" #$ pfield @"resolved" # inInfo
                   in gstValueOf # value #== 1
              )
            # pfromData txInfoF.inputs

    HRec
  (BoundTerms
     (PFields (PAsData PTxInInfo))
     (Bindings
        (PFields (PAsData PTxInInfo))
        ((':) @Symbol "outRef" ((':) @Symbol "resolved" ('[] @Symbol))))
     s)
govInInfo <- ((HRec
    (BoundTerms
       (PFields (PAsData PTxInInfo))
       (Bindings
          (PFields (PAsData PTxInInfo))
          ((':) @Symbol "outRef" ((':) @Symbol "resolved" ('[] @Symbol))))
       s)
  -> Term s POpaque)
 -> Term s POpaque)
-> TermCont
     @POpaque
     s
     (HRec
        (BoundTerms
           (PFields (PAsData PTxInInfo))
           (Bindings
              (PFields (PAsData PTxInInfo))
              ((':) @Symbol "outRef" ((':) @Symbol "resolved" ('[] @Symbol))))
           s))
forall a (s :: S) (r :: PType).
((a -> Term s r) -> Term s r) -> TermCont @r s a
tcont (((HRec
     (BoundTerms
        (PFields (PAsData PTxInInfo))
        (Bindings
           (PFields (PAsData PTxInInfo))
           ((':) @Symbol "outRef" ((':) @Symbol "resolved" ('[] @Symbol))))
        s)
   -> Term s POpaque)
  -> Term s POpaque)
 -> TermCont
      @POpaque
      s
      (HRec
         (BoundTerms
            (PFields (PAsData PTxInInfo))
            (Bindings
               (PFields (PAsData PTxInInfo))
               ((':) @Symbol "outRef" ((':) @Symbol "resolved" ('[] @Symbol))))
            s)))
-> ((HRec
       (BoundTerms
          (PFields (PAsData PTxInInfo))
          (Bindings
             (PFields (PAsData PTxInInfo))
             ((':) @Symbol "outRef" ((':) @Symbol "resolved" ('[] @Symbol))))
          s)
     -> Term s POpaque)
    -> Term s POpaque)
-> TermCont
     @POpaque
     s
     (HRec
        (BoundTerms
           (PFields (PAsData PTxInInfo))
           (Bindings
              (PFields (PAsData PTxInInfo))
              ((':) @Symbol "outRef" ((':) @Symbol "resolved" ('[] @Symbol))))
           s))
forall a b. (a -> b) -> a -> b
$ forall (fs :: [Symbol]) (a :: PType) (s :: S) (b :: PType)
       (ps :: [PLabeledType]) (bs :: [ToBind]).
(PDataFields a,
 (ps :: [PLabeledType]) ~ (PFields a :: [PLabeledType]),
 (bs :: [ToBind]) ~ (Bindings ps fs :: [ToBind]),
 BindFields ps bs) =>
Term s a -> (HRecOf a fs s -> Term s b) -> Term s b
pletFields @'["outRef", "resolved"] (Term s (PAsData PTxInInfo)
 -> (HRec
       (BoundTerms
          (PFields (PAsData PTxInInfo))
          (Bindings
             (PFields (PAsData PTxInInfo))
             ((':) @Symbol "outRef" ((':) @Symbol "resolved" ('[] @Symbol))))
          s)
     -> Term s POpaque)
 -> Term s POpaque)
-> Term s (PAsData PTxInInfo)
-> (HRec
      (BoundTerms
         (PFields (PAsData PTxInInfo))
         (Bindings
            (PFields (PAsData PTxInInfo))
            ((':) @Symbol "outRef" ((':) @Symbol "resolved" ('[] @Symbol))))
         s)
    -> Term s POpaque)
-> Term s POpaque
forall a b. (a -> b) -> a -> b
$ Term s (PAsData PTxInInfo)
inputWithGST

    -- The effect can only modify the governor UTXO referenced in the datum.
    Term s (PString @S) -> Term s PBool -> TermCont @POpaque s ()
forall {r :: PType} (s :: S).
Term s (PString @S) -> Term s PBool -> TermCont @r s ()
pguardC Term s (PString @S)
"Can only modify the pinned governor" (Term s PBool -> TermCont @POpaque s ())
-> Term s PBool -> TermCont @POpaque s ()
forall a b. (a -> b) -> a -> b
$
      HRec
  (BoundTerms
     (PFields (PAsData PTxInInfo))
     (Bindings
        (PFields (PAsData PTxInInfo))
        ((':) @Symbol "outRef" ((':) @Symbol "resolved" ('[] @Symbol))))
     s)
govInInfo.outRef Term s (PAsData PTxOutRef)
-> Term s (PAsData PTxOutRef) -> Term s PBool
forall (t :: PType) (s :: S).
PEq t =>
Term s t -> Term s t -> Term s PBool
#== HRec
  ((':)
     @(Symbol, Type)
     '("governorRef", Term s (PAsData PTxOutRef))
     ((':)
        @(Symbol, Type)
        '("newDatum", Term s (PAsData PGovernorDatum))
        ('[] @(Symbol, Type))))
datumF.governorRef

    -- The transaction can only have one output, which should be sent to the governor.
    Term s (PString @S) -> Term s PBool -> TermCont @POpaque s ()
forall {r :: PType} (s :: S).
Term s (PString @S) -> Term s PBool -> TermCont @r s ()
pguardC Term s (PString @S)
"Only governor output is allowed" (Term s PBool -> TermCont @POpaque s ())
-> Term s PBool -> TermCont @POpaque s ()
forall a b. (a -> b) -> a -> b
$
      Term s (PBuiltinList (PAsData PTxOut) :--> PInteger @S)
forall (list :: PType -> PType) (a :: PType) (s :: S).
PIsListLike list a =>
Term s (list a :--> PInteger @S)
plength Term s (PBuiltinList (PAsData PTxOut) :--> PInteger @S)
-> Term s (PBuiltinList (PAsData PTxOut)) -> Term s (PInteger @S)
forall (s :: S) (a :: PType) (b :: PType).
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PAsData (PBuiltinList (PAsData PTxOut)))
-> Term s (PBuiltinList (PAsData PTxOut))
forall (a :: PType) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData HRec
  ((':)
     @(Symbol, Type)
     '("inputs", Term s (PAsData (PBuiltinList (PAsData PTxInInfo))))
     ((':)
        @(Symbol, Type)
        '("outputs", Term s (PAsData (PBuiltinList (PAsData PTxOut))))
        ((':)
           @(Symbol, Type)
           '("mint", Term s (PAsData (PValue 'Sorted 'NoGuarantees)))
           ((':)
              @(Symbol, Type)
              '("datums",
                Term
                  s (PAsData (PBuiltinList (PAsData (PTuple PDatumHash PDatum)))))
              ('[] @(Symbol, Type))))))
txInfoF.outputs Term s (PInteger @S) -> Term s (PInteger @S) -> Term s PBool
forall (t :: PType) (s :: S).
PEq t =>
Term s t -> Term s t -> Term s PBool
#== Term s (PInteger @S)
1

    let govAddress :: Term
  s
  (PAsData
     (PUnLabel
        (IndexList
           @PLabeledType
           (PLabelIndex "address" (PFields (PAsData PTxOut)))
           (PFields (PAsData PTxOut)))))
govAddress = forall (name :: Symbol) (p :: PType) (s :: S) (a :: PType)
       (as :: [PLabeledType]) (n :: Nat) (b :: PType).
(PDataFields p,
 (as :: [PLabeledType]) ~ (PFields p :: [PLabeledType]),
 (n :: Nat) ~ (PLabelIndex name as :: Nat), KnownNat n,
 (a :: PType) ~ (PUnLabel (IndexList @PLabeledType n as) :: PType),
 PFromDataable a b) =>
Term s (p :--> b)
pfield @"address" Term
  s
  (PAsData PTxOut
   :--> PAsData
          (PUnLabel
             (IndexList
                @PLabeledType
                (PLabelIndex "address" (PFields (PAsData PTxOut)))
                (PFields (PAsData PTxOut)))))
-> Term s (PAsData PTxOut)
-> Term
     s
     (PAsData
        (PUnLabel
           (IndexList
              @PLabeledType
              (PLabelIndex "address" (PFields (PAsData PTxOut)))
              (PFields (PAsData PTxOut)))))
forall (s :: S) (a :: PType) (b :: PType).
Term s (a :--> b) -> Term s a -> Term s b
#$ HRec
  (BoundTerms
     (PFields (PAsData PTxInInfo))
     (Bindings
        (PFields (PAsData PTxInInfo))
        ((':) @Symbol "outRef" ((':) @Symbol "resolved" ('[] @Symbol))))
     s)
govInInfo.resolved
        govOutput' :: Term s PTxOut
govOutput' = Term s (PAsData PTxOut) -> Term s PTxOut
forall (a :: PType) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData (Term s (PAsData PTxOut) -> Term s PTxOut)
-> Term s (PAsData PTxOut) -> Term s PTxOut
forall a b. (a -> b) -> a -> b
$ Term s (PBuiltinList (PAsData PTxOut) :--> PAsData PTxOut)
forall (list :: PType -> PType) (a :: PType) (s :: S).
(PListLike list, PElemConstraint list a) =>
Term s (list a :--> a)
phead Term s (PBuiltinList (PAsData PTxOut) :--> PAsData PTxOut)
-> Term s (PBuiltinList (PAsData PTxOut))
-> Term s (PAsData PTxOut)
forall (s :: S) (a :: PType) (b :: PType).
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PAsData (PBuiltinList (PAsData PTxOut)))
-> Term s (PBuiltinList (PAsData PTxOut))
forall (a :: PType) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData HRec
  ((':)
     @(Symbol, Type)
     '("inputs", Term s (PAsData (PBuiltinList (PAsData PTxInInfo))))
     ((':)
        @(Symbol, Type)
        '("outputs", Term s (PAsData (PBuiltinList (PAsData PTxOut))))
        ((':)
           @(Symbol, Type)
           '("mint", Term s (PAsData (PValue 'Sorted 'NoGuarantees)))
           ((':)
              @(Symbol, Type)
              '("datums",
                Term
                  s (PAsData (PBuiltinList (PAsData (PTuple PDatumHash PDatum)))))
              ('[] @(Symbol, Type))))))
txInfoF.outputs

    HRec
  (BoundTerms
     (PFields PTxOut)
     (Bindings
        (PFields PTxOut)
        ((':)
           @Symbol
           "address"
           ((':) @Symbol "value" ((':) @Symbol "datumHash" ('[] @Symbol)))))
     s)
govOutput <- ((HRec
    (BoundTerms
       (PFields PTxOut)
       (Bindings
          (PFields PTxOut)
          ((':)
             @Symbol
             "address"
             ((':) @Symbol "value" ((':) @Symbol "datumHash" ('[] @Symbol)))))
       s)
  -> Term s POpaque)
 -> Term s POpaque)
-> TermCont
     @POpaque
     s
     (HRec
        (BoundTerms
           (PFields PTxOut)
           (Bindings
              (PFields PTxOut)
              ((':)
                 @Symbol
                 "address"
                 ((':) @Symbol "value" ((':) @Symbol "datumHash" ('[] @Symbol)))))
           s))
forall a (s :: S) (r :: PType).
((a -> Term s r) -> Term s r) -> TermCont @r s a
tcont (((HRec
     (BoundTerms
        (PFields PTxOut)
        (Bindings
           (PFields PTxOut)
           ((':)
              @Symbol
              "address"
              ((':) @Symbol "value" ((':) @Symbol "datumHash" ('[] @Symbol)))))
        s)
   -> Term s POpaque)
  -> Term s POpaque)
 -> TermCont
      @POpaque
      s
      (HRec
         (BoundTerms
            (PFields PTxOut)
            (Bindings
               (PFields PTxOut)
               ((':)
                  @Symbol
                  "address"
                  ((':) @Symbol "value" ((':) @Symbol "datumHash" ('[] @Symbol)))))
            s)))
-> ((HRec
       (BoundTerms
          (PFields PTxOut)
          (Bindings
             (PFields PTxOut)
             ((':)
                @Symbol
                "address"
                ((':) @Symbol "value" ((':) @Symbol "datumHash" ('[] @Symbol)))))
          s)
     -> Term s POpaque)
    -> Term s POpaque)
-> TermCont
     @POpaque
     s
     (HRec
        (BoundTerms
           (PFields PTxOut)
           (Bindings
              (PFields PTxOut)
              ((':)
                 @Symbol
                 "address"
                 ((':) @Symbol "value" ((':) @Symbol "datumHash" ('[] @Symbol)))))
           s))
forall a b. (a -> b) -> a -> b
$ forall (fs :: [Symbol]) (a :: PType) (s :: S) (b :: PType)
       (ps :: [PLabeledType]) (bs :: [ToBind]).
(PDataFields a,
 (ps :: [PLabeledType]) ~ (PFields a :: [PLabeledType]),
 (bs :: [ToBind]) ~ (Bindings ps fs :: [ToBind]),
 BindFields ps bs) =>
Term s a -> (HRecOf a fs s -> Term s b) -> Term s b
pletFields @'["address", "value", "datumHash"] Term s PTxOut
govOutput'

    Term s (PString @S) -> Term s PBool -> TermCont @POpaque s ()
forall {r :: PType} (s :: S).
Term s (PString @S) -> Term s PBool -> TermCont @r s ()
pguardC Term s (PString @S)
"No output to the governor" (Term s PBool -> TermCont @POpaque s ())
-> Term s PBool -> TermCont @POpaque s ()
forall a b. (a -> b) -> a -> b
$
      HRec
  (BoundTerms
     (PFields PTxOut)
     (Bindings
        (PFields PTxOut)
        ((':)
           @Symbol
           "address"
           ((':) @Symbol "value" ((':) @Symbol "datumHash" ('[] @Symbol)))))
     s)
govOutput.address Term
  s
  (PAsData
     (PUnLabel
        (IndexList
           @PLabeledType
           (PLabelIndex "address" (PFields (PAsData PTxOut)))
           (PFields (PAsData PTxOut)))))
-> Term
     s
     (PAsData
        (PUnLabel
           (IndexList
              @PLabeledType
              (PLabelIndex "address" (PFields (PAsData PTxOut)))
              (PFields (PAsData PTxOut)))))
-> Term s PBool
forall (t :: PType) (s :: S).
PEq t =>
Term s t -> Term s t -> Term s PBool
#== Term
  s
  (PAsData
     (PUnLabel
        (IndexList
           @PLabeledType
           (PLabelIndex "address" (PFields (PAsData PTxOut)))
           (PFields (PAsData PTxOut)))))
govAddress

    Term s (PString @S) -> Term s PBool -> TermCont @POpaque s ()
forall {r :: PType} (s :: S).
Term s (PString @S) -> Term s PBool -> TermCont @r s ()
pguardC Term s (PString @S)
"Governor output doesn't carry the GST" (Term s PBool -> TermCont @POpaque s ())
-> Term s PBool -> TermCont @POpaque s ()
forall a b. (a -> b) -> a -> b
$
      Term s (PValue 'Sorted 'Positive :--> PInteger @S)
forall (s :: S) {w :: KeyGuarantees} {w :: AmountGuarantees}.
Term s (PValue w w :--> PInteger @S)
gstValueOf Term s (PValue 'Sorted 'Positive :--> PInteger @S)
-> Term s (PValue 'Sorted 'Positive) -> Term s (PInteger @S)
forall (s :: S) (a :: PType) (b :: PType).
Term s (a :--> b) -> Term s a -> Term s b
# HRec
  (BoundTerms
     (PFields PTxOut)
     (Bindings
        (PFields PTxOut)
        ((':)
           @Symbol
           "address"
           ((':) @Symbol "value" ((':) @Symbol "datumHash" ('[] @Symbol)))))
     s)
govOutput.value Term s (PInteger @S) -> Term s (PInteger @S) -> Term s PBool
forall (t :: PType) (s :: S).
PEq t =>
Term s t -> Term s t -> Term s PBool
#== Term s (PInteger @S)
1

    let governorOutputDatumHash :: Term s PDatumHash
governorOutputDatumHash =
          Term s (PString @S :--> (PMaybeData PDatumHash :--> PDatumHash))
forall (a :: PType) (s :: S).
PIsData a =>
Term s (PString @S :--> (PMaybeData a :--> a))
mustBePDJust Term s (PString @S :--> (PMaybeData PDatumHash :--> PDatumHash))
-> Term s (PString @S)
-> Term s (PMaybeData PDatumHash :--> PDatumHash)
forall (s :: S) (a :: PType) (b :: PType).
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PString @S)
"Governor output doesn't have datum" Term s (PMaybeData PDatumHash :--> PDatumHash)
-> Term s (PMaybeData PDatumHash) -> Term s PDatumHash
forall (s :: S) (a :: PType) (b :: PType).
Term s (a :--> b) -> Term s a -> Term s b
# HRec
  (BoundTerms
     (PFields PTxOut)
     (Bindings
        (PFields PTxOut)
        ((':)
           @Symbol
           "address"
           ((':) @Symbol "value" ((':) @Symbol "datumHash" ('[] @Symbol)))))
     s)
govOutput.datumHash
        governorOutputDatum :: Term s PGovernorDatum
governorOutputDatum =
          forall (a :: PType) (s :: S).
PIsData a =>
Term s (PAsData a) -> Term s a
pfromData @PGovernorDatum (Term s (PAsData PGovernorDatum) -> Term s PGovernorDatum)
-> Term s (PAsData PGovernorDatum) -> Term s PGovernorDatum
forall a b. (a -> b) -> a -> b
$
            Term
  s
  (PString @S
   :--> (PMaybe (PAsData PGovernorDatum) :--> PAsData PGovernorDatum))
forall (a :: PType) (s :: S).
Term s (PString @S :--> (PMaybe a :--> a))
mustBePJust Term
  s
  (PString @S
   :--> (PMaybe (PAsData PGovernorDatum) :--> PAsData PGovernorDatum))
-> Term s (PString @S)
-> Term
     s (PMaybe (PAsData PGovernorDatum) :--> PAsData PGovernorDatum)
forall (s :: S) (a :: PType) (b :: PType).
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PString @S)
"Governor output datum not found"
              #$ ptryFindDatum # governorOutputDatumHash # txInfoF.datums

    -- Ensure the output governor datum is what we want.
    Term s (PString @S) -> Term s PBool -> TermCont @POpaque s ()
forall {r :: PType} (s :: S).
Term s (PString @S) -> Term s PBool -> TermCont @r s ()
pguardC Term s (PString @S)
"Unexpected governor datum" (Term s PBool -> TermCont @POpaque s ())
-> Term s PBool -> TermCont @POpaque s ()
forall a b. (a -> b) -> a -> b
$ HRec
  ((':)
     @(Symbol, Type)
     '("governorRef", Term s (PAsData PTxOutRef))
     ((':)
        @(Symbol, Type)
        '("newDatum", Term s (PAsData PGovernorDatum))
        ('[] @(Symbol, Type))))
datumF.newDatum Term s PGovernorDatum -> Term s PGovernorDatum -> Term s PBool
forall (t :: PType) (s :: S).
PEq t =>
Term s t -> Term s t -> Term s PBool
#== Term s PGovernorDatum
governorOutputDatum
    Term s (PString @S) -> Term s PBool -> TermCont @POpaque s ()
forall {r :: PType} (s :: S).
Term s (PString @S) -> Term s PBool -> TermCont @r s ()
pguardC Term s (PString @S)
"New governor datum should be valid" (Term s PBool -> TermCont @POpaque s ())
-> Term s PBool -> TermCont @POpaque s ()
forall a b. (a -> b) -> a -> b
$ Term s (PGovernorDatum :--> PBool)
forall (s :: S). Term s (PGovernorDatum :--> PBool)
governorDatumValid Term s (PGovernorDatum :--> PBool)
-> Term s PGovernorDatum -> Term s PBool
forall (s :: S) (a :: PType) (b :: PType).
Term s (a :--> b) -> Term s a -> Term s b
# Term s PGovernorDatum
governorOutputDatum

    Term s POpaque -> TermCont @POpaque s (Term s POpaque)
forall (m :: Type -> Type) a. Monad m => a -> m a
return (Term s POpaque -> TermCont @POpaque s (Term s POpaque))
-> Term s POpaque -> TermCont @POpaque s (Term s POpaque)
forall a b. (a -> b) -> a -> b
$ Term s (PUnit @S) -> Term s POpaque
forall (s :: S) (a :: PType). Term s a -> Term s POpaque
popaque (Term s (PUnit @S) -> Term s POpaque)
-> Term s (PUnit @S) -> Term s POpaque
forall a b. (a -> b) -> a -> b
$ PLifted (PUnit @S) -> Term s (PUnit @S)
forall (p :: PType) (s :: S). PLift p => PLifted p -> Term s p
pconstant ()
  where
    -- Get the amount of GST in the a given value.
    gstValueOf :: Term s (PValue _ _ :--> PInteger)
    gstValueOf :: Term s (PValue w w :--> PInteger @S)
gstValueOf = ClosedTerm (PValue w w :--> PInteger @S)
-> Term s (PValue w w :--> PInteger @S)
forall (a :: PType) (s :: S).
HasCallStack =>
ClosedTerm a -> Term s a
phoistAcyclic (ClosedTerm (PValue w w :--> PInteger @S)
 -> Term s (PValue w w :--> PInteger @S))
-> ClosedTerm (PValue w w :--> PInteger @S)
-> Term s (PValue w w :--> PInteger @S)
forall a b. (a -> b) -> a -> b
$ (Term s (PValue w w) -> Term s (PInteger @S))
-> Term s (PValue w w :--> PInteger @S)
forall a (b :: PType) (s :: S) (c :: PType).
PLamN a b s =>
(Term s c -> a) -> Term s (c :--> b)
plam ((Term s (PValue w w) -> Term s (PInteger @S))
 -> Term s (PValue w w :--> PInteger @S))
-> (Term s (PValue w w) -> Term s (PInteger @S))
-> Term s (PValue w w :--> PInteger @S)
forall a b. (a -> b) -> a -> b
$ \Term s (PValue w w)
v -> Term
  s
  (PValue w w
   :--> (PCurrencySymbol :--> (PTokenName :--> PInteger @S)))
forall (s :: S) (keys :: KeyGuarantees)
       (amounts :: AmountGuarantees).
Term
  s
  (PValue keys amounts
   :--> (PCurrencySymbol :--> (PTokenName :--> PInteger @S)))
pvalueOf Term
  s
  (PValue w w
   :--> (PCurrencySymbol :--> (PTokenName :--> PInteger @S)))
-> Term s (PValue w w)
-> Term s (PCurrencySymbol :--> (PTokenName :--> PInteger @S))
forall (s :: S) (a :: PType) (b :: PType).
Term s (a :--> b) -> Term s a -> Term s b
# Term s (PValue w w)
v Term s (PCurrencySymbol :--> (PTokenName :--> PInteger @S))
-> Term s PCurrencySymbol -> Term s (PTokenName :--> PInteger @S)
forall (s :: S) (a :: PType) (b :: PType).
Term s (a :--> b) -> Term s a -> Term s b
# PLifted PCurrencySymbol -> Term s PCurrencySymbol
forall (p :: PType) (s :: S). PLift p => PLifted p -> Term s p
pconstant PLifted PCurrencySymbol
CurrencySymbol
cs Term s (PTokenName :--> PInteger @S)
-> Term s PTokenName -> Term s (PInteger @S)
forall (s :: S) (a :: PType) (b :: PType).
Term s (a :--> b) -> Term s a -> Term s b
# PLifted PTokenName -> Term s PTokenName
forall (p :: PType) (s :: S). PLift p => PLifted p -> Term s p
pconstant PLifted PTokenName
TokenName
tn
      where
        AssetClass (CurrencySymbol
cs, TokenName
tn) = Governor -> AssetClass
governorSTAssetClassFromGovernor Governor
gov