# Introduction

Gentle reader,&#x20;

Welcome to this Plutus course. The course aims to teach you the basics of Plutus for Cardano smart contract development. This course will use `PlutusV2` and the latest `cardano-node` version (`8.1.2`). To get the most out of the course, it is recommended to have an understanding of the fundamentals of Haskell and the basic usage of `cardano-cli`. To get started with Haskell, you may want to follow the [Introduction to Haskell video series](https://www.youtube.com/playlist?list=PLAoT_AQC5nO_2bMR85RJksJgcKlvIRKRQ) or [the GitBook version of the course](https://haskell.hpmeducation.com/).

Before starting any practical work with the so-called smart contracts, it is extremely important to have a good understanding of the underlying accounting model used on Cardano - the Extended Unspent Transaction Output model called EUTxO.


# Introduction to the EUTxO model

In this section, you will find an overview of the EUTxO accounting model that is used by the Cardano blockchain ledger. We will start with a brief overview of the previously used UTxO model originating from Bitcoin, and then proceed to the extensions of that model that Cardano implemented along with some of its key features relating to smart contracts.


# The UTxO (Unspent Transaction Output) model

To get started with Plutus and smart contracts on Cardano, it is important to understand the underlying accounting (ledger) model it uses. Before the Mary era, Cardano used Bitcoins' UTxO (Unspent Transaction Output) model.

In the UTxO model, transactions **consist of a list of&#x20;*****inputs*** and **a list of&#x20;*****outputs***. Transaction inputs are **existing and unspent transaction outputs** that are being spent by the transaction. Each output is connected to an ***address*** and can only be spent **once**, i.e. it can only be an input to a transaction once. **Every input in a spending transaction is spent in its entirety** and following that, it is no longer an *unspent* transaction output and **cannot** be used as an input anymore. Transactions can have a different number of inputs (*n*) and outputs (*m*). For example, a transaction with one input (`n = 1`) could create one hundred outputs (`m = 100`).

Every UTxO has a value (`value`), which represents a cryptocurrency value, and **a validating function attached** to it. This function serves as its *validator* (`ν`), which enforces rules to decide whether a transaction that attempts to spend it has the right to do so. The transaction provides *redeemers* (`ρ`) that are passed to the validator functions of outputs. As each UTxO is connected to an *address* with a corresponding private and public key pair, the redeemers are signatures by which the transaction is signed using the private keys. If a transaction that attempts to spend an output is signed by that output's address private key, the validation will be successful. In other words, the validation function will evaluate to true: `ν(value, ρ) = true`. A transaction with multiple inputs from different addresses needs to be signed by each of the private keys of the addresses. If the transaction is not signed by the required signature(s), it will not pass validation and will fail.

The UTxO model is a great fit for a distributed ledger as it **does not require any shared global state** for its transactions. Transactions only need to know about their inputs, and multiple transactions dealing with separate inputs are independent and can be executed concurrently. However, the transaction functionalities of these simple validators are limited, hence Cardano has implemented an extension to the UTxO model that allows more expressive validators while preserving the core properties of the UTxO model, called the *EUTxO (Extended UTxO) model*.


# The EUTxO model (Extended UTxO) model

## Extensions to the UTxO model

To allow more expressive validators, the EUTxO model extends the UTxOs format by adding a ***datum*** (`δ`) field to transaction outputs. A datum is an arbitrary piece of data sitting at the specific UTxO. The datum generally represents a state and allows contracts to maintain their state, still avoiding a shared global state of the entire system. During validation, the datum of the UTxO in question is passed to the validator. Therefore, the UTxO format is extended from `(ν, value)` to `(ν, value, δ)`.

In addition to the above extension in the EUTxO model, **the validating function** or **validator** or **validator script** also **receives the entire transaction** being validated. We call this the transaction ***context***. This allows the validator to enforce validity constraints based not only on the input in question but the entire consuming transaction with all of its inputs, outputs, signatures, and certificates.

Therefore, the validating function from the UTxO model which received just the redeemer (a simple signature): `ν(value, ρ) = true`; becomes more complex: `ν(value, δ, ρ, tx) = true`. It now receives the **datum** `δ` sitting at the UTxO being spent in the transaction, the **redeemer** `ρ`, which now generally contains the instruction or the intent of the spending transaction rather than the spenders' signature. The redeemer itself is no longer required to carry the signature, as any signatures in the transaction will be included and available for inspection in its **context** `tx`.

The final change in the EUTxO model is the addition of a ***validity interval*** for transactions. This interval specifies the length of time during which the transaction ***can*** be processed. It is a fundamental check that happens before the validator script even runs. In Cardano, the validity intervals are represented via **slots**, and each slot currently represents 1 second.

### Where are the validator and datum stored?

We mentioned that in the EUTxO model, transaction outputs can have an arbitrary piece of data attached to them called `datum`. In the ledger, they are actually stored as cryptographic hashes of the actual `datum` object to keep outputs as small as possible memory-wise. When an output with a `datum` attached to it is being spent in a transaction, the transaction must provide the actual `datum` object in its context. The transaction will only be able to pass validation if the provided `datum` matches the hash that sits at the corresponding output. Note that there is also the ***inlinable datum*** functionality on Cardano now (part of Plutus V2), which is limited to simple datum objects but allows storing them in the ledger in full rather than just the hash. Therefore, outputs with inline datums do not require the datum object in the transaction itself, as it is already accessible from the ledger.

The same principle is applied to validator scripts, which are stored in the ledger as their cryptographic hashes. When a transaction wants to use the validator script, it must provide it as part of the transaction (in the case of Cardano as a **Plutus script file**). The hash of the script again must match the hash that exists in the ledger for the transaction to be able to pass validation. Another note here is that with Plutus V2 came the ***reference script*** functionality. It allows a validator script to be attached to a transaction once and can be referenced in future transactions without providing the full script to the transaction. Before reference scripts, the validator script needed to be attached to each transaction that wanted to use it, which greatly increased the transaction size.&#x20;

### Validity rules for transactions in the EUTxO model

Any transaction in the EUTxO model must satisfy the following validity rules in order to be successful:

1. The current tick is within the validity interval\
   `currentTick ∈ t.validityInterval`
2. All outputs have non-negative values\
   `For all o ∈ t.outputs, o.value ≥ 0`
3. All inputs refer to unspent outputs\
   `{i.outputRef : i ∈ t.inputs} ⊆ unspentOutputs(l)`
4. Value is preserved\
   `Sum of all input values = Sum of all output values - Tx fee`
5. No output is double spent\
   `If i1, i2 ∈ t.inputs and i1.outputRef = i2.outputRef then i1 = i2`
6. All inputs validate\
   `For all i ∈ t.inputs, [i.validator] (i.datum, i.redeemer , toData(toContext(t, i, l))) = true`
7. Validator scripts match output addresses\
   `For all i ∈ t.inputs, scriptAddr(i.validator) = getSpentOutput(i, l).addr`
8. Each datum matches its output hash\
   `For all i ∈ t.inputs, dataHash(i.datum) = getSpentOutput(i, l).datumHash`

### Custom Native Tokens in the EUTxO model

The EUTxO model ledger running on Cardano directly supports native custom tokens, including their **forging (minting)**, **burning,** and **transfer**. In IOG research papers, this model is referred to as ***EUTxOma*** (***ma*** stands for *multi-asset*) and is the combination of the above-described EUTxO model and the ***UTxOma*** model, which was introduced in Cardano in the Mary era, and supported custom native tokens on the ledger level via their ***forging policy scripts***.

The UTxOma model generalised the `value` field by making it a two-level structure of ***asset group*** and ***currency*** together called a ***token bundle***. One asset group can have multiple currencies. An example of a token bundle would be: `{CoinGroup1 → {CoinCurrency → 3}, CoinGroup2 → {t1 → 1, t2 → 1}}`, which contains three `CoinCurrency` tokens of the `CoinGroup1` asset group, and one of `t1` and `t2` currencies of the `CoinGroup2` asset group.

### Constraint Emitting machines (CEMs)

Arguably the most important functionality of the EUTxO model is the possibility of implementing validators as ***Constraint Emitting Machines***. These are [state machines](https://en.wikipedia.org/wiki/Finite-state_machine) that can have a finite or infinite number of valid states. Their important feature is the possibility of emitting constraints that transactions must fulfil to interact with the validator. That is, given a certain CEM state of the validator, the validator on-chain code can tell the transaction-building client which transitions to new states are allowed and in what fashion.

### State Thread Tokens

Specifically for smart contracts, the merge of the EUTxO and UTxOma models allows validators to create so-called ***state thread tokens*** (a form of NFTs), allowing even more functionality to be transferred from off-chain to on-chain code, increasing security and simplicity of application implementations. In particular, state thread tokens are used as unique identifiers of specific validator runs, i.e. used to distinguish between different output threads created by the same validator. Moreover, the minting transaction of the state thread token specifies the definite state that the validator thread was initiated with.

This is done in a way that a validator implementing a CEM also implements a forging policy for the state thread token. The forging policy enforces rules to ensure that the token is locked by the same validator and that it can only be minted in a valid initial state (specifically, that the datum attached to the NFT output corresponds to a valid initial state). Upon any further interaction, the validator will check that the state thread token is still present and propagated to the new state if a valid transition occurs. Finally, the state thread token is burnt if the spending transaction transitions the CEM into a final state at which point no further interaction is possible with that specific thread.


# What is Plutus?

Plutus is generally referred to as the smart contract language for Cardano. But IOG engineers more often refer to it as the *Plutus Platform*, which is made up of several different parts that enable writing applications that interact with the Cardano blockchain and take advantage of the validator script capabilities of the EUTxO model.

The Plutus Platform can therefore be separated into two main parts:

**1) The Plutus Foundation**

The Plutus Foundation provides the ledger with a way of specifying and executing scripts. This is done through a programming language called ***Plutus Core***. Plutus Core is a small low-level functional programming language that acts as an on-chain *"assembly language"*. Because it is so low-level, it is not meant to be written by developers. Instead, it is a compilation target with the idea of writing Haskell (or another higher-level language) code that gets compiled down to Plutus Core for on-chain execution. This is where ***PlutusTx*** comes in as it provides a mechanism for compiling Haskell to Plutus Core. PlutusTx contains the libraries and the compiler for such compilations, and their results form the on-chain parts of smart contract applications.

**2) The Plutus Application Framework**

The Plutus Application Framework provides support tools for writing applications in Plutus. It consists of several different tools such as:

*Contract API* - a component that provides an interface for writing the off-chain parts of Plutus applications. A useful tool that goes along is the *Contract monad emulator* which is used to emulate a blockchain for testing contract instances.

*Plutus Application Backend (PAB)* - a web server library that manages the state of Plutus contract instances and executes the off-chain components of Plutus applications. It does so by interacting with the *cardano-wallet* backend and *cardano-node* components while providing a client/application interface for the Plutus application. It is not really production-ready yet because only the hosted option is available, which means the backend must hold all the wallet keys. We will not be using PAB in this course but it is worth mentioning it for the future.

*Various other libraries* - provide a full framework for writing Plutus applications. A full list can be found [here](https://plutus-apps.readthedocs.io/en/latest/plutus/explanations/plutus-tools-component-descriptions.html#plutus-tools-in-development).

All these tools are located in the [plutus-apps\_ repository](https://github.com/intersectMBO/plutus-apps).

<figure><img src="https://2631579069-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FnmBb9HUhFFwIlTQOxWlj%2Fuploads%2F5UlRowKfzzYSMzVu4qK5%2Fimage.png?alt=media&amp;token=310c2678-48fa-471f-b814-8faebde3f040" alt=""><figcaption><p>A high-level architecture of the Plutus Platform, with an emphasis on applications (<a href="https://ci.iog.io/build/65553/download/1/plutus.pdf">https://ci.iog.io/build/65553/download/1/plutus.pdf</a>).</p></figcaption></figure>

###

###


# System requirements for this course

To fully follow the course, you will need a running `cardano-node` instance on one of the Cardano testnets (preferably `preview`). The `cardano-node` instance is required to actually interact with and test the scripts you build. The other requirement is having an environment for writing and compiling Plutus scripts. Together, these two roughly add up to the following two minimal system requirements:

* working memory: 8 GB RAM
* disk space: 40 GB would be the minimum, 60-80 GB recommended

### Setting up cardano-node

There are many ways to set up a `cardano-node`. This guide favours the use of the guild operators' guide: [https://cardano-community.github.io/guild-operators](https://cardano-community.github.io/guild-operators/). To avoid building the binaries yourself, you can use the already compiled binaries from IOG (found on the `cardano-node` release pages) instead. This is also explained in the guild operators' guide. A short video will be available that follows the instructions as well.


# Setting up your Plutus development environment

This guide will cover setting up the environment for writing and compiling Plutus scripts. It does not include any of the development components such as the PAB. The guide is written for the Ubuntu OS but uses Nix (as favoured by IOG) so it should be easily replicated on other systems.

To set up a Plutus environment, we need a `cabal.project` file that will specify the dependencies required to develop Plutus scripts. It is important to note that both the [plutus](https://github.com/intersectMBO/plutus) and [plutus-apps](https://github.com/intersectMBO/plutus-apps) repositories are constantly under development with new releases. Combined with releases of cardano-node and cardano-wallet, this may cause various complications with regard to compatibility between the components.

Therefore, we will use the following repository as a reference, which seems to be a stable and reasonably up-to-date way to get started: <https://github.com/james-iohk/plutus-scripts>. Besides providing us with the `cabal.project` template, it also contains various Plutus scripts which serve as a good reference when learning.

In particular, the `cabal.project` file specifies a commit in the `plutus-apps` repository along with its compatible versions of dependencies such as `cardano-node` and `cardano-wallet` that we can use to build our `nix-shell` and start writing and compiling Plutus scripts.

Here are step-by-step instructions on how to get started:

* Install Nix: the Package Manager from <https://nixos.org/download.html> (after installation we need to reload the terminal session or open a new one in order to have `nix` in our `$PATH`).
* Configure Nix cache: Add the following lines to `/etc/nix/nix.conf` (from <https://github.com/intersectMBO/plutus-apps/blob/main/CONTRIBUTING.adoc>):

```nix
substituters = https://cache.zw3rk.com https://cache.iog.io https://cache.nixos.org/
trusted-public-keys = loony-tools:pr9m4BkM/5/eSTZlkQyRt57Jz7OMBxNSUiMC4FkcNfk= hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
extra-experimental-features = nix-command flakes
```

* After editing the Nix configuration file `nix.conf`, we need to restart the Nix daemon to apply the changes. We can send a SIGKILL signal to trigger a restart:

```
sudo pkill nix-daemon
```

* Clone the `plutus-apps` repository: <https://github.com/intersectMBO/plutus-apps>:

```git
git clone https://github.com/intersectMBO/plutus-apps
```

* Clone the `plutus-scripts` repository as well: <https://github.com/james-iohk/plutus-scripts>:

```git
git clone https://github.com/james-iohk/plutus-scripts
```

* Find the `plutus-apps` commit hash from its `plutus-scripts/cabal.project` file
* Checkout to the specified commit inside `plutus-apps`, e.g.:

```bash
cd plutus-apps
git checkout 65ddfa5d467ed64f8709d7db9faf96151942da82
```

* Enter a `nix-shell` from inside the `plutus-apps` repository: `nix-shell` (for verbose output `nix-shell -vvv`). With verbose output, we should see some cache references in the output if we correctly configured the cache config, e.g.:

```bash
finished download of 'https://cache.zw3rk.com/nar/159x1j930z2fs9frii74fsanza6h0hg0h35i2q825nj3qa43gp13.nar.zst'; curl status = 0, HTTP status = 200, body = 44600355 bytes
```

* Now that we are inside a Nix shell created from the `plutus-apps` repo, navigate back to `plutus-scripts` directory where `cabal.project` is located and run `cabal update`:

```
cabal update
```

* We should now be able to run `cabal build` - this will compile all the script examples from the `plutus-scripts` repository which means your development environment works - you can compile Plutus scripts!

```
cabal build
```

* We should also be able to use `cabal repl` which gives you an interactive GHCi REPL in which you can use PlutusTx.

```
cabal repl
```

Before that, we will go over the project files `cabal.project` and `plutus-scripts.cabal`.


# Cabal project files

A cabal project normally consists of two configuration files:

1. `<project_name>.cabal` - defines the project metadata.
2. `cabal.project` - defines the build configuration options of the project.

### \<project\_name>.cabal

[*Reference*](https://cabal.readthedocs.io/en/3.10/cabal-projectindex.html)

Let's start with the `project.cabal` file. This file is named as `<project_name>.cabal`. We will use the `plutus-scripts` files as examples so this file is `plutus-scripts.cabal`. The first line of the file states the `Cabal-Version` of the project which is the specification version that this package description uses. The following lines contain some basic metadata about the project (author, licence, etc...):

```haskell
# plutus-scripts/plutus-scripts.cabal

Cabal-Version:      2.4
Name:               plutus-script
Version:            0.1.0.0
Author:             James Browning
Maintainer:         james.browning@iohk.io
Build-Type:         Simple
Copyright:          © 2022 James Browning
License:            Apache-2.0
License-files:      LICENSE
```

After that, we get the definition of the project type. A project can be a `library` or an `executable`. It can also be both of those. The `plutus-scripts` project is a `library` with source code located in the `src` directory and exposes the listed modules:

```haskell
...
library
  hs-source-dirs:      src
  exposed-modules:     UntypedHelloWorld
                     , TypedDatumRedeemer42
                     , Deadline
                     ...
```

The next section `build-depends` specifies the *library* dependencies required to build the project. Dependencies can have specific versions specified:

```haskell
...
    build-depends:     aeson
                     , base ^>=4.14.1.0
                     , bytestring
                     , containers
                     ...
```

The following two options `default-language` and `ghc-options` specify the language specification to use (in this case `Haskell2010`), and the GHC options for the compiler to use when building the project:

```haskell
...
  default-language:    Haskell2010
  ghc-options:         -Wall -fobject-code -fno-ignore-interface-pragmas ...
```

### cabal.project

[*Reference*](https://cabal.readthedocs.io/en/stable/cabal-project.html)

The `cabal.project` file supports a variety of options that configure the details of your build. Perhaps most importantly, it specifies dependencies which are not on Hackage. In `plutus-scripts`, the first definition in the file is for the [Cardano Haskell package repository](https://intersectMBO.github.io/cardano-haskell-packages/) which aims to be the central package repository for Cardano-related packages not found on Hackage.

```haskell
-- Custom repository for cardano haskell packages
-- See https://github.com/intersectMBO/cardano-haskell-packages on how to use CHaP in a Haskell project.
repository cardano-haskell-packages
  url: https://intersectMBO.github.io/cardano-haskell-packages
  secure: True
  root-keys:
    3e0cce471cf09815f930210f7827266fd09045445d65923e6d0238a6cd15126f
    443abb7fb497a134c343faf52f0b659bd7999bc06b7f63fa76dc99d631f9bea1
    a86a1f6ce86c449c46666bda44268677abf29b5b2d2eb5ec7af903ec2f117a82
    bcec67e8e99cabfa7764d75ad9b158d72bfacf70ca1d0ec8bc6b4406d1bf8413
    c00aae8461a256275598500ea0e187588c35a5d5d7454fb57eac18d9edb86a56
    d4a35cd3121aa00d18544bb0ac01c3e1691d618f462c46129271bccf39f7e8ee
```

This instructs `cabal` to look for packages in that repository as well. The `packages` field specifies the list of package locations that contain the local packages to be built by this project. The `index-state` field instructs `cabal` to look for packages in repositories (Hackage/CHaP etc.) with the state of those repositories as it was at the given time.

```haskell
...

packages: plutus-scripts.cabal

index-state: 2022-11-14T00:20:02Z

index-state:
  , hackage.haskell.org 2022-11-14T00:20:02Z
  , cardano-haskell-packages 2022-11-17T04:56:26Z
  
...
```

The `constraints` field defines specific version constraints and can also specify flag settings.

```haskell
...

constraints:
  -- cardano-prelude-0.1.0.0 needs
  , protolude <0.3.1

  -- cardano-ledger-byron-0.1.0.0 needs
  , cardano-binary <1.5.0.1

...
```

A `source-repository-package` field provides a location from where to build a certain dependency that is not found on central repositories such as Hackage or CHaP, as is the case here for `plutus-apps` packages.

```haskell
...

source-repository-package
  type: git
  location: https://github.com/intersectMBO/plutus-apps.git
  tag: 65ddfa5d467ed64f8709d7db9faf96151942da82
  subdir:
    cardano-streaming
    doc
    freer-extras
    marconi
    marconi-mamba
    playground-common
    pab-blockfrost
    plutus-chain-index
    plutus-chain-index-core
    plutus-contract
    plutus-contract-certification
    plutus-example
    plutus-ledger
    plutus-ledger-constraints
    plutus-pab
    plutus-pab-executables
    plutus-script-utils
    plutus-tx-constraints
    plutus-use-cases
    rewindable-index

...
```


# General Notes

### General steps for development

Creating and executing Plutus scripts can be summarised in a couple of steps:

* Write your Plutus on-chain code.
* Serialize your Plutus on-chain code to the [text envelope format](https://intersectMBO.github.io/plutus-apps/main/cardano-api/html/Cardano-Api.html#v:writeFileTextEnvelope) (`cardano-cli` expects this format).
* Create your transaction with the accompanying Plutus script(s). This must include a datum, either through a datum hash or an inlinable datum. Important: any script UTxO without a datum is **UNSPENDABLE**.
* Submit the transaction to execute and test the Plutus script. This needs to include the collateral input to cover costs in case the transaction fails. The transaction should never fail this way except in a very particular edge case where the UTxO trying to be spent has been spent in the meantime before the block with the transaction propagates through the network. Important: Only *regular* address inputs can be used as collateral (those with an associated key pair). **Script address inputs cannot be used as collateral.**
* We will also look at another way of testing Plutus scripts by emulating the blockchain at the end of the course.

### PlutusV2

As mentioned before, we will be writing PlutusV2. The significant changes from PlutusV1 to PlutusV2 are listed below (<https://www.youtube.com/watch?v=0TEKLRR5XPU>):

* Reference inputs (possibility of looking at a `datum` without attempting to spend the associated UTxO)
* Inline datums (able to store a simple datum on the ledger)
* Reference scripts (no need to upload the Plutus script on each transaction, instead reference it from a previous transaction)


# Cabal setup

Let us organise our code for this course project. We will be writing a number of Plutus validators and our project can have the same structure as `plutus-scripts`.

### The .cabal file

We start off by creating a new directory and initialising a cabal project.

```bash
mkdir hpm-validators && cd hpm-validators
cabal init
```

This will create a default cabal project structure for us that looks like this:

<pre class="language-bash"><code class="lang-bash"><strong>├── app
</strong>│   └── Main.hs
├── CHANGELOG.md
└── hpm-validators.cabal
</code></pre>

We will place all our source code in the `src/` directory so let's rename the `app` directory to `src`. Inspecting the `hpm-validators.cabal` file shows that the project was initialised as an executable, but we will be building a library of validators so we can change that to a library and specify the `hs-source-dirs` to `src`. The rest of the file we can simply copy from the `plutus-scripts.cabal` template (most notably the `build-depends` section). Our complete `hpm-validators.cabal` file looks like this:

```haskell
cabal-version:      2.4
name:               hpm-validators
version:            0.1.0.0

-- A short (one-line) description of the package.
-- synopsis:

-- A longer description of the package.
-- description:

-- A URL where users can report bugs.
-- bug-reports:

-- The license under which the package is released.
-- license:

-- The package author(s).
-- author:

-- An email address to which users can send suggestions, bug reports, and patches.
-- maintainer:

-- A copyright notice.
-- copyright:
-- category:
extra-source-files: CHANGELOG.md

library
    hs-source-dirs:      src
    exposed-modules:     SimplestSuccess

    build-depends:       aeson
                        , base ^>=4.14.1.0
                        , bytestring
                        , containers
                        , cardano-api
                        , data-default
                        , freer-extras
                        , plutus-contract
                        , plutus-ledger
                        , plutus-ledger-api
                        , plutus-ledger-constraints
                        , plutus-script-utils
                        , plutus-tx-plugin
                        , plutus-tx
                        , text
                        , serialise
  default-language:    Haskell2010
  ghc-options:         -Wall -fobject-code -fno-ignore-interface-pragmas -fno-omit-interface-pragmas -fno-strictness -fno-spec-constr -fno-specialise

```

Our `exposed-modules:` exposes `SimplestSuccess` as that will be the first validator script we write.

{% hint style="info" %}
Note that there is also an interactive option `cabal init -i` that you can try out.
{% endhint %}

### The cabal.project file

We do not need to think too much about the `cabal.project` file. Simply copy the full file from `plutus-scripts/cabal.project` as it contains all the dependencies we need. For reference, the full file looks like this:

```haskell
-- Custom repository for cardano haskell packages
-- See https://github.com/IntersectMBO/cardano-haskell-packages on how to use CHaP in a Haskell project.
repository cardano-haskell-packages
  url: https://chap.intersectmbo.org
  secure: True
  root-keys:
    3e0cce471cf09815f930210f7827266fd09045445d65923e6d0238a6cd15126f
    443abb7fb497a134c343faf52f0b659bd7999bc06b7f63fa76dc99d631f9bea1
    a86a1f6ce86c449c46666bda44268677abf29b5b2d2eb5ec7af903ec2f117a82
    bcec67e8e99cabfa7764d75ad9b158d72bfacf70ca1d0ec8bc6b4406d1bf8413
    c00aae8461a256275598500ea0e187588c35a5d5d7454fb57eac18d9edb86a56
    d4a35cd3121aa00d18544bb0ac01c3e1691d618f462c46129271bccf39f7e8ee

packages: hpm-validators.cabal

index-state: 2022-11-14T00:20:02Z

index-state:
  , hackage.haskell.org 2022-11-14T00:20:02Z
  , cardano-haskell-packages 2022-11-17T04:56:26Z

-- We never, ever, want this.
write-ghc-environment-files: never

allow-newer:
  -- cardano-ledger packages need aeson >2, the following packages have a
  -- too restictive upper bounds on aeson, so we relax them here. The hackage
  -- trustees can make a revision to these packages cabal file to solve the
  -- issue permanently.
  , ekg:aeson
  , ekg-json:aeson
  , openapi3:aeson
  , servant:aeson
  , servant-client-core:aeson
  , servant-server:aeson

constraints:
  -- cardano-prelude-0.1.0.0 needs
  , protolude <0.3.1

  -- cardano-ledger-byron-0.1.0.0 needs
  , cardano-binary <1.5.0.1

  -- plutus-core-1.0.0.1 needs
  , cardano-crypto-class >2.0.0.0
  , algebraic-graphs <0.7

  -- cardano-ledger-core-0.1.0.0 needs
  , cardano-crypto-class <2.0.0.1

  -- cardano-crypto-class-2.0.0.0.1 needs
  , cardano-prelude <0.1.0.1

  -- dbvar from cardano-wallet needs
  , io-classes <0.3.0.0

  -- newer typed-protocols need io-classes>=0.3.0.0 which is incompatible with dbvar's constraint above
  , typed-protocols==0.1.0.0

-- DELETE
-- The plugin will typically fail when producing Haddock documentation. However,
-- in this instance you can simply tell it to defer any errors to runtime (which
-- will never happen since you're building documentation).
--
-- So, any package using 'PlutusTx.compile' in the code for which you need to
-- generate haddock documentation should use the following 'haddock-options'.
--package plutus-ledger
--  haddock-options: "--optghc=-fplugin-opt PlutusTx.Plugin:defer-errors"
--package plutus-script-utils
--  haddock-options: "--optghc=-fplugin-opt PlutusTx.Plugin:defer-errors"
--package plutus-contract
--  haddock-options: "--optghc=-fplugin-opt PlutusTx.Plugin:defer-errors"

-- These packages appear in our dependency tree and are very slow to build.
-- Empirically, turning off optimization shaves off ~50% build time.
-- It also mildly improves recompilation avoidance.
-- For dev work we don't care about performance so much, so this is okay.
-- package cardano-ledger-alonzo
--   optimization: False
-- package ouroboros-consensus-shelley
--   optimization: False
-- package ouroboros-consensus-cardano
--   optimization: False
-- package cardano-api
--   optimization: False
-- package cardano-wallet
--   optimization: False
-- package cardano-wallet-core
--   optimization: False
-- package cardano-wallet-cli
--   optimization: False
-- package cardano-wallet-launcher
--   optimization: False
-- package cardano-wallet-core-integration
--   optimization: False

-- Waiting for plutus-apps CHaP to be published
source-repository-package
  type: git
  location: https://github.com/intersectMBO/plutus-apps.git
  tag: 65ddfa5d467ed64f8709d7db9faf96151942da82
  subdir:
    cardano-streaming
    doc
    freer-extras
    marconi
    marconi-mamba
    playground-common
    pab-blockfrost
    plutus-chain-index
    plutus-chain-index-core
    plutus-contract
    plutus-contract-certification
    plutus-example
    plutus-ledger
    plutus-ledger-constraints
    plutus-pab
    plutus-pab-executables
    plutus-script-utils
    plutus-tx-constraints
    plutus-use-cases
    rewindable-index

-- Direct dependency.
source-repository-package
    type: git
    location: https://github.com/intersectMBO/quickcheck-dynamic
    tag: c272906361471d684440f76c297e29ab760f6a1e

-- Should follow cardano-wallet.
source-repository-package
    type: git
    location: https://github.com/intersectMBO/cardano-addresses
    tag: b7273a5d3c21f1a003595ebf1e1f79c28cd72513
    subdir:
      -- cardano-addresses-cli
      command-line
      -- cardano-addresses
      core

-- Direct dependency.
-- Compared to others, cardano-wallet doesn't bump dependencies very often.
-- Making it a good place to start when bumping dependencies.
-- As, for example, bumping the node first highly risks breaking API with the wallet.
-- Unless early bug fixes are required, this is fine as the wallet tracks stable releases of the node.
-- And it is indeed nice for plutus-apps to track stable releases of the node too.
--
-- The current version is dated 2022/08/10
source-repository-package
    type: git
    location: https://github.com/intersectMBO/cardano-wallet
    tag: 18a931648550246695c790578d4a55ee2f10463e
    subdir:
      lib/cli
      lib/core
      lib/core-integration
      lib/dbvar
      lib/launcher
      lib/numeric
      lib/shelley
      lib/strict-non-empty-containers
      lib/test-utils
      lib/text-class

-- This is needed because we rely on an unreleased feature
-- https://github.com/intersectMBO/cardano-ledger/pull/3111
source-repository-package
    type: git
    location: https://github.com/intersectMBO/cardano-ledger
    tag: da3e9ae10cf9ef0b805a046c84745f06643583c2
    subdir:
      eras/alonzo/impl
      eras/alonzo/test-suite
      eras/babbage/impl
      eras/babbage/test-suite
      eras/byron/chain/executable-spec
      eras/byron/crypto
      eras/byron/crypto/test
      eras/byron/ledger/executable-spec
      eras/byron/ledger/impl
      eras/byron/ledger/impl/test
      eras/shelley/impl
      eras/shelley/test-suite
      eras/shelley-ma/impl
      eras/shelley-ma/test-suite
      libs/cardano-ledger-core
      libs/cardano-ledger-pretty
      libs/cardano-protocol-tpraos
      libs/cardano-data
      libs/vector-map
      libs/set-algebra
      libs/small-steps
      libs/small-steps-test
      libs/non-integral
```

The project structure that we will create in this course looks like this:

<pre class="language-bash"><code class="lang-bash">hpm-validators
├── cabal.project 
├── CHANGELOG.md
├── compiled                        # Compiled assets and validators 
├── dist-newstyle
├── hpm-validators.cabal
├── src/                            # Haskell source code
│   ├── DeadlineParam.hs
<strong>│   ├── ExploringScriptContext.hs
</strong>│   ├── GuessingGame.hs
│   ├── Helpers/
│   ├── MintingPolicy.hs
│   ├── SharedWallet.hs
│   ├── SharedWalletParam.hs
│   ├── SimplestSuccess.hs
│   └── StakingValidator.hs
└── testnet/                        # Scripts and files for testing validators
    ├── address/
    ├── build-addresses.sh
    ├── DeadlineParam/
    ├── ExploringScriptContext/
    ├── GuessingGame/
    ├── MintingPolicy/
    ├── SharedWallet/
    ├── SharedWalletParam/
    ├── SimplestSuccess/
    └── StakingValidator/
</code></pre>


# The Simplest Script

As mentioned in the [EUTxO overview](/the-eutxo-model/introduction-to-the-eutxo-model/the-eutxo-model-extended-utxo-model), the validator script receives three arguments:

1. `Datum`
2. `Redeemer`
3. `Context`

The Haddock documentation for Plutus specifies the main modules (<https://intersectMBO.github.io/plutus/master/>):

```
PlutusTx: Compiling Haskell to PLC (Plutus Core; on-chain code).

PlutusTx.Prelude: Haskell prelude replacement compatible with PLC.

PlutusCore: Programming language in which scripts on the Cardano blockchain are written.

UntypedPlutusCore: On-chain Plutus code.
```

The two modules that we will be importing into our Haskell files are `PlutusTx` and `PlutusTx.Prelude`. We start with a new `SimplestSuccess.hs` file. We will **write the simplest contract that successfully validates every attempt to spend its funds**.

### Writing the validator

First, we will need to add some GHC extensions at the start of the file:

```haskell
{-# LANGUAGE DataKinds         #-} -- make any type constructor into a type
{-# LANGUAGE NoImplicitPrelude #-} -- do not import Prelude by default
{-# LANGUAGE TemplateHaskell   #-} -- allows embedding domain-specific language into the Haskell host language
```

The `DataKinds` extension is needed for some Template Haskell features or the `PlutusTx` compilation will fail. `NoImplicitPrelude` states not to import the Haskell Prelude. We always need to specify this as `PlutusTx` has its own Prelude that we have to use. When writing the validator to a file, we still need to use the `IO` monad from the original Prelude, which we can import explicitly. The `TemplateHaskell` extension is simply to allow us to write Template Haskell expressions to be able to properly use `PlutusTx.compile` inside our module.

Next, we define our module name (same as the filename):

<pre class="language-haskell"><code class="lang-haskell"><strong>module SimplestSuccess
</strong>  (
    successScriptSerialised,
    writeSerialisedSuccessScript
  ) 
where
</code></pre>

Next, we need to import the packages required for the compilation of our script. Note that these must be defined in our `.cabal` file in order to be imported here. For now, these will be:

```haskell
import qualified PlutusTx                           -- main on-chain code module
import qualified PlutusTx.Prelude     as Prelude    -- Prelude replacement for Plutus
import qualified Plutus.V2.Ledger.Api as Plutus     -- functions for working with scripts on the ledger

import Cardano.Api.Shelley (PlutusScript (PlutusScriptSerialised), PlutusScriptV2, writeFileTextEnvelope)
import Cardano.Api (FileError)

-- Hackage packages
import qualified Data.ByteString.Lazy as LBS
import qualified Data.ByteString.Short as SBS
import Codec.Serialise

import Prelude (IO)
```

In general, we want to **write three major parts** of our Haskell file:

1. The `mkValidator` function that contains our validation logic.
2. Compilation of that function to a Plutus Core script (the on-chain language). This is done by using [template Haskell](http://wiki.haskell.org/Template_Haskell).
3. Serialise and write the script to a `.plutus` file.

When we write a validator we define a function that receives the three aforementioned arguments and **returns a unit `()` if successful**. Not returning a `()` means that the validation failed and the transaction will be invalidated. With that in mind, we can start to think about the type signature of the validator function, something like:

`mkValidator :: Datum -> Redeemer -> Context -> ()`.

But what are the types of `Datum`, `Redeemer` and `Context`? It turns out that in Plutus, all three of the validation arguments need to come in a type of `Data`. We can explore the Haddock pages to learn more about it: <https://intersectMBO.github.io/plutus/master/plutus-core/html/PlutusCore-Data.html#t:Data>.

We see that the `Data` type comes with several constructors, but the main takeaway is that it is a generic data type that can represent various things such as integers, byte strings, lists, and maps. Plutus also features a `BuiltinData` type (<https://intersectMBO.github.io/plutus/master/plutus-tx/html/PlutusTx-Builtins.html#g:4>) that can be used directly in the on-chain code.

So we can now write the type signature of our validator function using the `BuiltinData` type for its arguments and returning `()`:

`mkValidator :: BuiltinData -> BuiltinData -> BuiltinData -> ()`

```
{-# INLINABLE mkValidator #-}
mkValidator :: Prelude.BuiltinData -> Prelude.BuiltinData -> Prelude.BuiltinData -> ()
mkValidator _ _ _ = ()
```

Since this function always returns `()` regardless of its arguments, any UTxO belonging to the script will be spendable by any transaction. We add the inlinable pragma just above the function to be able to later use it with the PlutusTx compiler directly in our Haskell code.

We now need to do part 2 of our three steps, compiling this validator function to Plutus Core:

```
validator :: Plutus.Validator
validator = Plutus.mkValidatorScript $$(PlutusTx.compile [|| mkValidator ||])
```

The unusual syntax above is template Haskell: `$$([|| ||])`. The function [`Plutus.mkValidatorScript`](https://intersectMBO.github.io/plutus-apps/main/plutus-ledger/html/Ledger.html#v:mkValidatorScript) requires a Plutus Core argument so the `mkValidator` is first compiled to Plutus Core. In order for this to work, the compiled function `mkValidator` must be made inlinable with `{-# INLINABLE mkValidator #-}` that we specified earlier.

Part 3 of our three steps is arguably the simplest. We need to unwrap the validator to get the script. This is just a necessary step to conform with the expected types. Since [`Plutus.Validator`](https://intersectMBO.github.io/plutus-apps/main/plutus-ledger/html/Ledger.html#t:Validator) is a wrapper around [`Plutus.Script`](https://intersectMBO.github.io/plutus-apps/main/plutus-ledger/html/Ledger.html#t:Script) which is used as the actual validator in the ledger, we need to unwrap it.

```haskell
script :: Plutus.Script
script = Plutus.unValidatorScript validator
```

We can now serialise the script to a `ShortByteString`:

```haskell
successScriptShortBs :: SBS.ShortByteString
successScriptShortBs = SBS.toShort Prelude.. LBS.toStrict Prelude.$ serialise script
```

The next step is just a type conversion again:

```haskell
successScriptSerialised :: PlutusScript PlutusScriptV2
successScriptSerialised = PlutusScriptSerialised successScriptShortBs
```

Finally, we expose a function that writes the `Plutus` script to a file that we will use with the actual blockchain:

<pre class="language-haskell"><code class="lang-haskell"><strong>writeSerialisedSuccessScript :: IO (Prelude.Either (FileError ()) ())
</strong>writeSerialisedSuccessScript = writeFileTextEnvelope "compiled/SimplestSuccess.plutus" Prelude.Nothing successScriptSerialised
</code></pre>

We can load up a `cabal repl`, and compile the script. Make sure you create the `compiled/` directory first.

```haskell
Prelude SimplestSuccess> SimplestSuccess.writeSerialisedSuccessScript 
Right ()
```

### Serialising a datum object

We now have the compiled script in `compiled/simplestSuccess.plutus`. Another thing we need is to serialise a `datum`. We need to use datums on script outputs as **any UTxO without a datum hash attached will be unspendable** as we mentioned before. We need to write a utility function for converting Plutus data to JSON because `cardano-cli` expects JSON values. Create a new file under `src/Helpers/Utils.hs`:

```haskell
{-# LANGUAGE DataKinds         #-}
{-# LANGUAGE NoImplicitPrelude #-}

module Helpers.Utils
  (
    plutusDataToJSON,
    writeJSONData
  ) 
where

import qualified PlutusTx
import PlutusTx.Prelude
import Data.Aeson (encode)

import Cardano.Api.Shelley (fromPlutusData, scriptDataToJson, ScriptDataJsonSchema (ScriptDataJsonDetailedSchema))

import qualified Data.ByteString.Lazy as LBS

import Prelude (IO, String)

plutusDataToJSON :: PlutusTx.ToData a => a ->  LBS.ByteString
plutusDataToJSON = encode . scriptDataToJson ScriptDataJsonDetailedSchema . fromPlutusData . PlutusTx.toData

writeJSONData :: PlutusTx.ToData a => String -> a -> IO ()
writeJSONData filePath pData = LBS.writeFile filePath $ plutusDataToJSON pData
```

This is mostly boilerplate code that we don't need to think too much about. It simply takes some data of the [`ToData`](https://intersectMBO.github.io/plutus-apps/main/plutus-ledger-api/html/Plutus-V2-Ledger-Api.html#t:ToData) class and serialises it to a JSON that `cardano-cli` expects. We can now load and use this function anytime we need to write a datum file. Here, we just want to write a unit `()` datum file. Make sure you create the `compiled/assets/` directory before running the code below first.

<pre class="language-haskell"><code class="lang-haskell"><strong>Prelude> :l src/Helpers/Utils.hs
</strong><strong>Ok, one module loaded.
</strong><strong>Prelude Utils> writeJSONData "compiled/assets/unit.json" ()
</strong></code></pre>

{% hint style="info" %}
Every time we want to automatically load a module we write when launching a `cabal repl`, we can add them to our `.cabal` file in the `exposed-modules` field.

```haskell
-- hpm-validators.cabal

...
library
    hs-source-dirs:       src
    exposed-modules:      SimplestSuccess
                        , Helpers.Utils
...
```

{% endhint %}

### Testing the validator

To start testing our validators, we will need to create some regular Cardano addresses on the testnet and use the faucet to get some tADA. We will use these to pay the fees for the transactions we create as well as the collateral inputs. We will build two addresses now and use them throughout the course with different validators. Let's place all our testing files in the `testnet/` directory of the project root. Below is a `bash` script that creates the addresses for us (you can also use `cardano-cli` directly in the terminal). Make sure you create the `testnet/addresses/` directory beforehand.

{% hint style="warning" %}
***We always test our validators from OUTSIDE the\*\*\*\*****&#x20;****`nix-shell`****, i.e. with our local node that is synced. The\*\*\*\***** ****`nix-shell`**** \*\*\*\*\*\*\*\*provides ONLY a development environment for writing and serialising Plutus validators.***
{% endhint %}

<pre class="language-bash"><code class="lang-bash"><strong># testnet/create-addresses.sh
</strong>
<strong>#!/usr/bin/env bash
</strong>
NWMAGIC=2 # preview testnet

# Build normal address 1
cardano-cli address key-gen \
--verification-key-file ./address/01.vkey \
--signing-key-file ./address/01.skey

cardano-cli address build \
--payment-verification-key-file ./address/01.vkey \
--testnet-magic $NWMAGIC \
--out-file ./address/01.addr

# Build normal address 2
cardano-cli address key-gen \
--verification-key-file ./address/02.vkey \
--signing-key-file ./address/02.skey

cardano-cli address build \
--payment-verification-key-file ./address/02.vkey \
--testnet-magic $NWMAGIC \
--out-file ./address/02.addr

echo "Before continuing, request faucet funds to address: $(cat address/01.addr)!"

</code></pre>

To run the script, we first have to make it an executable:

```
chmod +x create-addressses.sh
./create-addressses.sh
```

{% hint style="info" %}
We will always need to make any `bash` scripts we intend to run executable first with the above command `chmod +x <script-name>.sh`.
{% endhint %}

Once done, we need to request funds to our new address from the faucet: <https://docs.cardano.org/cardano-testnet/tools/faucet/>. Make sure you select the right network for the transaction, we are using `preview` in this course.

The two addresses we created will be shared among all the validators we test. Now we need to create a *script address* for our `SimplestSuccess` validator. For each validator we test, we will place the testing resources under a new directory specific to that validator. For `SimplestSuccess`, that will be `testnet/SimplestSuccess/`. After creating the directory, let's build the script address. Note that here we do not specify a key pair for the address, but instead a script file that acts as the validator for that address.

```bash
# testnet/SimplestSuccess/build-script-address.sh

#!/usr/bin/env bash

NWMAGIC=2 # preview testnet

# Build script address
cardano-cli address build \
--payment-script-file ../../compiled/SimplestSuccess.plutus \
--testnet-magic $NWMAGIC \
--out-file SimplestSuccess.addr
```

We can also build a convenience script to check the UTxOs at our addresses.

```bash
# testnet/SimplestSuccess/check-utxos.sh

#!/usr/bin/env bash

NWMAGIC=2 # preview testnet
export CARDANO_NODE_SOCKET_PATH=$CNODE_HOME/sockets/node0.socket

funds_normal=$(cardano-cli query utxo \
--address $(cat ../address/01.addr) \
--testnet-magic $NWMAGIC)

funds_script=$(cardano-cli query utxo \
--address $(cat SimplestSuccess.addr) \
--testnet-magic $NWMAGIC)

echo "Normal address:"
echo "${funds_normal}"

echo "Script address:"
echo "${funds_script}"
```

We will see something interesting when we check the UTxOs. Our normal address has just a single UTxO on it, which is the transaction from the faucet, and that is expected. But the script address has a lot of UTxOs on it. You might have expected it to have no UTxOs as we just created it. But it turns out, this is a common script whose address was already created and used on this testnet. Of course, if two or more people write scripts with the same compilation result (the same Plutus Core code that is executed on-chain), then the address created from that script will also be the same. This is because a script address is simply the hash of the script code.

Since we know there are already UTxOs sitting at the script address, we do not really need to send any funds to it in order to test that we can spend them back. We can just use any of the existing UTxOs since the script allows any UTxO sitting on it to be spent. We will still create a script for sending funds to the script for completeness. Note that as we mentioned before, any script UTxO without a datum attached is ***UNSPENDABLE*** (go ahead and try spending one), so never forget to attach a datum when sending funds to a script. The `--tx-in` argument will be the UTxO from our normal address so you need to change it accordingly. For datum, we will simply embed the `unit.json` that we created earlier. Finally, we need to sign the transaction with the private key of the `01.addr`.

{% hint style="warning" %}
***Note that for all the bash scripts in this course, you will need to change the --tx-in arguments to match your own UTxOs. If you have not maintained the same directory structure as outlined in the course, you will need to change those paths accordingly as well.***
{% endhint %}

```bash
# testnet/SimplestSuccess/send-funds-to-script.sh

#!/usr/bin/env bash

NWMAGIC=2 # preview testnet
export CARDANO_NODE_SOCKET_PATH=$CNODE_HOME/sockets/node0.socket

cardano-cli transaction build \
    --testnet-magic $NWMAGIC \
    --change-address $(cat ../address/01.addr) \
    --tx-in 2326577336a90f71738aab4803b3f1ae9107d0ddeb107fc4bf926b24e95930ad#0 \
    --tx-out $(cat SimplestSuccess.addr)+2000000 \
    --tx-out-datum-embed-file ../../compiled/assets/unit.json \
    --out-file tx.body

cardano-cli transaction sign \
    --tx-body-file tx.body \
    --signing-key-file ../address/01.skey \
    --testnet-magic $NWMAGIC \
    --out-file tx.signed

cardano-cli transaction submit \
    --testnet-magic $NWMAGIC \
    --tx-file tx.signed
```

Now we want to see if we can spend a UTxO from the script. Good luck finding the one you just sent to it. You can just pick a random one that has a datum from the UTxO list instead. This time, we must include a collateral UTxO, which must be from a regular address as we mentioned before. Change the `--tx-in` and `--tx-in-collateral` accordingly.

```bash
# testnet/SimplestSuccess/spend-script-utxo.sh

#!/usr/bin/env bash

NWMAGIC=2 # preview testnet
export CARDANO_NODE_SOCKET_PATH=$CNODE_HOME/sockets/node0.socket

cardano-cli transaction build \
    --testnet-magic $NWMAGIC \
    --change-address $(cat ../address/01.addr) \
    --tx-in ea340a31a9ad4dd059e6743274607e2cc7bdb7b12b5345be8bc81988d9a6ea86#0 \
    --tx-in-script-file ../../compiled/SimplestSuccess.plutus \
    --tx-in-datum-file ../../compiled/assets/unit.json \
    --tx-in-redeemer-file ../../compiled/assets/unit.json \
    --tx-in-collateral ea340a31a9ad4dd059e6743274607e2cc7bdb7b12b5345be8bc81988d9a6ea86#1 \
    --out-file tx.body

cardano-cli transaction sign \
    --tx-body-file tx.body \
    --signing-key-file ../address/01.skey \
    --testnet-magic $NWMAGIC \
    --out-file tx.signed

cardano-cli transaction submit \
    --testnet-magic $NWMAGIC \
    --tx-file tx.signed
```

After the transaction is successfully submitted and processed, we can confirm that our `01.addr` received the funds from the script and our collateral was not spent.

```bash
./check-utxos.sh
```

```bash
Normal address:
                           TxHash                                 TxIx        Amount
--------------------------------------------------------------------------------------
ea340a31a9ad4dd059e6743274607e2cc7bdb7b12b5345be8bc81988d9a6ea86     1        9997830891 lovelace + TxOutDatumNone
ee346be463426509daec07aba24a8905c5f55965daebb39f842a49191d83f9e1     0        1829006 lovelace + TxOutDatumNone
```

### Practice!

It is important to practice on your own. Try using the materials above to write and test a Plutus script that always fails (a sort of token-burning script) from scratch.


# A Guessing Game Script

## Exploring datum and redeemer in scripts

For our next script, we will use the `datum` and `redeemer` arguments instead of ignoring them. We will still ignore the third argument, the *transaction context*, for now. The goal of this script is to create a guessing game, where the UTxO sitting at the script address is unlocked if the submitting transaction sends a `redeemer` that matches the `datum` present at that UTxO. It is quite a simple re-rewrite from our first script - we just need to add a bit of logic to the `mkValidator` function and replace the function names accordingly. Create a new file `src/GuessingGame.hs` for this validator and paste the code from `SimplestSuccess.hs` into it. Our extensions and imports stay exactly the same, let's just remove the `qualified` from the `PlutusTx.Prelude` import so that we do not have to prefix every `Prelude` function with `Prelude.`:

```haskell
import PlutusTx.Prelude
```

### Writing the validator

We rename our module and exposed functions. Let's remove the script name from the exposed generic functions for serialising and writing the script to disk and just call them `scriptSerialised` and `writeSerialisedScript`:

```haskell
module GuessingGame
  (
    scriptSerialised,
    writeSerialisedScript
  )
where
```

Our `mkValidator` function becomes:

```haskell
{-# INLINABLE mkValidator #-}
mkValidator :: BuiltinData -> BuiltinData -> BuiltinData -> ()
mkValidator datum redeemer _ =
    if datum == redeemer then ()
    else error ()
```

We use the comparison function to check whether the received `redeemer` matches the `datum` sitting at the UTxO. If that's the case, we return `()` as a sign of successful validation. Otherwise, we use the `error ()` from `Prelude` to signify failed validation. Our `validator` and `script` functions stay exactly the same, but we need to update the names of generic functions for serialising and writing the script to disk, and set the write filename to `GuessingGame.plutus`:

```haskell
scriptShortBs :: SBS.ShortByteString
scriptShortBs = SBS.toShort . LBS.toStrict $ serialise script

scriptSerialised :: PlutusScript PlutusScriptV2
scriptSerialised = PlutusScriptSerialised scriptShortBs

writeSerialisedScript :: IO (Either (FileError ()) ())
writeSerialisedScript = writeFileTextEnvelope "compiled/GuessingGame.plutus" Nothing scriptSerialised
```

{% hint style="info" %}
Every time we want to automatically load a module we write when launching a `cabal repl`, we can add them to our `.cabal` file in the `exposed-modules` field.

```haskell
-- hpm-validators.cabal

...
library
    hs-source-dirs:       src
    exposed-modules:      SimplestSuccess
                        , GuessingGame
                        , Helpers.Utils
...
```

{% endhint %}

### Testing the validator

#### Serialising string-like datums

To test this script, we could use the compiled `unit.json` as our datum, but let's instead create a more interesting one. Again launch the `cabal repl` and load the `Utils` module. Let's say we want to create a secret in the `String` format. We can try:

```haskell
Prelude> :l src/helpers/Utils.hs 
Ok, one module loaded.
Prelude Utils> writeJSONData "compiled/assets/secretGuess.json" "I am a secret"
```

But we will get the following error:

```haskell
<interactive>:3:1: error:
    • No instance for (PlutusTx.IsData.Class.ToData Char)
        arising from a use of ‘writeJSONData’
```

It seems that `PlutusTx.toData` class does not implement an instance for the `String` type. Indeed, if we check the [documentation](https://intersectMBO.github.io/plutus/master/plutus-tx/html/PlutusTx-IsData-Class.html), we see that only a `ToData BuiltinByteString` is defined when it comes to string-like values. So we need to convert our Haskell `String` to a Plutus `BuiltinByteString`. Again we need to look through the [documentation](https://intersectMBO.github.io/plutus/master/plutus-tx/html/PlutusTx-Builtins-Class.html#v:stringToBuiltinByteString) to find the function we need (located in the `PlutusTx.Builtins.Class` module):

```haskell
stringToBuiltinByteString :: String -> BuiltinByteString
```

Let's load up this module and apply this function to our string before serialising it:

```haskell
Prelude Utils> import PlutusTx.Builtins.Class
Prelude PlutusTx.Builtins.Class Utils> writeJSONData "compiled/assets/secretGuess.json" $ stringToBuiltinByteString "I am
 a secret"
```

No error message, and our datum is compiled under `compiled/assets/secretGuess.json`. It looks like this:

```json
{"bytes":"4920616d206120736563726574"}
```

We are now ready to test the validator! Create a new directory `testnet/GuessingGame` for this purpose.

Let's compile the validator as well.

```haskell
-- The following line is not necessary if the module was added to exposed-modules in the .cabal file
Prelude> :l src/GuessingGame.hs
Prelude> GuessingGame.writeSerialisedScript
Right ()
```

Now, we need to create an address for this validator like before:

```sh
# testnet/GuessingGame/create-script-address.sh

#!/usr/bin/env bash

NWMAGIC=2 # preview testnet

# Build script address
cardano-cli address build \
--payment-script-file ../../compiled/GuessingGame.plutus \
--testnet-magic $NWMAGIC \
--out-file GuessingGame.addr

echo "Script address: $(cat GuessingGame.addr)"
```

Our `check-utxos.sh` script remains the same, but we updated the script address:

```bash
# testnet/GuessingGame/check-utxos.sh

#!/usr/bin/env bash

NWMAGIC=2 # preview testnet
export CARDANO_NODE_SOCKET_PATH=$CNODE_HOME/sockets/node0.socket

funds_normal=$(cardano-cli query utxo \
--address $(cat ../address/01.addr) \
--testnet-magic $NWMAGIC)

funds_script=$(cardano-cli query utxo \
--address $(cat GuessingGame.addr) \
--testnet-magic $NWMAGIC)

echo "Normal address:"
echo "${funds_normal}"

echo "Script address:"
echo "${funds_script}"
```

Again, we will see existing UTxOs present on the script address, as someone has already compiled and used it. Let's send some value to the script along with our secret datum.

```bash
# testnet/GuessingGame/set-guess-utxo.sh

#!/usr/bin/env bash

NWMAGIC=2 # preview testnet
export CARDANO_NODE_SOCKET_PATH=$CNODE_HOME/sockets/node0.socket

cardano-cli transaction build \
    --testnet-magic $NWMAGIC \
    --change-address $(cat ../address/01.addr) \
    --tx-in ea340a31a9ad4dd059e6743274607e2cc7bdb7b12b5345be8bc81988d9a6ea86#1 \
    --tx-out $(cat GuessingGame.addr)+2000000 \
    --tx-out-datum-embed-file ../../compiled/assets/secretGuess.json \
    --out-file tx.body

cardano-cli transaction sign \
    --tx-body-file tx.body \
    --signing-key-file ../address/01.skey \
    --testnet-magic $NWMAGIC \
    --out-file tx.signed

cardano-cli transaction submit \
    --testnet-magic $NWMAGIC \
    --tx-file tx.signed
```

If we check the UTxOs again, we'll see a new UTxO sitting at the script address. Only transactions with the matching redeemer can spend it. Let's try to first spend it with an invalid redeemer. Since the datum of the UTxO we are trying to spend needs to be specified in the transaction regardless, this is slightly pointless. But to show that the validator works as it should, let's specify the correct datum, but the wrong redeemer:

```bash
# testnet/GuessingGame/spend-script-utxo-invalid.sh

#!/usr/bin/env bash

NWMAGIC=2 # preview testnet
export CARDANO_NODE_SOCKET_PATH=$CNODE_HOME/sockets/node0.socket

cardano-cli transaction build \
    --testnet-magic $NWMAGIC \
    --change-address $(cat ../address/01.addr) \
    --tx-in 8fc7a4fda80ad379811c44591a9fc4bae7fcd9a4ddda1574df910adc0143ac7a#0 \
    --tx-in-script-file ../../compiled/GuessingGame.plutus \
    --tx-in-datum-file ../../compiled/assets/secretGuess.json \
    --tx-in-redeemer-file ../../compiled/assets/unit.json \
    --tx-in-collateral ee346be463426509daec07aba24a8905c5f55965daebb39f842a49191d83f9e1#0 \
    --out-file tx.body

cardano-cli transaction sign \
    --tx-body-file tx.body \
    --signing-key-file ../address/01.skey \
    --testnet-magic $NWMAGIC \
    --out-file tx.signed

cardano-cli transaction submit \
    --testnet-magic $NWMAGIC \
    --tx-file tx.signed
```

Trying to execute it gives us a script execution failure:

```bash
./spend-script-utxo-invalid.sh

Command failed: transaction build  Error: The following scripts have execution failures:
the script for transaction input 0 (in ascending 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:
```

The logs are empty as we have not configured any logging, nor did we give an error message. But we still know that the script failed to execute successfully for this transaction because the redeemer does not match the datum. Let's create a valid transaction this time. We just need to change the `--tx-in-redeemer-file` line to point to our secret guess:

4\) `spend-script-utxo.sh`

```bash
# testnet/GuessingGame/spend-script-utxo.sh

#!/usr/bin/env bash

NWMAGIC=2 # preview testnet
export CARDANO_NODE_SOCKET_PATH=$CNODE_HOME/sockets/node0.socket

cardano-cli transaction build \
    --testnet-magic $NWMAGIC \
    --change-address $(cat ../address/01.addr) \
    --tx-in 8fc7a4fda80ad379811c44591a9fc4bae7fcd9a4ddda1574df910adc0143ac7a#0 \
    --tx-in-script-file ../../compiled/GuessingGame.plutus \
    --tx-in-datum-file ../../compiled/assets/secretGuess.json \
    --tx-in-redeemer-file ../../compiled/assets/secretGuess.json \
    --tx-in-collateral ee346be463426509daec07aba24a8905c5f55965daebb39f842a49191d83f9e1#0 \
    --out-file tx.body

cardano-cli transaction sign \
    --tx-body-file tx.body \
    --signing-key-file ../address/01.skey \
    --testnet-magic $NWMAGIC \
    --out-file tx.signed

cardano-cli transaction submit \
    --testnet-magic $NWMAGIC \
    --tx-file tx.signed
```

We see that the transaction is successful this time, and we are able to spend the script UTxO!

```bash
./spend-script-utxo.sh
Estimated transaction fee: Lovelace 173085
Transaction successfully submitted.
```


# Exploring Script Context

### Introduction to Script Context

We will now take a closer look at the third argument to Plutus validator functions which is the ***script context***. As mentioned before, the script context contains the entire transaction being validated including all its inputs and outputs, fees, and certificates.

{% hint style="info" %}
You may hear *script context* being called *transaction context*. Don't be confused as they mean the same thing.
{% endhint %}

In Plutus, this script context corresponds to the `ScriptContext` type. The best way to explore the structure of the `ScriptContext` type is through [Haddock documentation](https://intersectMBO.github.io/plutus-apps/main/plutus-ledger/html/Ledger.html#t:ScriptContext).

{% hint style="info" %}
Here, we are looking at the [plutus-apps repository Haddock documentation](https://intersectMBO.github.io/plutus-apps/main/).
{% endhint %}

We can see that it consists of two fields:

1. `scriptContextTxInfo :: TxInfo`
2. `scriptContextPurpose :: ScriptPurpose`

The `scriptContextTxInfo` field is a type of `TxInfo` for which we can find further information in Haddock:

```haskell
txInfoInputs :: [TxInInfo]	                 -- Transaction inputs

txInfoReferenceInputs :: [TxInInfo]              -- Transaction reference inputs

txInfoOutputs :: [TxOut]	                 -- Transaction outputs

txInfoFee :: Value	                         -- The fee paid by this transaction.

txInfoMint :: Value                              -- The Value minted by this transaction.

txInfoDCert :: [DCert]	                         -- Digests of certificates included in this transaction

txInfoWdrl :: Map StakingCredential Integer	 -- Withdrawals

txInfoValidRange :: POSIXTimeRange	         -- The valid range for the transaction.

txInfoSignatories :: [PubKeyHash]	         -- Signatures provided with the transaction, attested that they all signed the tx

txInfoRedeemers :: Map ScriptPurpose             -- Redeemer

txInfoData :: Map DatumHash                      -- Datum
 
txInfoId :: TxId	                         -- Hash of the pending transaction (excluding witnesses)
```

In other words, it contains everything that we attached to the transaction when we built it.

The other field `scriptContextPurpose` is of type `ScriptPurpose` which can be one of:

```haskell
Minting    CurrencySymbol
Spending   TxOutRef
Rewarding  StakingCredential
Certifying DCert
```

### A ScriptContext Exploration Script

Now that we have a theoretical overview of the script context, let's write a simple script utilising it in practice. It will be just a simple example with the sole purpose of exploring the use of script context inside the validator. We will create a script that validates only if the transaction attempts to create less than or exactly **three** outputs and if its valid time range is **infinite** (this is the default range applied if no valid range is specified during the transaction building stage).

#### A note on Cardano transaction validity ranges

Cardano transactions contain a `txInfoValidRange`, which defines the range of *slots* between which the transaction is valid. There are two layers of checking the valid range for a transaction. The first one happens when a `cardano-node` receives the transaction. The first thing the node does when considering a transaction is check its valid range - if the current slot does not fall into the valid range of the transaction, it is immediately discarded without doing anything else (including running a possible validator script in the transaction). The second layer is optional and can be specified in the validator script itself. This is done by accessing the `txInfoValidRange` from the `ScriptContext` and performing arbitrary checks against it.

### Writing the validator

Create a new file `src/ExploringScriptContext.hs` for this validator. Our imports stay the same as in the previous scripts so copy those in. Firstly, we need to change the way we look at arguments in the `mkValidator` function. We are not interested in the `datum` and `redeemer` fields so we can ignore them now, and instead, look only at the `context` field:

```haskell
mkValidator :: BuiltinData -> BuiltinData -> BuiltinData -> ()
mkValidator _ _ ctx = ...
```

We want to check two things in the validation as mentioned above, so we will create helper functions that check each one individually, `checkOutputs` and `checkRange`. The main function will check that both of these helper functions evaluate to `True`:

```haskell
mkValidator _ _ ctx =
  if checkOutputs && checkRange 
    then ()
    else error ()
```

Now we need to write the helper functions which is a bit more complicated as they have to work with the script `context`. Firstly, to even access the `context` in the structure of `ScriptContext` we explored, we have to build that structure from the third argument `ctx`, which is of type `BuiltinData`. We can do this transformation by using [`unsafeFromBuiltinData` ](https://intersectMBO.github.io/plutus-apps/main/plutus-ledger-api/html/Plutus-V2-Ledger-Api.html#v:unsafeFromBuiltinData)function on `ctx` (the difference between `unsafeFromBuiltinData` and `fromBuiltinData` is that the former will error if it fails which is faster, while the latter will return `Nothing`). This leads to our first helper function:

`valCtx = Plutus.unsafeFromBuiltinData ctx`

We now have the `valCtx` of type `ScriptContext`, so we can destructure it accordingly. Remember that it consists of two fields `scriptContextTxInfo :: TxInfo` and `scriptContextPurpose :: ScriptPurpose`. For our use case, we are only interested in the `TxInfo`, and we can get it with our second helper function:

`info = Plutus.scriptContextTxInfo valCtx`

The `info` is now of type `TxInfo`, which contains all the information we need for our validation. Specifically, we are interested in the fields `txInfoOutputs :: [TxOut]` and `txInfoValidRange :: POSIXTimeRange`. To create the validation logic for the number of UTxOs we can simply use the `length` function to count the number of UTxOs in the transaction since `txInfoOutputs` is a `[List]`. We also combine that with the Plutus Prelude `traceIfFalse` function to provide us with debugging info in case of invalid transactions:

`checkOutputs = traceIfFalse "4 or more outputs in tx!" $ length (Plutus.txInfoOutputs info) <= 3`

The final part of our validator logic is to check that the submitted transaction's valid range is infinite. We first destruct the `txInfoValidRange` field of `TxInfo`, and compare it with the `Plutus.always` pre-defined time interval which corresponds to the infinite time range. Again, we use the `traceIfFalse` as before:

`checkRange = traceIfFalse "Tx does not have infinite range!" $ Plutus.txInfoValidRange info == Plutus.always`

Now we have all the pieces of the validation done and the full validator looks like this:

```haskell
mkValidator :: BuiltinData -> BuiltinData -> BuiltinData -> ()
mkValidator _ _ ctx =
  if checkOutputs P.&& checkRange 
    then ()
    else error ()
  where
    valCtx = Plutus.unsafeFromBuiltinData ctx
    info = Plutus.scriptContextTxInfo valCtx
    checkOutputs = traceIfFalse "4 or more outputs in tx!" $ length (Plutus.txInfoOutputs info) <= 3
    checkRange = traceIfFalse "Tx does not have infinite range!" $ Plutus.txInfoValidRange info == Plutus.always
```

The rest of the functions for serialising and writing the script stay the same as with previous scripts (`validator`, `script`, `scriptShortBs`, `scriptSerialised`). We just need to change the compilation result destination in the `writeSerialisedScript` function:

```haskell
writeSerialisedScript :: IO (Either (FileError ()) ())
writeSerialisedScript = writeFileTextEnvelope "compiled/ExploringScriptContext.plutus" Nothing scriptSerialised
```

If we try to compile this script as is, we will get an error:

```haskell
Couldn't match expected type ‘BuiltinString’
    with actual type ‘[ghc-prim-0.6.1:GHC.Types.Char]’
    • In the first argument of ‘traceIfFalse’, namely
        ‘"Tx does not have infinite range!"’
```

The `traceIfFalse` function is expecting a `BuiltinString` but we are passing it a regular Haskell string. We can solve this with the `stringToBuiltinString` function from [`PlutusTx.Builtins.Class`](https://intersectMBO.github.io/plutus/master/plutus-tx/html/PlutusTx-Builtins-Class.html#v:stringToBuiltinString). Add an import for this function and apply it to the trace message string in the `checkOutputs` and `checkRange` functions:

```haskell
import PlutusTx.Builtins.Class (stringToBuiltinString)

...

checkOutputs = traceIfFalse (stringToBuiltinString "4 or more outputs in tx!")
    $ length (Plutus.txInfoOutputs txInfo) <= 3

checkRange = traceIfFalse (stringToBuiltinString "Tx does not have infinite range!")
    $ Plutus.txInfoValidRange txInfo == Plutus.always
    
...
```

The module will compile okay now. However, there is another way to get through this issue, with a GHC extension called `OverloadedStrings`. This extension lets GHC try to transform regular Haskell strings into the required types. We can remove the `PlutusTx.Builtins.Class` import and revert our functions to just using a normal Haskell string as before, with the addition of this extension to the top of the file.

```haskell
...
{-# LANGUAGE OverloadedStrings #-}
...
```

{% hint style="info" %}
Every time we want to automatically load a module we write when launching a `cabal repl`, we can add them to our `.cabal` file in the `exposed-modules` field.

```haskell
-- hpm-validators.cabal

...
library
    hs-source-dirs:       src
    exposed-modules:      SimplestSuccess
                        , GuessingGame
                        , ExploringScriptContext
                        , Helpers.Utils
...
```

{% endhint %}

### Testing the validator

Compile the validator as before by launching a `cabal repl` and calling the write function.

```
Prelude> ExploringScriptContext.writeSerialisedScript
Right ()
```

Firstly, create a script address for the validator. We will use `src/testnet/ExploringScriptContext` as the testing directory.

```bash
# testnet/ExploringScriptContext/create-script-address.sh

#!/usr/bin/env bash

NWMAGIC=2 # preview testnet

# Build script address
cardano-cli address build \
--payment-script-file ../../compiled/ExploringScriptContext.plutus \
--testnet-magic $NWMAGIC \
--out-file ExploringScriptContext.addr

echo "Script address: $(cat ExploringScriptContext.addr)"
```

As before, we need a way to check the UTxOs. It's likely that this script address will not have any UTxOs on it when checked.

```bash
# testnet/ExploringScriptContext/check-utxos.sh

#!/usr/bin/env bash

NWMAGIC=2 # preview testnet
export CARDANO_NODE_SOCKET_PATH=$CNODE_HOME/sockets/node0.socket

funds_normal=$(cardano-cli query utxo \
--address $(cat ../address/01.addr) \
--testnet-magic $NWMAGIC)

funds_script=$(cardano-cli query utxo \
--address $(cat ExploringScriptContext.addr) \
--testnet-magic $NWMAGIC)

echo "Normal address:"
echo "${funds_normal}"

echo "Script address:"
echo "${funds_script}"
```

```bash
./check-utxos.sh

Normal address:
                           TxHash                                 TxIx        Amount
--------------------------------------------------------------------------------------
5dc5111e257f8e68b0978c9619e57bbb12d365c0ec45d879115866bb674156ae     0        1826915 lovelace + TxOutDatumNone
8fc7a4fda80ad379811c44591a9fc4bae7fcd9a4ddda1574df910adc0143ac7a     1        9995661298 lovelace + TxOutDatumNone
ee346be463426509daec07aba24a8905c5f55965daebb39f842a49191d83f9e1     0        1829006 lovelace + TxOutDatumNone
Script address:
                           TxHash                                 TxIx        Amount
--------------------------------------------------------------------------------------
```

We need to fund the script with some tADA before testing it. Create a `send-funds-to-script.sh` script.

<pre class="language-bash"><code class="lang-bash"># testnet/ExploringScriptContext/send-funds-to-script.sh

<strong>#!/usr/bin/env bash
</strong>
NWMAGIC=2 # preview testnet
export CARDANO_NODE_SOCKET_PATH=$CNODE_HOME/sockets/node0.socket


cardano-cli transaction build \
    --testnet-magic $NWMAGIC \
    --change-address $(cat ../address/01.addr) \
    --tx-in 8fc7a4fda80ad379811c44591a9fc4bae7fcd9a4ddda1574df910adc0143ac7a#1 \
    --tx-out $(cat ExploringScriptContext.addr)+10000000 \
    --tx-out-datum-embed-file ../../compiled/assets/unit.json \
    --out-file tx.body

cardano-cli transaction sign \
    --tx-body-file tx.body \
    --signing-key-file ../address/01.skey \
    --testnet-magic $NWMAGIC \
    --out-file tx.signed

cardano-cli transaction submit \
    --testnet-magic $NWMAGIC \
    --tx-file tx.signed
</code></pre>

```bash
./send-funds-to-script.sh
Estimated transaction fee: Lovelace 169109
Transaction successfully submitted.
```

The funds are on the script, and we want to start actually testing the validator logic. Let's create the two transactions that should *fail*. These two cases are:

1. The transaction tries to spend the script UTxO by creating *4 or more outputs*.
2. The transaction validity range is *not* infinite.

Let's start with the validity range case. We can query the tip of the chain with `cardano-cli` to get the current slot, and we can add an `--invalid-before` argument to the `transaction build` command with any slot before the current tip. This will define the transaction validity range from that slot to infinity. This will make the transaction pass the first validity range check that the node performs, as the current slot will fall into the transactions' valid range, but our logic inside the validator regarding the transaction range should fail.

```bash
cardano-cli query tip --testnet-magic 2
{
    "block": 1099151,
    "epoch": 290,
    "era": "Babbage",
    "hash": "31323e6507cf03e5668ab714be923535b01aee73b04ebb175c9c744472d573a4",
    "slot": 25086665,  # This is our current chain tip
    "slotInEpoch": 30665,
    "slotsToEpochEnd": 55735,
    "syncProgress": "100.00"
}
```

Select the script UTxO for the `--tx-in` and create a valid number of outputs (in the below example two).

<pre class="language-bash"><code class="lang-bash"><strong># testnet/ExploringScriptContext/spend-script-funds-invalid-range.sh
</strong>
#!/usr/bin/env bash

NWMAGIC=2 # preview testnet
export CARDANO_NODE_SOCKET_PATH=$CNODE_HOME/sockets/node0.socket


cardano-cli transaction build \
    --testnet-magic $NWMAGIC \
    --change-address $(cat ../address/01.addr) \
    --invalid-before 25086665 \
    --tx-in e4a68d9cb4e58d47085c74426441445eaa30c2a60a9d102217d27ec0b0664db8#0 \
    --tx-in-script-file ../../compiled/ExploringScriptContext.plutus \
    --tx-in-datum-file ../../compiled/assets/unit.json \
    --tx-in-redeemer-file ../../compiled/assets/unit.json \
    --tx-in-collateral ee346be463426509daec07aba24a8905c5f55965daebb39f842a49191d83f9e1#0 \
    --tx-out $(cat ../address/01.addr)+1500000 \
    --tx-out $(cat ../address/01.addr)+1500000 \
    --out-file tx.body

cardano-cli transaction sign \
    --tx-body-file tx.body \
    --signing-key-file ../address/01.skey \
    --testnet-magic $NWMAGIC \
    --out-file tx.signed

cardano-cli transaction submit \
    --testnet-magic $NWMAGIC \
    --tx-file tx.signed
</code></pre>

Trying to build this transaction gives us a nice error message under `Script debugging logs:` since we used `traceIfFalse`.

```bash
./spend-script-funds-invalid-range.sh

Command failed: transaction build  Error: The following scripts have execution failures:
the script for transaction input 0 (in ascending 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: Tx does not have infinite range!
```

Okay, now let's see if the script fails when we try to create an invalid number of outputs. Create a `spend-script-utxo-invalid-utxos.sh` script to test this. This time, we omit the `--invalid-before` as we want the transaction to have infinite range to make sure the failure is from the number of outputs trying to be created.

```bash
# testnet/ExploringScriptContext/spend-script-utxo-invalid-utxos.sh

#!/usr/bin/env bash

NWMAGIC=2 # preview testnet
export CARDANO_NODE_SOCKET_PATH=$CNODE_HOME/sockets/node0.socket


cardano-cli transaction build \
    --testnet-magic $NWMAGIC \
    --change-address $(cat ../normal_address/01.addr) \
    --tx-in 1886d7f5af349199fd8fb74f37372b473c888cd40f19f5885ba470d8e25fb571#0 \
    --tx-in-script-file exploringContext.plutus \
    --tx-in-datum-file ../assets/unit.json \
    --tx-in-redeemer-file ../assets/unit.json \
    --tx-in-collateral 45337a0fb353dadc7e31f865378885207553b4471814384421e0fa1607271bf6#1 \
    --tx-out $(cat ../normal_address/01.addr)+1500000 \
    --tx-out $(cat ../normal_address/01.addr)+1500000 \
    --tx-out $(cat ../normal_address/01.addr)+1500000 \
    --tx-out $(cat ../normal_address/01.addr)+1500000 \
    --protocol-params-file ../normal_address/protocol.json \
    --out-file tx.body

cardano-cli transaction sign \
    --tx-body-file tx.body \
    --signing-key-file ../normal_address/01.skey \
    --testnet-magic $NWMAGIC \
    --out-file tx.signed

cardano-cli transaction submit \
    --testnet-magic $NWMAGIC \
    --tx-file tx.signed
```

Again, we get a nice error message explaining the failure.

```bash
./spend-script-funds-invalid-utxos.sh

Command failed: transaction build  Error: The following scripts have execution failures:
the script for transaction input 0 (in ascending 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: 4 or more outputs in tx!
```

The only thing left to test is whether a valid transaction will work. That is one with infinite range and less than four outputs. Let's create a `spend-script-funds.sh` to test it. The below example has just one output to be created specified via `--change-address`. With no other outputs present, all the tADA will go to this address after the transaction fees are paid.

<pre class="language-bash"><code class="lang-bash"># testnet/ExploringScriptContext/spend-script-utxo.sh

<strong>#!/usr/bin/env bash
</strong>
NWMAGIC=2 # preview testnet
export CARDANO_NODE_SOCKET_PATH=$CNODE_HOME/sockets/node0.socket


cardano-cli transaction build \
    --testnet-magic $NWMAGIC \
    --change-address $(cat ../address/01.addr) \
    --tx-in e4a68d9cb4e58d47085c74426441445eaa30c2a60a9d102217d27ec0b0664db8#0 \
    --tx-in-script-file ../../compiled/ExploringScriptContext.plutus \
    --tx-in-datum-file ../../compiled/assets/unit.json \
    --tx-in-redeemer-file ../../compiled/assets/unit.json \
    --tx-in-collateral ee346be463426509daec07aba24a8905c5f55965daebb39f842a49191d83f9e1#0 \
    --out-file tx.body

cardano-cli transaction sign \
    --tx-body-file tx.body \
    --signing-key-file ../address/01.skey \
    --testnet-magic $NWMAGIC \
    --out-file tx.signed

cardano-cli transaction submit \
    --testnet-magic $NWMAGIC \
    --tx-file tx.signed
</code></pre>

With this transaction, we can successfully spend the UTxO from the script address.

```bash
./spend-script-funds.sh

Estimated transaction fee: Lovelace 350224
Transaction successfully submitted.
```


# Overview

So far, we have worked only with the low-level untyped version of validator functions which use the `BuiltinData` type for its arguments. With typed validators, we can define our own types for validation arguments, simplifying things. These types still get compiled down to the low-level `BuiltinData` type, but our high-level code can be more understandable.

For typed validators, we will use the `mkTypedValidator` instead of the `mkValidatorScript` that we have been using so far. `mkTypedValidator` uses the `ToData` typeclass (<https://intersectMBO.github.io/plutus-apps/main/plutus-ledger-api/html/Plutus-V2-Ledger-Api.html#t:ToData>) to convert the given types to `BuiltinData` types. In Haddock, we can find that the instances for this typeclass are already defined for regular Haskell and Plutus types. In the case of using those basic types, we just need to create a new data type and make it an instance of the `ValidatorTypes` class (<https://intersectMBO.github.io/plutus-apps/main/plutus-ledger/html/Ledger-Typed-Scripts.html#t:ValidatorTypes>). The basic syntax for creating a validator type is as follows:

```haskell
data ArbitraryValidatorTypeName

instance Scripts.ValidatorTypes ArbitraryValidatorTypeName where
  type instance DatumType ArbitraryValidatorTypeName = Slot       -- Datum type (basic Plutus)
  type instance RedeemerType ArbitraryValidatorTypeName = Integer -- Redeemer type (basic Haskell)
```

With a typed validator, we use our defined types for `Datum` and `Redeemer` instead of the `BuiltinData` so the type signature of the `mkValidator` changes. Besides using our defined types for `Datum` and `Redeemer`, it also now returns a `Bool` instead of a `()`, with `True` signifying successful validation and `False` signifying a failed one.

```haskell
mkValidator :: Slot -> Integer -> Plutus.ScriptContext -> Bool
mkValidator = ...
```

Following that, we can create a ***typed*** validator with the validator we defined above using the `Plutus.Script.Utils` package:

```haskell
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
...

import qualified Plutus.Script.Utils.Typed as PSU
import qualified Plutus.Script.Utils.V2.Typed.Scripts as PSU.V2

typedValidator :: PSU.TypedValidator ArbitraryValidatorTypeName
typedValidator = PSU.V2.mkTypedValidator @ArbitraryValidatorTypeName
    $$(PlutusTx.compile [|| mkValidator ||])
    $$(PlutusTx.compile [|| wrap ||])
    where
        wrap = PSU.mkUntypedValidator
```

`PSU.TypedValidator` is version agnostic, but we must use `PSU.V2.mkTypedValidator` if we want to compile to Plutus V2. We also need the `{-# LANGUAGE TypeApplications #-}` and `{-# LANGUAGE TypeFamilies #-}` extensions for the above syntax to work properly.

### Creating Custom Data Types

If we want to create custom data types for our datum or redeemer, we must also create them as instances of the aforementioned `ToData` typeclass. We should simply use the [`PlutusTx.unstableMakeIsData`](https://intersectMBO.github.io/plutus-apps/main/plutus-tx/html/PlutusTx.html#v:unstableMakeIsData) on our defined datum/redeemer type. The difference between `unstableMakeIsData` and `makeIsDataIndexed` is that the latter ensures consistent indexing that is required to be specified and it is **recommended to use `makeIsDataIndexed` in production** because it ensures the same data structure results across different Plutus versions.

```haskell
data ExampleDatum = ExampleDatumConstr {
    field1 :: Field1Type,
    field2 :: Field2Type
  }
PlutusTx.unstableMakeIsData ''ExampleDatum
```

The rest is the same, we just use our data type for the datum/redeemer types:

```haskell
data ArbitraryValidatorTypeName

instance Scripts.ValidatorTypes ArbitraryValidatorTypeName where
  type instance DatumType ArbitraryValidatorTypeName = ExampleDatum -- Datum type (custom defined)
  type instance RedeemerType ArbitraryValidatorTypeName = Integer   -- Redeemer type (basic Haskell)
```


# A Shared Wallet Script

Now, we will write our first typed validator. It will act as a shared wallet between two trusted parties, where unlocking funds is allowed if either of their signatures is present in the spending transaction. For this example, we will define the public key hashes of the two parties in the ***datum***, and the validator will check that either of those hashes signed the transaction. We do not need to use the redeemer in this example, only the `datum` and `context`.

### Writing the validator

We can start off by creating our datum type, `SharedDatum`, and the corresponding `ValidatorTypes`, `Shared`. `SharedDatum` will have two fields, each corresponding to a `PubKeyHash` (from the `Plutus.V2.Ledger.Api` module) of one of the parties.

```haskell
-- create a new datum type
data SharedDatum = SharedDatum {
    wallet1 :: Plutus.PubKeyHash,
    wallet2 :: Plutus.PubKeyHash
  }
PlutusTx.unstableMakeIsData ''SharedDatum

-- create validator types
data SharedWalletValidator
instance Scripts.ValidatorTypes SharedWalletValidator where
  type instance DatumType SharedWalletValidator = SharedDatum
  type instance RedeemerType SharedWalletValidator = ()
```

Make sure that you import the `Scripts` package as:

```haskell
...

import qualified Ledger.Typed.Scripts as Scripts

...
```

Next, we need to write the `mkValidator` logic. As before, we need to destructure the transaction context to get `TxInfo`, and use the [`txSignedBy` ](https://intersectMBO.github.io/plutus-apps/main/plutus-ledger-api/html/Plutus-V2-Ledger-Contexts.html#v:txSignedBy)function from `Plutus.V2.Ledger.Contexts` to check for the signature. `txSignedBy` accepts two arguments, one of type `TxInfo` and the other `PubKeyHash`, returning `True` if the signature is present:

`txSignedBy :: TxInfo -> Plutus.V1.Ledger.Crypto.PubKeyHash -> Bool`

Our `mkValidator` type signature will be `mkValidator :: SharedDatum -> () -> Plutus.ScriptContext -> Bool`, and the main goal is to check for either of the two signatures:

`mkValidator sdat _ ctx = checkSignature1 || checkSignature2`

We then write the helper functions as before, `signature1` and `signature2` for deconstructing our datum type to get each of the corresponding signatures and the `checkSignature1` and `checkSignature2` functions to check each of them with `txSignedBy`. We can also add some error logging with `traceIfFalse`. The full function looks like this:

```haskell
mkValidator :: SharedDatum -> () -> Plutus.ScriptContext -> Bool
mkValidator sdat _ ctx = checkSignature1 || checkSignature2 
  where
    info :: Plutus.TxInfo
    info = Plutus.scriptContextTxInfo ctx

    signature1 :: PubKeyHash
    signature1 = wallet1 sdat

    signature2 :: PubKeyHash
    signature2 = wallet2 sdat

    checkSignature1 :: Bool
    checkSignature1 = traceIfFalse "signature 1 missing" $ txSignedBy info signature1
    
    checkSignature2 :: Bool
    checkSignature2 = traceIfFalse "signature 2 missing" $ txSignedBy info signature2
```

Make sure to import the `txSignedBy` function:

```haskell
...

import Plutus.V2.Ledger.Contexts (txSignedBy)

...
```

Now we have a function of type `SharedDatum -> () -> Plutus.ScriptContext -> Bool`, but remember that we always have to get down to the Untyped Plutus Core version of a validator: `BuiltinData -> BuiltinData -> BuiltinData -> ()`. So with typed validators, we have to do some extra steps to get there. Instead of the simple `Plutus.mkValidatorScript`, we need to use `PSU.V2.mkTypedValidator` (from `Plutus.Script.Utils.V2.Typed.Scripts` which we also need to import). The type signature of `PSU.V2.mkTypedValidator` is:

```haskell
-- | Make a 'TypedValidator' from the 'CompiledCode' of a validator script and its wrapper.
mkTypedValidator ::
    CompiledCode (ValidatorType a)
    -- ^ Validator script (compiled)
    -> CompiledCode (ValidatorType a -> WrappedValidatorType)
    -- ^ A wrapper for the compiled validator
    -> TypedValidator a
```

It accepts a compiled code of a typed validator (with some `ValidatorType a`) and a wrapper that is a function of compiled code `ValidatorType a -> WrappedValidatorType`. The `WrappedValidatorType` is simply a synonym for the basic validator function `BuiltinData -> BuiltinData -> BuiltinData -> ()`. That wrapper function for us is simply `PSU.mkUntypedValidator` which has the type signature:

```haskell
mkUntypedValidator
    :: forall d r
    . (PV1.UnsafeFromData d, PV1.UnsafeFromData r)
    => (d -> r -> sc -> Bool)
    -> UntypedValidator
```

What this means is simply that instead of compiling just the validator function to Plutus core with `$$(PlutusTx.compile [|| mkValidator ||])`, we also need to compile this wrapper. So `PSU.V2.mkTypedValidator` ends up being applied to both of the compiled code instances:

```haskell
typedValidator :: PSU.TypedValidator SharedWalletValidator
typedValidator = PSU.V2.mkTypedValidator @SharedWalletValidator
    $$(PlutusTx.compile [|| mkValidator ||])
    $$(PlutusTx.compile [|| wrap ||])
    where
        wrap = PSU.mkUntypedValidator
```

In order for this to work, we also need to enable the `DataKinds` GHC extension.

```haskell
{-# LANGUAGE DataKinds #-}
```

Make sure that the `plutus-script-utils` packages are imported:

```haskell
...

import qualified Plutus.Script.Utils.V2.Typed.Scripts as PSU.V2
import qualified Plutus.Script.Utils.Typed as PSU

...
```

From there, the rest is the same as before with only a minor difference in getting the actual validator and its hash. When compiling untyped validators, we got a type of `Plutus.Validator` as the compilation result. However, with `TypedValidator` we get a type that has multiple fields so we need to destructure it first to get to `Plutus.Script` type that we can use to serialise the script:

```haskell
validator :: Plutus.Validator  -- uses tvValidator field to get the validator
validator = PSU.V2.validatorScript typedValidator

script :: Plutus.Script -- gets the hash
script = Plutus.unValidatorScript validator
```

Lastly, we just need to add serialise/write file functions for this module.

```haskell
scriptShortBs :: SBS.ShortByteString
scriptShortBs = SBS.toShort . LBS.toStrict $ serialise script

scriptSerialised :: PlutusScript PlutusScriptV2
scriptSerialised = PlutusScriptSerialised scriptShortBs

writeSerialisedScript :: IO (Either (FileError ()) ())
writeSerialisedScript = writeFileTextEnvelope "compiled/SharedWallet.plutus" Nothing scriptSerialised
```

For reference, here is the full list of imports for this module:

```haskell
...

import qualified PlutusTx
import PlutusTx.Prelude
import qualified Plutus.V2.Ledger.Api as Plutus

import Cardano.Api.Shelley (PlutusScript (PlutusScriptSerialised), PlutusScriptV2, writeFileTextEnvelope)
import Cardano.Api (FileError)

import qualified Data.ByteString.Lazy as LBS
import qualified Data.ByteString.Short as SBS
import Codec.Serialise

import qualified Ledger.Typed.Scripts as Scripts
import qualified Plutus.Script.Utils.V2.Typed.Scripts as PSU.V2
import qualified Plutus.Script.Utils.Typed as PSU
import Plutus.V2.Ledger.Contexts (txSignedBy)

import Prelude (IO)

...
```

### Serialising a custom datum type

That's it for the script. We now need to create the correct datum and learn how to construct valid transactions for this use case. First of all, how can we get a `PubKeyHash` of an address? We can use the `cardano-cli address key-hash` command:

```bash
cardano-cli address key-hash \
    --payment-verification-key-file ../address/01.vkey
a5d318dadfb52eeffb260ae097f846aea0ca78e6cc4fe406d4ceedc0

cardano-cli address key-hash \
    --payment-verification-key-file ../address/02.vkey
1b1e5895b03302b248e8c459817bab49471c4013a0806ac52cb73f9b
```

That gets us the `PubKeyHash`es. How can we write them to a valid datum file in JSON format? We can create and import the `SharedDatum` type (we have to export it first) from the `TypedValidator.hs` module and create an instance of it, then serialise and write it to a file. We already have our `Utils` module to write Plutus data to JSON so we can use that. We just need to use some REPL wizardry to do it right. First off, we want to export the `SharedDatum` data type from our `SharedWallet.hs` in order to be able to import it somewhere else. We use the `SharedDatum (..)` syntax to export the type constructor and not just the type.

```haskell
module SharedWallet
  (
    scriptSerialised,
    writeSerialisedScript,
    SharedDatum (..)
  )
where
```

Next, update the `exposed-modules` in the `.cabal` file of the project for `SharedWallet`:

```haskell
...
    exposed-modules:      SimplestSuccess
                        , GuessingGame
                        , ExploringScriptContext
                        , SharedWallet -- add SharedWallet here
                        , Helpers.Utils
...
```

We are now ready to load up our `cabal repl` and start importing:

```haskell
Prelude SimplestSuccess> import SharedWallet 
Prelude SharedWallet SimplestSuccess> import Helpers.Utils 
Prelude SharedWallet Helpers.Utils SimplestSuccess> :set -XOverloadedStrings
Prelude SharedWallet Helpers.Utils SimplestSuccess> myDatum = SharedDatum "a5d318dadfb52eeffb260ae097f846aea0ca78e6cc4fe406d4ceedc0" "1b1e5895b03302b248e8c459817bab49471c4013a0806ac52cb73f9b"
Prelude SharedWallet Helpers.Utils SimplestSuccess> writeJSONData "compiled/assets/SharedDatum.json"
```

We used `:set -XOverloadedStrings` to enable the overloaded strings extension inside the REPL in order for it to be able to interpret our strings as `PubKeyHash`es, which is the type our datum requires. We end up with the following in `compiled/assets/SharedDatum.json`:

```json
{"constructor":0,"fields":[{"bytes":"a5d318dadfb52eeffb260ae097f846aea0ca78e6cc4fe406d4ceedc0"},{"bytes":"1b1e5895b03302b248e8c459817bab49471c4013a0806ac52cb73f9b"}]}
```

We now have everything we need to start testing the validator on the testnet.

### Testing the validator

Let's create a script address for this validator in `create-script-address.sh`.

```bash
#!/usr/bin/env bash

NWMAGIC=2 # preview testnet

# Build script address
cardano-cli address build \
--payment-script-file ../../compiled/SharedWallet.plutus \
--testnet-magic $NWMAGIC \
--out-file SharedWallet.addr

echo "Script address: $(cat SharedWallet.addr)"
```

We need to update the `check-utxos.sh` for this validator as well.

```bash
#!/usr/bin/env bash

NWMAGIC=2 # preview testnet
export CARDANO_NODE_SOCKET_PATH=$CNODE_HOME/sockets/node0.socket

funds_normal=$(cardano-cli query utxo \
--address $(cat ../address/01.addr) \
--testnet-magic $NWMAGIC)

funds_script=$(cardano-cli query utxo \
--address $(cat SharedWallet.addr) \
--testnet-magic $NWMAGIC)

echo "Normal address:"
echo "${funds_normal}"

echo "Script address:"
echo "${funds_script}"
```

After running these two scripts, we see the UTxO status. The script address does not have any UTxOs on it.

```bash
./create-script-address.sh 
Script address: addr_test1wqtul3uvnfqvk7a52fa7r5wcrn6alna6t6pd684jj8mmdvgdxn9r9

./check-utxos.sh 
Normal address:
                           TxHash                                 TxIx        Amount
--------------------------------------------------------------------------------------
5dc5111e257f8e68b0978c9619e57bbb12d365c0ec45d879115866bb674156ae     0        1826915 lovelace + TxOutDatumNone
e4a68d9cb4e58d47085c74426441445eaa30c2a60a9d102217d27ec0b0664db8     1        9985492189 lovelace + TxOutDatumNone
ede24e9e40ca82830c75d827b5c3b090132c1afaebd3a4256655fb5d2382474a     0        9649776 lovelace + TxOutDatumNone
ee346be463426509daec07aba24a8905c5f55965daebb39f842a49191d83f9e1     0        1829006 lovelace + TxOutDatumNone

Script address:
                           TxHash                                 TxIx        Amount
--------------------------------------------------------------------------------------
```

We need to supply the script with some funds in order to test that we can spend it with a valid signature. We already serialised our datum that specifies the two public key hashes that are allowed to spend the funds associated with the UTxO. Let's create a `send-funds-to-script.sh` that will do that for us by sending 20 tADA to the script along with the datum.

```bash
#!/usr/bin/env bash

NWMAGIC=2 # preview testnet
export CARDANO_NODE_SOCKET_PATH=$CNODE_HOME/sockets/node0.socket

cardano-cli transaction build \
    --testnet-magic $NWMAGIC \
    --change-address $(cat ../address/01.addr) \
    --tx-in e4a68d9cb4e58d47085c74426441445eaa30c2a60a9d102217d27ec0b0664db8#1 \
    --tx-out $(cat SharedWallet.addr)+20000000 \
    --tx-out-datum-embed-file ../../compiled/assets/SharedDatum.json \
    --out-file tx.body

cardano-cli transaction sign \
    --tx-body-file tx.body \
    --signing-key-file ../address/01.skey \
    --testnet-magic $NWMAGIC \
    --out-file tx.signed

cardano-cli transaction submit \
    --testnet-magic $NWMAGIC \
    --tx-file tx.signed
```

Checking the UTxOs on the script shows us the new output with the hash of our datum:

```bash
Script address:
                           TxHash                                 TxIx        Amount
--------------------------------------------------------------------------------------
b980f55aade4508803dcac1c48c28554ee9cf942e40ac1cb5e40e48a621263a5     0        20000000 lovelace + TxOutDatumHash ScriptDataInBabbageEra "7857b572c6e6f6fdacffef2bdec1ecc87e32b805c11c75abd59ad9d18e7f438f"
```

We now want to spend this UTxO. Let's try it first without signing the transaction with anything. Create a `spend-script-funds-no-signature.sh`.

```bash
#!/usr/bin/env bash

NWMAGIC=2 # preview testnet
export CARDANO_NODE_SOCKET_PATH=$CNODE_HOME/sockets/node0.socket


cardano-cli transaction build \
    --testnet-magic $NWMAGIC \
    --change-address $(cat ../address/02.addr) \
    --tx-in b980f55aade4508803dcac1c48c28554ee9cf942e40ac1cb5e40e48a621263a5#0 \
    --tx-in-script-file ../../compiled/SharedWallet.plutus \
    --tx-in-datum-file ../../compiled/assets/SharedDatum.json \
    --tx-in-redeemer-file ../../compiled/assets/unit.json \
    --tx-in-collateral ee346be463426509daec07aba24a8905c5f55965daebb39f842a49191d83f9e1#0 \
    --out-file tx.body

cardano-cli transaction submit \
    --testnet-magic $NWMAGIC \
    --tx-file tx.signed
```

Running this will give us an error:

```bash
./spend-script-funds-no-signature.sh 
Command failed: transaction build  Error: The following scripts have execution failures:
...
Script debugging logs: signature 1 missing
signature 2 missing
```

We see that the `transaction build` command failed before we even get to the point where we sign the transaction with `cardano-cli transaction sign`. This is because the `transaction build` command must already run the validator in question to determine whether the transaction is valid. As our validator checks the transaction signatures with `txSignedBy`, it will certainly fail validation since the transaction is not signed by anything at this build stage. So we need a way to tell the transaction-building command that the transaction *needs to be signed* by some private key corresponding to a public key hash.

This is where the `--required-signer-hash` option comes in.

```bash
cardano-cli transaction build --help
...
--required-signer-hash HASH
                           Hash of the verification key (zero or more) whose
                           signature is required.
...
```

The `--required-signer-hash` will run the validator simulation *as if the transaction was signed with the private key matching the specified public key hash*. Besides creating the correct simulation for the validator, this option will also make the transaction invalid for submitting *unless* it really is signed by the correct key. We can check this ourselves by specifying the `--required-signer-hash` to pass validator simulation, but then try submitting the transaction without a signature. Let's update the `cardano-cli transaction build` command in our `spend-script-funds-no-signature.sh` to include the `--required-signer-hash` option.

```bash
cardano-cli transaction build \
    --testnet-magic $NWMAGIC \
    --change-address $(cat ../address/02.addr) \
    --tx-in b980f55aade4508803dcac1c48c28554ee9cf942e40ac1cb5e40e48a621263a5#0 \
    --tx-in-script-file ../../compiled/SharedWallet.plutus \
    --tx-in-datum-file ../../compiled/assets/SharedDatum.json \
    --tx-in-redeemer-file ../../compiled/assets/unit.json \
    --tx-in-collateral ee346be463426509daec07aba24a8905c5f55965daebb39f842a49191d83f9e1#0 \
    --required-signer-hash a5d318dadfb52eeffb260ae097f846aea0ca78e6cc4fe406d4ceedc0 \
    --out-file tx.body
```

We will get through the validator run this time, but the transaction will still fail to be submitted as expected.

```bash
./spend-script-funds-no-signature.sh 
Estimated transaction fee: Lovelace 317891
Command failed: transaction submit  Error: Error while submitting tx: ShelleyTxValidationError ShelleyBasedEraBabbage (ApplyTxError [UtxowFailure (UtxoFailure (AlonzoInBabbageUtxoPredFailure (ValueNotConservedUTxO (MaryValue 0 (MultiAsset (fromList []))) (MaryValue 9985492189 (MultiAsset (fromList [])))))),UtxowFailure (UtxoFailure (AlonzoInBabbageUtxoPredFailure (BadInputsUTxO (fromList [TxIn (TxId {unTxId = SafeHash "e4a68d9cb4e58d47085c74426441445eaa30c2a60a9d102217d27ec0b0664db8"}) (TxIx 1)]))))])
```

That's enough testing invalid transactions for this validator. Finally, let's create a valid transaction that will spend the funds by signing the transaction with our `02.skey` (even though the funds were sent from `01.addr`). Create a `spend-script-funds.sh` script with an updated `--required-signer-hash`, and sign and submit the transaction. The change address will be `02.addr`.

```bash
#!/usr/bin/env bash

NWMAGIC=2 # preview testnet
export CARDANO_NODE_SOCKET_PATH=$CNODE_HOME/sockets/node0.socket


cardano-cli transaction build \
    --testnet-magic $NWMAGIC \
    --change-address $(cat ../address/02.addr) \
    --tx-in b980f55aade4508803dcac1c48c28554ee9cf942e40ac1cb5e40e48a621263a5#0 \
    --tx-in-script-file ../../compiled/SharedWallet.plutus \
    --tx-in-datum-file ../../compiled/assets/SharedDatum.json \
    --tx-in-redeemer-file ../../compiled/assets/unit.json \
    --tx-in-collateral ee346be463426509daec07aba24a8905c5f55965daebb39f842a49191d83f9e1#0 \
    --required-signer-hash 1b1e5895b03302b248e8c459817bab49471c4013a0806ac52cb73f9b \
    --out-file tx.body

cardano-cli transaction sign \
    --tx-body-file tx.body \
    --signing-key-file ../address/02.skey \
    --testnet-magic $NWMAGIC \
    --out-file tx.signed

cardano-cli transaction submit \
    --testnet-magic $NWMAGIC \
    --tx-file tx.signed
```

Interestingly, the transaction still fails at the submit stage. But notice that the transaction did successfully pass the validator simulation before failing.

```bash
./spend-script-funds.sh 
Estimated transaction fee: Lovelace 317891
Command failed: transaction submit  Error: Error while submitting tx: ShelleyTxValidationError ShelleyBasedEraBabbage (ApplyTxError [UtxowFailure (AlonzoInBabbageUtxowPredFailure (ShelleyInAlonzoUtxowPredFailure (MissingVKeyWitnessesUTXOW (fromList [KeyHash "a5d318dadfb52eeffb260ae097f846aea0ca78e6cc4fe406d4ceedc0"]))))])
```

It says we have a `MissingVKeyWitnessesUTXOW` corresponding to `a5d318dadfb52eeffb260ae097f846aea0ca78e6cc4fe406d4ceedc0`. But that is our `01.addr` public key hash! Why is it complaining about it? Well, remember what we said about collateral inputs, they must always be present with script transactions to cover potential failures. Our collateral input for this transaction is still `ee346be463426509daec07aba24a8905c5f55965daebb39f842a49191d83f9e1#0`, which belongs to `01.addr` so clearly the transaction must be signed by `01.skey` as well in order to allow the usage of this UTxO. Let's add that signature to the `cardano-cli transaction sign` command to allow the transaction to use that collateral input.

```bash
...

cardano-cli transaction sign \
    --tx-body-file tx.body \
    --signing-key-file ../address/01.skey \
    --signing-key-file ../address/02.skey \
    --testnet-magic $NWMAGIC \
    --out-file tx.signed

...
```

Submitting the transaction again works as expected now.

```bash
./spend-script-funds.sh 
Estimated transaction fee: Lovelace 317891
Transaction successfully submitted.
```

If we check our `02.addr` UTxOs, we will see the funds we just spent from the script.

```bash
cardano-cli query utxo \
--address $(cat ../address/02.addr) \
--testnet-magic 2 \
--socket-path $CNODE_HOME/sockets/node0.socket

                           TxHash                                 TxIx        Amount
--------------------------------------------------------------------------------------
59590fab00fb430d205151c59ca7e00af38e9945d778abdae6897f368aa39591     0        19682109 lovelace + TxOutDatumNone
```


# Overview

So far, we have been using the `Datum`, `Redeemer` and `Context` fields to express the validation logic of our scripts. However, there is a very valuable method of creating validators that do not rely only on those three fields. Recall our [shared wallet validator](/typed-validators/a-shared-wallet-script) where we had to put the public key hashes inside the datum to sit at the script UTxO. Imagine that instead of those hashes being specified in the datum, and then having the script look at the datum, we could instead *bake* *in* those public key hashes inside the script itself. In that case, the script would no longer need to look at the datum to determine whether a transaction is valid or not. Instead, it would already have that information inside the script itself. These types of validators are referred to as **parameterised validators**.

It is important to note that, as always, validator scripts are compiled down to the untyped form of `BuiltinData -> BuiltinData -> BuiltinData -> ()`, even with parameterised validators. However, in this case, we can write our logic in a different type signature that allows us to write the validators in a more high-level way. The type signature of the `mkValidator` function in parameterised validators is:

`ValidatorParam(s) -> DatumType -> RedeemerType -> ScriptContext -> Bool`.

The new argument `ValidatorParam` allows us to bake in any data we want into the script itself. We can define it with as many fields as we want, but as before, unless we use types that are already instances of `ToData` typeclass, we have to instantiate them and additionally, with parameter types, we have to ***lift*** them. Lifting values or types means compiling the Haskell code to Plutus IR (intermediate representation, which is later compiled into Plutus Core) at runtime. The result of a lifted `Integer` for example is `CompiledCode Integer`.&#x20;

As with [typed validators](/typed-validators/overview), we can still define our own `Datum` and `Redeemer` types. And we have to create the `ValidatorTypes` instance to use with our validator as before.


# A Deadline Script

Let's write a parameterised validator that is a simple deadline function. Before the deadline, all transactions are validated, and after the deadline, all are invalidated. The deadline will be our parameter for the validator that is baked in the script. This deadline needs to be expressed in the `Plutus.POSIXTime` type, which is measured as the number of ***milliseconds*** since `1970-01-01T00:00:00Z`. Plutus always works with POSIXTime, while the Cardano chain works with `slots`. The reason for this discrepancy is that the slot length of the chain is a parameter that can change over time.

### Writing the validator

Let's create a new file `DeadlineParam.hs`, define the module `DeadlineParam` and add the same imports as before. We can start off by creating the simple `DeadlineValidator` type for the validator. Since we don't need the datum and redeemer in this case, we can omit their definitions to apply the default `()` type for both of them.

```haskell
data Deadline
instance Scripts.ValidatorTypes Deadline
    -- default types for datum and redeemer are ()
```

Since `POSIXTime` already is an instance of `ToData`, we don't need to worry about lifting values right now and can go straight to the `mkValidator` function. The signature will be:

```haskell
mkValidator :: Plutus.POSIXTime -> () -> () -> Plutus.ScriptContext -> Bool
```

Inside the function, we want to check that the `txInfoValidRange` is contained in its entirety in the interval of negative infinity to the deadline.

{% hint style="warning" %}
Important to note that the ***ENTIRE*** transaction validity range must fall into this interval because if the positive end of the valid range would go over the deadline, the transaction would be validated after the deadline even if the majority of the valid range is before the deadline!
{% endhint %}

We will need to use some functions from the [`Interval` module](https://intersectMBO.github.io/plutus/master/plutus-ledger-api/html/PlutusLedgerApi-V1-Interval.html) to determine that, namely `contains` and `to`.

```haskell
import Plutus.V1.Ledger.Interval (contains, to)

...

mkValidator :: Plutus.POSIXTime -> () -> () -> Plutus.ScriptContext -> Bool
mkValidator deadline _ _ ctx =
  traceIfFalse "Invalid tx range" $ to deadline `contains` txRange
    where
      info :: Plutus.TxInfo
      info = Plutus.scriptContextTxInfo ctx

      txRange :: Plutus.POSIXTimeRange
      txRange = Plutus.txInfoValidRange info
```

We destructure our `ctx` as before to get to the `txInfoValidRange` field. Then we state the predicate ``to deadline `contains` txRange`` which reads as *"the interval from negative infinity to our deadline (inclusive) contains the entire interval of the transaction validity range"*.

Now, we need to compile the parameterised validator. We do this with the `PSU.V2.mkTypedValidatorParam` instead of `PSU.V2.mkTypedValidator`. Here is the `mkTypedValidatorParam` definition:

```haskell
-- | Make a 'TypedValidator' from the 'CompiledCode' of a parameterized validator script and its wrapper.
mkTypedValidatorParam ::
  forall a param.
  Lift DefaultUni param =>
  -- | Validator script (compiled)
  CompiledCode (param -> ValidatorType a) ->
  -- | A wrapper for the compiled validator
  CompiledCode (ValidatorType a -> UntypedValidator) ->
  -- | The extra paramater for the validator script
  param ->
  TypedValidator a
mkTypedValidatorParam vc wrapper param =
  mkTypedValidator (vc `applyCode` liftCode param) wrapper
```

This function takes similar arguments as before. `CompiledCode (param -> ValidatorType a)` is our parameterised `mkValidator` function, `CompiledCode (ValidatorType a -> UntypedValidator)` is our wrapper to `BuiltinData -> BuiltinData -> BuiltinData -> ()`, and what we get as a result is `param -> TypedValidator a` which will be the type signature of our `typedValidator` function. This makes sense, as our validator accepts a parameter to be baked in the validator. The validator can only be completed once that parameter is received and applied, finally resulting in `UntypedValidator`. Our `typedValidator` function now looks like this:

```haskell
typedValidator :: Plutus.POSIXTime -> PSU.V2.TypedValidator Deadline
typedValidator = PSU.V2.mkTypedValidatorParam @Deadline
    $$(PlutusTx.compile [|| mkValidator ||])
    $$(PlutusTx.compile [|| wrap ||])
    where
        wrap = PSU.mkUntypedValidator
```

The next step is to get the script from our validator. Before we used simply `PSU.V2.validatorScript typedValidator` and `Plutus.unValidatorScript validator`, but since `typedValidator` now accepts one argument, we need to compose these functions together, and the `validator` and `script` functions also must receive the deadline parameter:

```haskell
validator :: Plutus.POSIXTime -> Plutus.Validator
validator = PSU.V2.validatorScript . typedValidator

script :: Plutus.POSIXTime -> Plutus.Script
script = Plutus.unValidatorScript . validator

-- Note: we could write it a different way, this is using ETA reduction.
```

The last step is to write the serialised script to a file. Our writing script functions change a bit as a result of the additional parameter the `script` function must receive. At this stage, we simply need to apply the parameter to the `script` function. We will write it in a way so that `writeSerialisedDeadlineParamScript` accepts the deadline parameter and passes it on to create a script with our specified deadline. So using this function we can create many disfferent scripts of the same family (same validation logic), but with different deadline parameters.

```haskell
scriptShortBs :: Plutus.POSIXTime -> SBS.ShortByteString
scriptShortBs deadline = SBS.toShort . LBS.toStrict $ serialise $ script deadline

scriptSerialised :: Plutus.POSIXTime -> PlutusScript PlutusScriptV2
scriptSerialised deadline = PlutusScriptSerialised $ scriptShortBs deadline

writeSerialisedScript :: Plutus.POSIXTime -> IO (Either (FileError ()) ())
writeSerialisedScript deadline = writeFileTextEnvelope "compiled/DeadlineParam.plutus" Nothing $ scriptSerialised deadline
```

That's it! We can now load our new module in `cabal repl` and write the script to a file. Of course, we need to provide the actual `POSIXTime` parameter to specify the deadline. For testing, we can get the current time with `date %s` and add 20 minutes to it to give us time for testing:

{% hint style="info" %}
Remember, we are always working with POSIXTime in *miliseconds* when it comes to Plutus.
{% endhint %}

```bash
expr $(date +%s000) + 1200000
1692181336000
```

That gives us our deadline in POSIXTime one hour from now. Every transaction we submit until then will be validated!

`ghci> writeSerialisedScript 1692181336000`

### Testing the validator

As always, we create the script address first in `testnet/DeadlineParam/create-script-address.sh`.

```bash
#!/usr/bin/env bash

NWMAGIC=2 # preview testnet

# Build script address
cardano-cli address build \
--payment-script-file deadlineParam.plutus \
--testnet-magic $NWMAGIC \
--out-file deadlineParam.addr

echo "Script address: $(cat deadlineParam.addr)"
```

```bash
./create-script-address.sh 
Script address: addr_test1wqc0caz44aluw7wcsxct7annp680k2ucklv6r8vgzwqnvnsxd04jf
```

Create the `check-utxos.sh` for this script. Let's print out UTxOs for both of our normal addresses.

```bash
#!/usr/bin/env bash

NWMAGIC=2 # preview testnet
export CARDANO_NODE_SOCKET_PATH=$CNODE_HOME/sockets/node0.socket

funds_normal1=$(cardano-cli query utxo \
--address $(cat ../address/01.addr) \
--testnet-magic $NWMAGIC)

funds_normal2=$(cardano-cli query utxo \
--address $(cat ../address/02.addr) \
--testnet-magic $NWMAGIC)


funds_script=$(cardano-cli query utxo \
--address $(cat DeadlineParam.addr) \
--testnet-magic $NWMAGIC)

echo "Normal address 1:"
echo "${funds_normal1}"

echo "Normal address 2:"
echo "${funds_normal2}"

echo "Script address:"
echo "${funds_script}"
```

```bash
./check-utxos.sh 
Normal address 1:
                           TxHash                                 TxIx        Amount
--------------------------------------------------------------------------------------
5dc5111e257f8e68b0978c9619e57bbb12d365c0ec45d879115866bb674156ae     0        1826915 lovelace + TxOutDatumNone
ede24e9e40ca82830c75d827b5c3b090132c1afaebd3a4256655fb5d2382474a     0        9649776 lovelace + TxOutDatumNone
ee346be463426509daec07aba24a8905c5f55965daebb39f842a49191d83f9e1     0        1829006 lovelace + TxOutDatumNone
f455f1d31f2de72a25ccfb3874ca7702401297bb72ceba8625773dfb348d2bc5     2        9884977118 lovelace + TxOutDatumNone
Normal address 2:
                           TxHash                                 TxIx        Amount
--------------------------------------------------------------------------------------
59590fab00fb430d205151c59ca7e00af38e9945d778abdae6897f368aa39591     0        19682109 lovelace + TxOutDatumNone
Script address:
                           TxHash                                 TxIx        Amount
--------------------------------------------------------------------------------------
```

Time to send some funds to the script. Let's create two outputs, one that we intend to spend before the deadline and another to test that we cannot spend it after the deadline. Don't forget to attach a datum to both of these or they will be unspendable in any case!

```bash
#!/usr/bin/env bash

NWMAGIC=2 # preview testnet
export CARDANO_NODE_SOCKET_PATH=$CNODE_HOME/sockets/node0.socket

cardano-cli transaction build \
    --testnet-magic $NWMAGIC \
    --change-address $(cat ../address/01.addr) \
    --tx-in f455f1d31f2de72a25ccfb3874ca7702401297bb72ceba8625773dfb348d2bc5#2 \
    --tx-out $(cat DeadlineParam.addr)+20000000 \
    --tx-out-datum-embed-file ../../compiled/assets/unit.json \
    --tx-out $(cat DeadlineParam.addr)+20000000 \
    --tx-out-datum-embed-file ../../compiled/assets/unit.json \
    --out-file tx.body

cardano-cli transaction sign \
    --tx-body-file tx.body \
    --signing-key-file ../address/01.skey \
    --testnet-magic $NWMAGIC \
    --out-file tx.signed

cardano-cli transaction submit \
    --testnet-magic $NWMAGIC \
    --tx-file tx.signed
```

After our transaction is processed, we can check the UTxO balance again and see the two UTxOs at the script address.

```bash
./send-funds-to-script.sh 
Estimated transaction fee: Lovelace 172453
Transaction successfully submitted.

./check-utxos.sh 
Normal address 1:
                           TxHash                                 TxIx        Amount
--------------------------------------------------------------------------------------
5dc5111e257f8e68b0978c9619e57bbb12d365c0ec45d879115866bb674156ae     0        1826915 lovelace + TxOutDatumNone
6924903343947231af6c56a5d2d25b3256a513dee77e7966b6f8a47b09913188     2        9844804665 lovelace + TxOutDatumNone
ede24e9e40ca82830c75d827b5c3b090132c1afaebd3a4256655fb5d2382474a     0        9649776 lovelace + TxOutDatumNone
ee346be463426509daec07aba24a8905c5f55965daebb39f842a49191d83f9e1     0        1829006 lovelace + TxOutDatumNone
Normal address 2:
                           TxHash                                 TxIx        Amount
--------------------------------------------------------------------------------------
59590fab00fb430d205151c59ca7e00af38e9945d778abdae6897f368aa39591     0        19682109 lovelace + TxOutDatumNone
Script address:
                           TxHash                                 TxIx        Amount
--------------------------------------------------------------------------------------
6924903343947231af6c56a5d2d25b3256a513dee77e7966b6f8a47b09913188     0        20000000 lovelace + TxOutDatumHash ScriptDataInBabbageEra "923918e403bf43c34b4ef6b48eb2ee04babed17320d8d1b9ff9ad086e86f44ec"
6924903343947231af6c56a5d2d25b3256a513dee77e7966b6f8a47b09913188     1        20000000 lovelace + TxOutDatumHash ScriptDataInBabbageEra "923918e403bf43c34b4ef6b48eb2ee04babed17320d8d1b9ff9ad086e86f44ec"
```

Time to successfully spend one of the outputs before the deadline. We need to set the correct valid range for this transaction (remember the default is infinite which would be invalidated by our validator). We can get the current slot of the chain with:

```bash
cardano-cli query tip --testnet-magic 2 --socket-path $CNODE_HOME/sockets/node0.socket
{
    "block": 1117738,
    "epoch": 295,
    "era": "Babbage",
    "hash": "f3c6f5cabd28845159c1044e4dffb4b7a18170352fe4d79671fc0181aca1e2be",
    "slot": 25524308, # This is our current slot
    "slotInEpoch": 36308,
    "slotsToEpochEnd": 50092,
    "syncProgress": "100.00"
}
```

Using the `--invalid-hereafter` option in the `transaction build` command, we can set the upper limit of the transaction validity range to the current slot plus some time to allow the transaction to be processed, but not passed the deadline. For example, our current slot is `25524308` and we will add 300 seconds to it for the transaction to make it `25524608` in our `spend-script-funds.sh` for this validator:

{% hint style="info" %}
Remember, we are always working with *slots* when it comes to `cardano-cli` or `cardano-node`.
{% endhint %}

```bash
#!/usr/bin/env bash

NWMAGIC=2 # preview testnet
export CARDANO_NODE_SOCKET_PATH=$CNODE_HOME/sockets/node0.socket


cardano-cli transaction build \
    --testnet-magic $NWMAGIC \
    --change-address $(cat ../address/02.addr) \
    --invalid-hereafter 25524608 \
    --tx-in 6924903343947231af6c56a5d2d25b3256a513dee77e7966b6f8a47b09913188#0 \
    --tx-in-script-file ../../compiled/DeadlineParam.plutus \
    --tx-in-datum-file ../../compiled/assets/unit.json \
    --tx-in-redeemer-file ../../compiled/assets/unit.json \
    --tx-in-collateral ee346be463426509daec07aba24a8905c5f55965daebb39f842a49191d83f9e1#0 \
    --out-file tx.body

cardano-cli transaction sign \
    --tx-body-file tx.body \
    --signing-key-file ../address/01.skey \
    --testnet-magic $NWMAGIC \
    --out-file tx.signed

cardano-cli transaction submit \
    --testnet-magic $NWMAGIC \
    --tx-file tx.signed
```

Running `spend-script-funds.sh` will submit the transaction successfully and the script UTxO will be spent with the change sent to our `02.addr`.

```bash
./spend-script-funds.sh 
Estimated transaction fee: Lovelace 326823
Transaction successfully submitted.
```

To test that we cannot just spend a script UTxO with any `--invalid-hereafter` option, let's try to submit a transaction in which the right side of the validity range falls after the deadline. To make sure it is after the deadline, we can simply add one hour to the current slot, since we know that will be past the deadline. So instead of `25524608`, let's use `25528208` (`25524608 + 3600`). We can call this file `spend-script-funds-past-deadline.sh`. We also have to specify the other UTxO on the script address, since we already spent the first one.

```bash
#!/usr/bin/env bash

NWMAGIC=2 # preview testnet
export CARDANO_NODE_SOCKET_PATH=$CNODE_HOME/sockets/node0.socket


cardano-cli transaction build \
    --testnet-magic $NWMAGIC \
    --change-address $(cat ../address/02.addr) \
    --invalid-hereafter 25528208 \
    --tx-in 6924903343947231af6c56a5d2d25b3256a513dee77e7966b6f8a47b09913188#1 \
    --tx-in-script-file ../../compiled/DeadlineParam.plutus \
    --tx-in-datum-file ../../compiled/assets/unit.json \
    --tx-in-redeemer-file ../../compiled/assets/unit.json \
    --tx-in-collateral ee346be463426509daec07aba24a8905c5f55965daebb39f842a49191d83f9e1#0 \
    --out-file tx.body

cardano-cli transaction sign \
    --tx-body-file tx.body \
    --signing-key-file ../address/01.skey \
    --testnet-magic $NWMAGIC \
    --out-file tx.signed

cardano-cli transaction submit \
    --testnet-magic $NWMAGIC \
    --tx-file tx.signed
```

Attempting to build this transaction will fail instantly since the validator will run locally and invalidate the transaction with:

```bash
./spend-script-funds-past-deadline.sh
Command failed: transaction build  Error: The following scripts have execution failures:
the script for transaction input 0 (in ascending 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: Invalid tx range
```


# Another Shared Wallet Script

The previous example used the `POSIXTime` type as the script parameter. For the following example, we will look at custom-defined parameter types as there is some extra work we need to do in that case. We will transform the *SharedWallet* script from earlier to be parameterised instead of relying on the UTxO datum. That means that either of the trusted parties can spend any UTxO sitting at the script address, regardless of what the datum associated is.

### Writing the validator

Firstly, we create the same type as before, this time calling it `sharedParam`:

```haskell
data SharedWalletParam = SharedWalletParam {
    wallet1 :: Plutus.PubKeyHash,
    wallet2 :: Plutus.PubKeyHash
}
```

As before, we need to make our parameter type an instance of `ToData`/`FromData` via `PlutusTx.unstableMakeIsData`:

```haskell
PlutusTx.unstableMakeIsData ''SharedWalletParam
```

In addition, when defining custom parameter types, we need to make them an instance of the [`Lift` class](https://intersectMBO.github.io/plutus/master/plutus-tx/html/PlutusTx.html#t:Lift). This allows the type to be lifted into so-called *Plutus IR* (intermediate representation), which is then handled further to Plutus Core, but essentially, we just need this to allow the compiler to compile our type to Plutus Core. This is done with the `PlutusTx.makeLift` function that automatically derives an instance for us:

```haskell
PlutusTx.makeLift ''SharedWalletParam
```

Note that `PubKeyHash` type is an instance of both `ToData`/`FromData` and `Lift`, but our defined type `SharedParam` which contains two `PubKeyHash` fields is not.

The rest is pretty much the same as in the [typed validator version](/typed-validators/a-shared-wallet-script). We need to create a `ValidatorTypes` instance, but since we are using a parameter that will bake our `sharedParam` inside the script, we do not need datum and redeemer:

```haskell
data SharedWalletParamValidator
instance Scripts.ValidatorTypes SharedWalletParamValidator
    -- default types for datum and redeemer are ()
```

Our `mkValidator` function still for valid signatures in the transaction context, except this time the `PubKeyHash`es are deconstructed from the `SharedParam` argument:

```haskell
{-# INLINEABLE mkValidator #-}
mkValidator :: SharedWalletParam -> () -> () -> Plutus.ScriptContext -> Bool
mkValidator swp () () ctx = checkSignature1 || checkSignature2
  where
    info :: Plutus.TxInfo
    info = Plutus.scriptContextTxInfo ctx

    signature1 :: PubKeyHash
    signature1 = wallet1 swp

    signature2 :: PubKeyHash
    signature2 = wallet2 swp

    checkSignature1 :: Bool
    checkSignature1 = traceIfFalse "signature 1 missing" $ txSignedBy info signature1

    checkSignature2 :: Bool
    checkSignature2 = traceIfFalse "signature 2 missing" $ txSignedBy info signature2
```

As with the [parameterised deadline script example](/parameterised-validators/a-deadline-script), we use the `PSU.V2.mkTypedValidatorParam` to define a function that accepts the parameter to compile the validator.

```haskell
typedValidator :: SharedWalletParam -> PSU.V2.TypedValidator SharedWalletParamValidator
typedValidator =
  PSU.V2.mkTypedValidatorParam @SharedWalletParamValidator
    $$(PlutusTx.compile [||mkValidator||])
    $$(PlutusTx.compile [||wrap||])
  where
    wrap = PSU.mkUntypedValidator

validator :: SharedWalletParam -> Plutus.Validator
validator = PSU.V2.validatorScript . typedValidator

script :: SharedWalletParam -> Plutus.Script
script = Plutus.unValidatorScript . validator
```

Besides the `DataKind` extension we enabled when working with typed validators, for parameterised validators we also need to enable `ScopedTypeVariables` and `MultiParamTypeClasses`.

```haskell
{-# LANGUAGE ScopedTypeVariables   #-}
{-# LANGUAGE MultiParamTypeClasses #-}
```

Finally, we define the functions to serialise and write the script file:

```haskell
sharedWalletParamShortBs :: SharedWalletParam -> SBS.ShortByteString
sharedWalletParamShortBs swp = SBS.toShort . LBS.toStrict $ serialise $ script swp

scriptSerialised :: SharedWalletParam -> PlutusScript PlutusScriptV2
scriptSerialised swp = PlutusScriptSerialised $ sharedWalletParamShortBs swp

writeSerialisedScript :: SharedWalletParam -> IO (Either (FileError ()) ())
writeSerialisedScript swp = writeFileTextEnvelope "compiled/SharedWalletParam.plutus" Nothing $ scriptSerialised swp
```

In order to compile this validator, we need to provide it with a parameter of type `SharedWalletParam`. Again, we can export this type and its constructor by adding it to the module interface.

```haskell
module SharedWalletParam
  (
    scriptSerialised,
    writeSerialisedScript,
    SharedWalletParam (..)
  )
where
...
```

Now, when we load the module in a REPL, we can construct a valid `SharedWalletParam` type. Let's do that by specifying the two public key hashes from our addresses as we did with the [typed version of the shared wallet validator](/typed-validators/a-shared-wallet-script). When we have our parameter for the script, we can pass it to the `writeSerialisedScript` function.

<pre class="language-haskell"><code class="lang-haskell"><strong>Prelude> :l SharedWalletParam 
</strong>[1 of 1] Compiling SharedWalletParam ( src/SharedWalletParam.hs, /home/plutus/hpm-plutus/hpm-validators/dist-newstyle/build/x86_64-linux/ghc-8.10.7/hpm-validators-0.1.0.0/build/SharedWalletParam.o )
Ok, one module loaded.
Prelude SharedWalletParam> :set -XOverloadedStrings
Prelude SharedWalletParam> myParam = SharedWalletParam "a5d318dadfb52eeffb260ae097f846aea0ca78e6cc4fe406d4ceedc0" "1b1e5895b03302b248e8c459817bab49471c4013a0806ac52cb73f9b"
Prelude SharedWalletParam> writeSerialisedScript myParam
Right ()
</code></pre>

### Testing the validator

As always, we start off by creating the script address in `testnet/SharedWalletParam/create-script-address.sh`.

```bash
#!/usr/bin/env bash

NWMAGIC=2 # preview testnet

# Build script address
cardano-cli address build \
--payment-script-file ../../compiled/SharedWalletParam.plutus \
--testnet-magic $NWMAGIC \
--out-file SharedWalletParam.addr

echo "Script address: $(cat SharedWalletParam.addr)"
```

```bash
./create-script-address.sh 
Script address: addr_test1wqjvw5a437sarsrexzezx04cl4rtxsd895cx4s3ncn7qg6gevx55f
```

Next, let's get an overview of the UTxOs with `check-utxos.sh`.

```bash
#!/usr/bin/env bash

NWMAGIC=2 # preview testnet
export CARDANO_NODE_SOCKET_PATH=$CNODE_HOME/sockets/node0.socket

funds_normal1=$(cardano-cli query utxo \
--address $(cat ../address/01.addr) \
--testnet-magic $NWMAGIC)

funds_normal2=$(cardano-cli query utxo \
--address $(cat ../address/02.addr) \
--testnet-magic $NWMAGIC)

funds_script=$(cardano-cli query utxo \
--address $(cat SharedWalletParam.addr) \
--testnet-magic $NWMAGIC)

echo "Normal address1:"
echo "${funds_normal1}"
echo ""

echo "Normal address2:"
echo "${funds_normal2}"
echo ""

echo "Script address:"
echo "${funds_script}"
```

```bash
./check-utxos.sh 
Normal address1:
                           TxHash                                 TxIx        Amount
--------------------------------------------------------------------------------------
5dc5111e257f8e68b0978c9619e57bbb12d365c0ec45d879115866bb674156ae     0        1826915 lovelace + TxOutDatumNone
6924903343947231af6c56a5d2d25b3256a513dee77e7966b6f8a47b09913188     2        9844804665 lovelace + TxOutDatumNone
ede24e9e40ca82830c75d827b5c3b090132c1afaebd3a4256655fb5d2382474a     0        9649776 lovelace + TxOutDatumNone
ee346be463426509daec07aba24a8905c5f55965daebb39f842a49191d83f9e1     0        1829006 lovelace + TxOutDatumNone

Normal address2:
                           TxHash                                 TxIx        Amount
--------------------------------------------------------------------------------------
59590fab00fb430d205151c59ca7e00af38e9945d778abdae6897f368aa39591     0        19682109 lovelace + TxOutDatumNone
667f81c9a89946d83f5975d9d97534df42be85a5a5aa1161b7af0ecb3d6592d0     0        19673177 lovelace + TxOutDatumNone

Script address:
                           TxHash                                 TxIx        Amount
--------------------------------------------------------------------------------------
```

We can now send some funds to the script. Remember, we don't care about the datum as the script was parameterised at compilation so it knows about our public key hashes. However, we always have to attach a datum to any script UTxO or it will be *unspendable*, so we can attach our `unit.json` in the transaction constructed by the `send-funds-to-script.sh` script.

```bash
#!/usr/bin/env bash

NWMAGIC=2 # preview testnet
export CARDANO_NODE_SOCKET_PATH=$CNODE_HOME/sockets/node0.socket

cardano-cli transaction build \
    --testnet-magic $NWMAGIC \
    --change-address $(cat ../address/01.addr) \
    --tx-in 6924903343947231af6c56a5d2d25b3256a513dee77e7966b6f8a47b09913188#2 \
    --tx-out $(cat SharedWalletParam.addr)+20000000 \
    --tx-out-datum-embed-file ../../compiled/assets/unit.json \
    --out-file tx.body

cardano-cli transaction sign \
    --tx-body-file tx.body \
    --signing-key-file ../address/01.skey \
    --testnet-magic $NWMAGIC \
    --out-file tx.signed

cardano-cli transaction submit \
    --testnet-magic $NWMAGIC \
    --tx-file tx.signed
```

```bash
./send-funds-to-script.sh 
Estimated transaction fee: Lovelace 169109
Transaction successfully submitted.

./check-utxos.sh 

...

Script address:
                           TxHash                                 TxIx        Amount
--------------------------------------------------------------------------------------
abe233c49d4162d886a0e38e2ed03739cc9feb0b5f38eb54d8417eb9821f039b     0        20000000 lovelace + TxOutDatumHash ScriptDataInBabbageEra "923918e403bf43c34b4ef6b48eb2ee04babed17320d8d1b9ff9ad086e86f44ec"
```

We see the UTxO at the script address so we can try spending it by simply signing the transaction with one of our private keys. Let's use the key from the `02.addr` and use one of its UTxOs for collateral as well in `spend-script-funds.sh`.

```bash
#!/usr/bin/env bash

NWMAGIC=2 # preview testnet
export CARDANO_NODE_SOCKET_PATH=$CNODE_HOME/sockets/node0.socket


cardano-cli transaction build \
    --testnet-magic $NWMAGIC \
    --change-address $(cat ../address/02.addr) \
    --tx-in abe233c49d4162d886a0e38e2ed03739cc9feb0b5f38eb54d8417eb9821f039b#0 \
    --tx-in-script-file ../../compiled/SharedWalletParam.plutus \
    --tx-in-datum-file ../../compiled/assets/unit.json \
    --tx-in-redeemer-file ../../compiled/assets/unit.json \
    --tx-in-collateral 667f81c9a89946d83f5975d9d97534df42be85a5a5aa1161b7af0ecb3d6592d0#0 \
    --required-signer-hash 1b1e5895b03302b248e8c459817bab49471c4013a0806ac52cb73f9b \
    --out-file tx.body

cardano-cli transaction sign \
    --tx-body-file tx.body \
    --signing-key-file ../address/02.skey \
    --testnet-magic $NWMAGIC \
    --out-file tx.signed

cardano-cli transaction submit \
    --testnet-magic $NWMAGIC \
    --tx-file tx.signed
```

And we can successfully spend the funds from the script using the `02.addr` signing key!

```bash
./spend-script-funds.sh 
Estimated transaction fee: Lovelace 315499
Transaction successfully submitted.
```


# Overview

In this section, we will look at validator scripts as they relate to staking on Cardano. The scripts we looked at so far were only related to the payment part of addresses, i.e. used for the `Spending` part of `ScriptPurpose`. We will now look at `StakeValidator`s which correspond to `Certifying` and `Rewarding` script purposes.

The `Rewarding` script purpose is related to validating reward withdrawals, i.e. whether a transaction is allowed to withdraw rewards from the script stake address.

The `Certifying` script purpose is related to validating certificates present in the transaction which control the registration and delegation of the script stake address, i.e. validating whether the transaction can register/de-register the given script stake address and whether it can delegate its funds to the specified stake pool.

### Cardano address structure

A Cardano base address (Shelley-based) is composed of two parts, the payment part (which controls spending associated UTxOs) and the *optional* staking part (which controls delegation-related actions). These two parts have separate keys (payment and stake keys), that are used to sign transactions to prove that they are valid. For example, if we want to register and delegate a stake address to a pool, we must submit a transaction that is signed by the address's stake key to validate it.

Now, with Plutus, the Shelley-based model of addresses remains the same, but we are no longer limited to controlling address validation with just the usual key pairs. Instead, we can create addresses that are composed of two scripts, the payment script (which are scripts that we have been writing so far), and the stake script (which is what we will be writing shortly). This way, we can have arbitrary logic of scripts take over both the payment and the stake part of addresses. We can also make all other possible permutations to build addresses. For example, we can use a payment script and a staking key to create an address that uses script logic to spend its UTxO, but the staking actions of the address are controlled by a staking key. Or we could make an address that uses a payment key and a stake validator. Beautiful.

To confirm this, check the `cardano-cli address build --help` command:

```bash
cardano-cli address build --help

    Build a Shelley payment address, with optional delegation to a stake address.

Available options:
  --payment-verification-key STRING
                           Payment verification key (Bech32-encoded)
  --payment-verification-key-file FILE
                           Filepath of the payment verification key.
  --payment-script-file FILE
                           Filepath of the payment script.
  --stake-verification-key STRING
                           Stake verification key (Bech32 or hex-encoded).
  --stake-verification-key-file FILE
                           Filepath of the staking verification key.
  --stake-script-file FILE Filepath of the staking script.
  --stake-address ADDRESS  Target stake address (bech32 format).
  --mainnet                Use the mainnet magic id. This overrides the
                           CARDANO_NODE_NETWORK_ID environment variable
  --testnet-magic NATURAL  Specify a testnet magic id. This overrides the
                           CARDANO_NODE_NETWORK_ID environment variable
  --out-file FILE          Optional output file. Default is to write to stdout.
  -h,--help                Show this help text
```

It gives the option to provide either the keys or a script file for both payment and stake parts (`--payment-script-file` / `--stake-script-file`).

### The *StakeValidator* type

[`StakeValidator`](https://intersectMBO.github.io/plutus-apps/main/plutus-ledger/html/Ledger-Typed-Scripts.html#t:UntypedStakeValidator) has a slightly different type signature than the regular validators because it does not accept `datum` as the first argument. That makes sense since the datum sits at the UTxO, and we are not dealing with spending UTxO here, only with validating staking actions. Therefore, it only receives the `redeemer` and `context` to return a boolean value:

`type UntypedStakeValidator = BuiltinData -> BuiltinData -> ()`

So when writing our `mkStakingValidator` function, we would use that type signature. Principles of [typed ](https://github.com/dostrelith678/hpm-education-plutus/blob/master/stake-validators/broken-reference/README.md)and [parameterised ](https://github.com/dostrelith678/hpm-education-plutus/blob/master/stake-validators/broken-reference/README.md)validators still apply here so we can write a function in this way: `mkStakingValidator :: MyParam -> MyRedeemer -> ScriptContext -> Bool`

Going back to the `Certifying` and `Rewarding` script purposes, we can see that they are constructed as `Rewarding StakingCredential` and `Certifying DCert`:

```haskell
data ScriptPurpose
    = Minting CurrencySymbol
    | Spending TxOutRef
    | Rewarding StakingCredential
    | Certifying DCert
```

If we dive into the [`Rewarding StakingCredential`](https://intersectMBO.github.io/plutus-apps/main/plutus-ledger-api/html/Plutus-V1-Ledger-Api.html#g:13), we will find the `StakingHash` constructor with the generic `Credential` type (the other is a pointer address, which we will not go into here, but here is a reference for those interested: <https://docs.cardano.org/learn/cardano-addresses>):

```haskell
data StakingCredential
    = StakingHash Credential
    | StakingPtr Integer Integer Integer
```

The `Credential` type is either a `PubKeyHash` or a `ValidatorHash` depending on whether it's a *normal* or *script* address:

```haskell
data Credential
  = PubKeyCredential PubKeyHash
  | ScriptCredential ValidatorHash
```

For [`Certifying DCert`](https://intersectMBO.github.io/plutus-apps/main/plutus-ledger-api/html/Plutus-V2-Ledger-Api.html#t:DCert), we dive into `DCert` definition:

<pre class="language-haskell"><code class="lang-haskell"><strong>data DCert
</strong>  = DCertDelegRegKey StakingCredential
  | DCertDelegDeRegKey StakingCredential
  | DCertDelegDelegate
      StakingCredential
      -- ^ delegator
      PubKeyHash
      -- ^ delegatee
  | -- | A digest of the PoolParams
    DCertPoolRegister
      PubKeyHash
      -- ^ poolId
      PubKeyHash
      -- ^ pool VFR
  | -- | The retiremant certificate and the Epoch N
    DCertPoolRetire PubKeyHash Integer -- NB: Should be Word64 but we only have Integer on-chain
  | -- | A really terse Digest
    DCertGenesis
  | -- | Another really terse Digest
    DCertMir
</code></pre>

This is the full definition of `DCert` and it contains fields not really related to delegation per se (`DCertGenesis` and `DCertMir`). We can also see certificates related to pool registration/de-registration which we are not interested in from the POV of `StakeValidator` (`DCertPoolRetire` and `DCertPoolRegister`). This leaves just the ones related to the delegation from the delegator's POV, which is the `StakeValidator` POV:

```haskell
data DCert
  = DCertDelegRegKey StakingCredential
  | DCertDelegDeRegKey StakingCredential
  | DCertDelegDelegate
      StakingCredential
      -- ^ delegator
      PubKeyHash
      -- ^ delegatee
```

`DCertDelegRegKey StakingCredential` is the certificate for registering a stake address. In our case, a script stake address where `StakingCredential` will correspond to our script's credential, i.e. the validator hash.

`DCertDelegDeRegKey StakingCredential` is the certificate for de-registering a stake address.

`DCertDelegDelegate StakingCredential PubKeyHash` is the certificate for delegating the `StakingCredential` to the pool with the specified `PubKeyHash`.


# A Stake Validator Script

In this `StakeValidator` example, we will create a simple script that controls staking actions via secret codes that the script is parameterised with.

### Writing the validator

First, we will use the same GHC extensions as with the [parameterised shared wallet script](/parameterised-validators/another-shared-wallet-script) and the same module imports (except we don't need `txSignedBy` here).

```haskell
{-# LANGUAGE NoImplicitPrelude     #-}
{-# LANGUAGE TemplateHaskell       #-}
{-# LANGUAGE OverloadedStrings     #-}
{-# LANGUAGE TypeApplications      #-}
{-# LANGUAGE TypeFamilies          #-}
{-# LANGUAGE ScopedTypeVariables   #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE DataKinds             #-}

module StakingValidator
  (
    scriptSerialised,
    writeSerialisedScript,
    CodeParam (..)
  )
where

import qualified PlutusTx
import PlutusTx.Prelude
import qualified Plutus.V2.Ledger.Api as Plutus

import Cardano.Api.Shelley (PlutusScript (PlutusScriptSerialised), PlutusScriptV2, writeFileTextEnvelope)
import Cardano.Api (FileError)

import qualified Data.ByteString.Lazy as LBS
import qualified Data.ByteString.Short as SBS
import Codec.Serialise

import qualified Ledger.Typed.Scripts as Scripts
import qualified Plutus.Script.Utils.V2.Typed.Scripts as PSU.V2
import qualified Plutus.Script.Utils.Typed as PSU

import Prelude (IO)

...

```

Then, we need to create a parameter for the script as before, calling it `CodeParam`, and making it an instance of `Data` and `Lift` classes.

```haskell
data CodeParam = CodeParam {
  cert :: Integer,
  reward :: Integer
}
PlutusTx.unstableMakeIsData ''CodeParam
PlutusTx.makeLift ''CodeParam
```

The `cert` field will contain an `Integer` code that must be specified in the redeemer for script certificates to be validated, and the `reward` code will have to be specified in order to withdraw rewards. We will be writing this as a typed validator so we need a `ValidatorTypes` instance as well:

```haskell
data CodeValidator
instance PSU.ValidatorTypes CodeValidator where
  type instance RedeemerType CodeValidator = Integer
  -- We only care about the redeemer type for the stake validator
```

We now have everything to create the `mkStakingValidator` function which will represent our stake validator logic:

```haskell
mkStakingValidator :: CodeParam -> Integer -> Plutus.ScriptContext -> Bool
mkStakingValidator cp redeemer ctx = 
  case Plutus.scriptContextPurpose ctx of
    Plutus.Certifying _   -> redeemer == cert cp
    Plutus.Rewarding  _   -> redeemer == reward cp
    _                     -> False
```

We simply need to check that the `redeemer` matches the corresponding action. Any script purpose other than `Certifying` or `Rewarding` will always be `False`.

Next, we need to compile that function into a `StakeValidator` type with the end goal of the `UntypedStakeValidator` that we looked at earlier. Since there is still no interface `TypedStakeValidator`, we have to use somewhat explicit code with `mkStakeValidatorScript` and [`mkUntypedStakeValidator`](https://intersectMBO.github.io/plutus-apps/main/plutus-script-utils/html/Plutus-Script-Utils-Typed.html#v:mkUntypedStakeValidator). This function is defined as:

```haskell
mkUntypedStakeValidator
    :: PV1.UnsafeFromData r
    => (r -> sc -> Bool)
    -> UntypedStakeValidator
mkUntypedStakeValidator f r p =
    check $ f (tracedUnsafeFrom "Redeemer decoded successfully" r)
              (tracedUnsafeFrom "Script context decoded successfully" p)
```

It receives a function `(r -> sc -> Bool)` and returns the `UntypedStakeValidator` which is the end result we want here. Since this is a parameterised contract, we have to apply our `CodeParam` to the `mkStakingValidator` function first in order to get just the `(Integer -> ScriptContext -> Bool)` function that is required here.

That is why we have to compose the two functions together and *apply* the `CodeParam`. However, since this is all being compiled to Plutus IR (intermediate Plutus Core), we also have to first *lift* the `CodeParam` value to Plutus IR for it to be applied.

We do this with `PlutusTx.liftCode cp`, and we are able to do it because we made `CodeParam` an instance of the `Lift` class. In the previous examples, this was abstracted for us via the `mkTypedValidatorParam` function, but since one is not available for stake validators (yet), we have to do it manually here:

```haskell
validator :: CodeParam -> PSU.V2.StakeValidator
validator cp = Plutus.mkStakeValidatorScript $
  $$(PlutusTx.compile [|| PSU.mkUntypedStakeValidator . mkStakingValidator ||])
  `PlutusTx.applyCode`
  PlutusTx.liftCode cp
```

The rest is the same as before, the only difference being that instead of `unValidatorScript`, we use `unStakeValidatorScript` to get the `Script` type of the validator:

```haskell
script :: CodeParam -> Plutus.Script
script = Plutus.unStakeValidatorScript . validator

scripShortBs :: CodeParam -> SBS.ShortByteString
scripShortBs cp = SBS.toShort . LBS.toStrict $ serialise $ script cp

scriptSerialised :: CodeParam -> PlutusScript PlutusScriptV2
scriptSerialised cp = PlutusScriptSerialised $ scripShortBs cp

writeSerialisedScript :: CodeParam -> IO (Either (FileError ()) ())
writeSerialisedScript cp = writeFileTextEnvelope "compiled/StakingValidator.plutus" Nothing $ scriptSerialised cp
```

All that is left to do is come up with a concrete instance of the `CodeParam` and pass it to the `writeSerialisedScript` function to compile the validator. For this example, we will just use the integers `1` and `2` as our secret codes. In the `cabal repl` of our `nix-shell`, we can do that with:

<pre class="language-bash"><code class="lang-bash"><strong>Prelude> :l src/StakingValidator.hs  
</strong>[1 of 1] Compiling StakingValidator ( src/StakingValidator.hs, /home/plutus/hpm-plutus/hpm-validators/dist-newstyle/build/x86_64-linux/ghc-8.10.7/hpm-validators-0.1.0.0/build/StakingValidator.o )
Ok, one module loaded.
Prelude StakingValidator> myCodeParam = CodeParam 1 2
Prelude StakingValidator> writeSerialisedScript myCodeParam 
Right ()
</code></pre>

### Testing the validator

To test a staking validator, we will need to slightly change our usual way of creating a script address with `create-script-address.sh`. So far we have only been using the payment credentials part to create an address, either a verification key or a validator script hash. Here, we want to add the optional staking credential part and use our stake validator script to provide the validation logic.

We can first use the `cardano-cli stake-address build` to get the stake address for this validator. When we do that, this address will be just a "Reward account address" (terminology from [Cardano docs](https://docs.cardano.org/learn/cardano-addresses/)), unable to receive any UTxO, but could be used as a rewards address for delegation.

As mentioned above, we usually want to combine payment and staking credentials into one address, so let's do that next. We will specify the `01.vkey` for the payment credential, and use our stake validator script to provide the staking credential. The full Bash script looks like this:

```bash
#!/usr/bin/env bash

NWMAGIC=2 # preview testnet


# Build script stake address
cardano-cli stake-address build \
  --testnet-magic ${NWMAGIC} \
  --stake-script-file ../../compiled/StakingValidator.plutus \
  --out-file StakingValidator.stake

echo "Script stake address: $(cat StakingValidator.stake)"

# Build address with 01.vkey for payment part and script stake part
cardano-cli address build \
  --payment-verification-key-file ../address/01.vkey \
  --stake-script-file ../../compiled/StakingValidator.plutus \
  --testnet-magic ${NWMAGIC} \
  --out-file StakingValidator.addr

echo "Full address: $(cat StakingValidator.addr)"
```

Running the script provides us with the two addresses, the first one being just the stake address and the second a fully combined address:

```bash
./create-script-address.sh
Script stake address: stake_test17peya46y0tymw8cq6hgdlzdlrys58acwsww4luzk0yur9vgy0xqrc
Full address: addr_test1yzjaxxx6m76jamlmyc9wp9lcg6h2pjncumxyleqx6n8wmsrjfmt5g7kfku0sp4wsm7ym7xfpg0msaquatlc9v7fcx2cs65ntf3
```

As usual, we need a way of checking the UTxO on our addresses, so we update the `check-utxos.sh` script for this `StakingValidator.addr` we just created.

```bash
#!/usr/bin/env bash

NWMAGIC=2 # preview testnet
export CARDANO_NODE_SOCKET_PATH=$CNODE_HOME/sockets/node0.socket

funds_normal1=$(cardano-cli query utxo \
--address $(cat ../normal_address/01.addr) \
--testnet-magic $NWMAGIC)


funds_script=$(cardano-cli query utxo \
--address $(cat codeParam.addr) \
--testnet-magic $NWMAGIC)

echo "Normal address1:"
echo "${funds_normal1}"
echo ""

echo "Script address:"
echo "${funds_script}"
```

We can now send some funds to the script with `send-funds-to-script.sh` that we will delegate to a pool.

```bash
#!/usr/bin/env bash

NWMAGIC=2 # preview testnet
export CARDANO_NODE_SOCKET_PATH=$CNODE_HOME/sockets/node0.socket

cardano-cli transaction build \
  --testnet-magic $NWMAGIC \
  --change-address $(cat ../address/01.addr) \
  --tx-in abe233c49d4162d886a0e38e2ed03739cc9feb0b5f38eb54d8417eb9821f039b#1 \
  --tx-out $(cat StakingValidator.addr)+200000000 \
  --tx-out-datum-embed-file ../../compiled/assets/unit.json \
  --out-file tx.body

cardano-cli transaction sign \
  --tx-body-file tx.body \
  --signing-key-file ../address/01.skey \
  --testnet-magic $NWMAGIC \
  --out-file tx.signed

cardano-cli transaction submit \
  --testnet-magic $NWMAGIC \
  --tx-file tx.signed
```

```bash
./send-funds-to-script.sh 
Estimated transaction fee: Lovelace 170341
Transaction successfully submitted.

./check-utxos.sh 
Normal address1:
                           TxHash                                 TxIx        Amount
--------------------------------------------------------------------------------------
5dc5111e257f8e68b0978c9619e57bbb12d365c0ec45d879115866bb674156ae     0        1826915 lovelace + TxOutDatumNone
9f24a56e249b86b3216cd337d9ada7fe3a030e339c97ab00191bc496b03132ed     1        9624465215 lovelace + TxOutDatumNone
ede24e9e40ca82830c75d827b5c3b090132c1afaebd3a4256655fb5d2382474a     0        9649776 lovelace + TxOutDatumNone
ee346be463426509daec07aba24a8905c5f55965daebb39f842a49191d83f9e1     0        1829006 lovelace + TxOutDatumNone

Script address:
                           TxHash                                 TxIx        Amount
--------------------------------------------------------------------------------------
9f24a56e249b86b3216cd337d9ada7fe3a030e339c97ab00191bc496b03132ed     0        200000000 lovelace + TxOutDatumHash ScriptDataInBabbageEra "923918e403bf43c34b4ef6b48eb2ee04babed17320d8d1b9ff9ad086e86f44ec"
```

It's time to finally register and delegate this address to a pool. Besides submitting the registration certificate, we also have to find a pool to delegate to. We can get a list of stake pools from `cardano-cli` with:

```bash
cardano-cli query stake-pools --testnet-magic 2
pool1q95luz38nhsw6h7mxud8tptc6mxvnsczhanw4j5htk8h2ltlf3k
pool1qxcz3zxnye8g9ejsqslhl0ljevdx895uc80lr89ulf92gcv40ng
pool1qncwwllw9nwtu7sl7zqw3fpyh4t3q6nhludryfwv0jyqjygd46d
pool1qal80uhlj949mgv0ecvdkmgqjdn5q27wmpaj4crnr5e9v6qmsv7
pool1p9xu88dzmpp5l8wmjd6f5xfs9z89mky6up86ty2wz4aavmm8f3m
pool1p835jxsj8py5n34lrgk6fvpgpxxvh585qm8dzvp7ups37vdet5a
...
```

We can use [preview.cardanoscan.io](https://preview.cardanoscan.io) to check pool information. Let's pick the second pool from the list [`pool1qxcz3zxnye8g9ejsqslhl0ljevdx895uc80lr89ulf92gcv40ng`](https://preview.cardanoscan.io/pool/01b02888d3264e82e650043f7fbff2cb1a63969cc1dff19cbcfa4aa4) because it is regularly creating blocks so we know we will get rewards. We can submit both the address registration and delegation certificate in the same transaction. Our validator defined two secret integer codes (we used `1` and `2`) that need to be specified as the redeemer for transactions, the first one required to validate certificates being submitted (registration, delegation, deregistration), and the second one for validating rewards withdrawals.

Let's create a `register-and-delegate-script.sh` script that will do that for us. We create the registration and delegation certificates and attach them to the `transaction build` command. Then we have to specify the `--certificate-script-file` argument since our certificates are validated by our script rather than regular keys. The script must receive a redeemer and since our redeemer is very simple (just the integer value `1`), we can use `--certificate-redeemer-value 1`. Besides that, we can specify the `--change-address $(cat StakingValidator.addr)` to send any remaining funds after the transaction fees are substracted to the staking address as well to be delegated.

```bash
#!/usr/bin/env bash

NWMAGIC=2 # preview testnet
export CARDANO_NODE_SOCKET_PATH=$CNODE_HOME/sockets/node0.socket

cardano-cli stake-address registration-certificate \
  --stake-script-file ../../compiled/StakingValidator.plutus \
  --out-file reg.cert

cardano-cli stake-address delegation-certificate \
  --stake-script-file ../../compiled/StakingValidator.plutus \
  --stake-pool-id pool1qxcz3zxnye8g9ejsqslhl0ljevdx895uc80lr89ulf92gcv40ng \
  --out-file deleg.cert

cardano-cli transaction build \
  --testnet-magic $NWMAGIC \
  --change-address $(cat StakingValidator.addr) \
  --tx-in 9f24a56e249b86b3216cd337d9ada7fe3a030e339c97ab00191bc496b03132ed#01 \
  --tx-in-collateral ee346be463426509daec07aba24a8905c5f55965daebb39f842a49191d83f9e1#0 \
  --certificate-file reg.cert \
  --certificate-file deleg.cert \
  --certificate-script-file ../../compiled/StakingValidator.plutus \
  --certificate-redeemer-value 1 \
  --out-file tx.body

cardano-cli transaction sign \
  --tx-body-file tx.body \
  --signing-key-file ../address/01.skey \
  --testnet-magic $NWMAGIC \
  --out-file tx.signed

cardano-cli transaction submit \
  --testnet-magic $NWMAGIC \
  --tx-file tx.signed
```

```bash
./register-and-delegate.sh 
Estimated transaction fee: Lovelace 313896
Transaction successfully submitted.
```

We can check [Cardanoscan](https://preview.cardanoscan.io/stakekey/f0724ed7447ac9b71f00d5d0df89bf192143f70e839d5ff056793832b1) again to look for our script address and see that the transaction did what was expected. It is now registered and delegated to the pool we specified.

You are free to try redelegating now by creating a new `delegation-certificate` with the wrong redeemer or an absent redeemer but our staking validator will invalidate the transaction.

We can create a `check-script-rewards.sh` next, but it will be empty for a few days until the first rewards start coming in (epochs are 1 day long on the Preview testnet).

```bash
#!/usr/bin/env bash

NWMAGIC=2 # preview testnet
export CARDANO_NODE_SOCKET_PATH=$CNODE_HOME/sockets/node0.socket

rewards_script=$(cardano-cli query stake-address-info \
--address $(cat StakingValidator.stake) \
--testnet-magic $NWMAGIC)

echo "Script address:"
echo "${rewards_script}"
```

```bash
./check-script-rewards.sh 
Script address:
[
    {
        "address": "stake_test17peya46y0tymw8cq6hgdlzdlrys58acwsww4luzk0yur9vgy0xqrc",
        "delegation": "pool1qxcz3zxnye8g9ejsqslhl0ljevdx895uc80lr89ulf92gcv40ng",
        "rewardAccountBalance": 0
    }
]
```

Once a few days have passed and we have some rewards, we can withdraw them with the correct redeemer code in our `withdraw-rewards.sh` script.

```bash
#!/usr/bin/env bash

NWMAGIC=2 # preview testnet
export CARDANO_NODE_SOCKET_PATH=$CNODE_HOME/sockets/node0.socket


rewards=$(cardano-cli query stake-address-info \
    --address $(cat StakingValidator.stake) \
    --testnet-magic $NWMAGIC | jq -r ".[0].rewardAccountBalance")

cardano-cli transaction build \
    --testnet-magic $NWMAGIC \
    --change-address $(cat StakingValidator.addr) \
    --tx-in cf72524e68d5884b2b1fb402494cf81de60aec6fbefd610af606adcddc7e4837#0 \
    --tx-in-collateral ee346be463426509daec07aba24a8905c5f55965daebb39f842a49191d83f9e1#0 \
    --withdrawal $(cat StakingValidator.stake)+${rewards} \
    --withdrawal-script-file ../../compiled/StakingValidator.plutus \
    --withdrawal-redeemer-value 2 \
    --out-file tx.body

cardano-cli transaction sign \
    --tx-body-file tx.body \
    --signing-key-file ../address/01.skey \
    --testnet-magic $NWMAGIC \
    --out-file tx.signed

cardano-cli transaction submit \
    --testnet-magic $NWMAGIC \
    --tx-file tx.signed
```

Actually, the pool we initially delegated `pool1qxcz3zxnye8g9ejsqslhl0ljevdx895uc80lr89ulf92gcv40ng` to is not producing blocks anymore so we need to redelegate to another pool. We can write a new `redelegate.sh` script for that.

```bash
#!/usr/bin/env bash

NWMAGIC=2 # preview testnet
export CARDANO_NODE_SOCKET_PATH=$CNODE_HOME/sockets/node0.socket

cardano-cli stake-address delegation-certificate \
  --stake-script-file ../../compiled/StakingValidator.plutus \
  --stake-pool-id pool1x9xkvkrfw6htmnflpad0z2aqsxx50f5mwkyzpylw0tlsk9z5uff \
  --out-file deleg.cert

cardano-cli transaction build \
  --testnet-magic $NWMAGIC \
  --change-address $(cat StakingValidator.addr) \
  --tx-in fbbf7a532ff30176087966c129f8fe44aa9e3462e4224e4fbfe3e162b1569ded#2 \
  --tx-in-collateral ee346be463426509daec07aba24a8905c5f55965daebb39f842a49191d83f9e1#0 \
  --certificate-file deleg.cert \
  --certificate-script-file ../../compiled/StakingValidator.plutus \
  --certificate-redeemer-value 1 \
  --out-file tx.body

cardano-cli transaction sign \
  --tx-body-file tx.body \
  --signing-key-file ../address/01.skey \
  --testnet-magic $NWMAGIC \
  --out-file tx.signed

cardano-cli transaction submit \
  --testnet-magic $NWMAGIC \
  --tx-file tx.signed
```

```bash
./redelegate.sh 
Estimated transaction fee: Lovelace 309296
Transaction successfully submitted.
```

After a couple of days and pool blocks produced, rewards will be available at the stake address we created with the validator.

<pre class="language-bash"><code class="lang-bash"><strong>./check-script-rewards.sh
</strong><strong>Script address:
</strong>[
    {
        "address": "stake_test17peya46y0tymw8cq6hgdlzdlrys58acwsww4luzk0yur9vgy0xqrc",
        "delegation": "pool1x9xkvkrfw6htmnflpad0z2aqsxx50f5mwkyzpylw0tlsk9z5uff",
        "rewardAccountBalance": 49443941
    }
]
</code></pre>


# Overview

Minting policies are very similar to `StakeValidator`s in the sense that they also do not receive the `datum` argument for validation, only the `redeemer` and `context`. This type of policy is used for the `Minting CurrencySymbol` script purpose. It returns a `()` representing a valid minting or burning transaction or throws an error if validation fails. But when using typed minting policy scripts, the function should return a boolean value.

As introduced in the [Introduction to the EUTxO model section](/the-eutxo-model/introduction-to-the-eutxo-model/the-eutxo-model-extended-utxo-model#custom-native-tokens-in-the-eutxo-model), tokens on Cardano are made up of the [`CurrencySymbol`](https://intersectMBO.github.io/plutus/master/plutus-ledger-api/html/PlutusLedgerApi-V2.html#t:CurrencySymbol) and the token name. One `CurrencySymbol` can hold an infinite number of [`TokenName`](https://intersectMBO.github.io/plutus/master/plutus-ledger-api/html/PlutusLedgerApi-V2.html#t:TokenName)s. Token names are generally hexified ByteStrings but have an ASCII representation as well. `CurrencySymbol` is the hash of the minting policy that controls token minting/burning.

Before Plutus, these policies were introduced in the Mary era and simple timelocking minting policies were already possible. Now with Plutus, we can control the minting policy with arbitrary logic instead of just key witnesses and timelocks. So `CurrencySymbol` is the hash of the minting policy, whether it's a Plutus policy script or a Mary-era style policy (`CurrencySymbol` is also referred to as the `policyID`).

To create minting policies with Plutus, we use the [`mkMintingPolicyScript`](https://intersectMBO.github.io/plutus-apps/main/plutus-ledger/html/Ledger.html#v:mkMintingPolicyScript) function, which accepts a function of `BuiltinData -> BuiltinData -> ()` of `CompiledCode` and returns a [`MintingPolicy`](https://intersectMBO.github.io/plutus/master/plutus-ledger-api/html/PlutusLedgerApi-V2.html#t:TokenName) - a wrapper around the [`Script`](https://intersectMBO.github.io/plutus-apps/main/plutus-ledger/html/Ledger.html#t:Script) type. The function of type `BuiltinData -> BuiltinData -> ()` represents the *untyped* version of the minting policy created with the [mkUntypedMintingPolicy](https://intersectmbo.github.io/plutus-apps/main/plutus-ledger/html/Ledger-Typed-Scripts.html#v:mkUntypedMintingPolicy) method.

```haskell
mkMintingPolicyScript :: 
    CompiledCode (BuiltinData -> BuiltinData -> ())
    -> MintingPolicy

mkUntypedMintingPolicy :: 
    UnsafeFromData r =>
        (r -> sc -> Bool) -> UntypedMintingPolicy
```

In the next section, we will write a pay-to-store minting policy script.

###


# A Pay-to-Store Policy

This script will be a [parameterised](/parameterised-validators/overview) minting policy script that allows the minting of tokens if a certain amount of ADA is paid to the store address as part of the minting transaction.

### Writing the validator

We can start by creating the `TokenSaleParams` that will consist of the store address, the token name, and the token price:

```haskell
data TokenSaleParams = TokenSaleParams
    {
        store :: PlutusV2.Address,   -- public address of the token store
        tName :: PlutusV2.TokenName, -- name of the token to be minted
        tPrice :: Integer            -- price in ADA per token
    } 
PlutusTx.unstableMakeIsData ''TokenSaleParams
PlutusTx.makeLift ''TokenSaleParams
```

The next part is writing the `mkPolicy` function that will represent our minting logic. We will need quite a bit of helper functions here. First, define the main behaviour of the function which is to use the `checkMint` function in order to determine whether minting is allowed and write a trace `Invalid mint` if it is not. Then, we start writing our helper functions for deconstructing `info` and `txOuts` from the transaction context.

```haskell
mkPolicy ::  TokenSaleParams -> BuiltinData -> PlutusV2.ScriptContext -> Bool
mkPolicy tsp _ ctx  =  traceIfFalse "Invalid mint" checkMint
    where
        info :: PlutusV2.TxInfo
        info = PlutusV2.scriptContextTxInfo ctx

        txOuts :: [PlutusV2.TxOut]
        txOuts = PlutusV2.txInfoOutputs info
```

We want a `checkMint` function that will look at the minting field of the transaction (`PlutusV2.txInfoMint info`) and validate only if there is **only one particular token being minted**, that token **matches our `CurrencySymbol` and `TokenName`** and **the amount minted is valid** for the amount of ADA being paid to the store address.&#x20;

We will call this last variable `canMintAmount` and it will simply divide (using integer division) the amount of ADA paid to the store (`storeTxOutAdaValue`) by the price of the token. Getting the `storeTxOutAdaValue` will be slightly complicated. First, we will need to look at all the UTxOs of the transactions that go to the store address via `storeTxOuts :: [PlutusV2.TxOut]`. That will give us a list of UTxOs that we then have to filter for their values `storeTxOutValue :: PlutusV2.Value` and then filter that for only the ADA (Lovelace) values and also sum them all together via `storeTxOutLovelaceValue :: Integer`. We then simply need to turn that into the corresponding ADA value by dividing it by a million.

```haskell
...
        checkMint :: Bool
        checkMint = case PlutusV1.flattenValue (Plutus.txInfoMint info) of
          [(cs', tn', amt)] -> tn' == tn && cs' == cs && amt == canMintAmount
          _               -> False

        cs :: Plutus.CurrencySymbol
        cs = ownCurrencySymbol ctx

        tn :: Plutus.TokenName
        tn = tName tsp
        
        canMintAmount :: Integer
        canMintAmount = storeTxOutAdaValue `divide` tPrice tsp
        
        storeTxOuts :: [Plutus.TxOut]
        storeTxOuts = filter (\x -> Plutus.txOutAddress x == store tsp) txOuts

        storeTxOutValue :: Plutus.Value
        storeTxOutValue = mconcat (fmap Plutus.txOutValue storeTxOuts)

        storeTxOutLovelaceValue :: Integer
        storeTxOutLovelaceValue = getLovelaceQuantity (PlutusV1.flattenValue storeTxOutValue)

        storeTxOutAdaValue :: Integer
        -- note must use PLutusTx DIVIDE instead of DIV
        storeTxOutAdaValue = storeTxOutLovelaceValue `divide` 1_000_000

        getLovelaceQuantity :: [(Plutus.CurrencySymbol, Plutus.TokenName, Integer)] -> Integer
        getLovelaceQuantity = foldr (\(ccs, _, qt) -> if ccs == Plutus.adaSymbol then (qt +) else (0 + )) 0

```

To use the underscore format for large numbers to make them more readable such as `1_000_000`, we have to activate the extension `{-# LANGUAGE NumericUnderscores #-}`.  Here is the full list of extensions and imports used for this validator for reference:

```haskell
{-# LANGUAGE NoImplicitPrelude     #-}
{-# LANGUAGE TemplateHaskell       #-}
{-# LANGUAGE OverloadedStrings     #-}
{-# LANGUAGE TypeApplications      #-}
{-# LANGUAGE TypeFamilies          #-}
{-# LANGUAGE ScopedTypeVariables   #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE DataKinds             #-}
{-# LANGUAGE NumericUnderscores  #-}

module MintingPolicy
  (
    scriptSerialised,
    writeSerialisedScript,
  )
where

import qualified PlutusTx
import PlutusTx.Prelude
import qualified Plutus.V2.Ledger.Api as Plutus

import Cardano.Api.Shelley (PlutusScript (PlutusScriptSerialised), PlutusScriptV2, writeFileTextEnvelope)
import Cardano.Api (FileError)

import qualified Data.ByteString.Lazy as LBS
import qualified Data.ByteString.Short as SBS
import Codec.Serialise

import qualified Ledger.Typed.Scripts as Scripts
import Plutus.Script.Utils.V2.Contexts (ownCurrencySymbol)

import qualified Plutus.V1.Ledger.Value as PlutusV1

import Prelude (IO)
```

Once our logic is complete, we need to apply our parameter to the function and create a `MintingPolicy` via `PlutusV2.mkMintingPolicyScript`. Since we are creating a parameterised script, we need to lift and apply our `tsp` parameter to our `mkPolicy` function as we did with our [`StakingValidator`](/stake-validators/a-stake-validator-script):

```haskell
policy :: TokenSaleParams -> Scripts.MintingPolicy
policy tsp = Plutus.mkMintingPolicyScript $
    $$(PlutusTx.compile [|| wrap ||])
    `PlutusTx.applyCode`
     PlutusTx.liftCode tsp
  where
    wrap tsp' = Scripts.mkUntypedMintingPolicy $ mkPolicy tsp'
```

To use this `MintingPolicy`, we need to serialise it as a script first. We can get the `Script` type via `unMintingPolicyScript`. We can create and apply the parameter here directly (using the `02.addr` as the store address):

```haskell
myTsp :: TokenSaleParams
myTsp = TokenSaleParams {
  store = Plutus.Address (Plutus.PubKeyCredential "1b1e5895b03302b248e8c459817bab49471c4013a0806ac52cb73f9b") Nothing,
  tName = "HPM",
  tPrice = 10
}

script :: Plutus.Script
script = Plutus.unMintingPolicyScript $ policy myTsp
```

And serialising the script as usual:

```haskell
scriptSBS :: SBS.ShortByteString
scriptSBS = SBS.toShort . LBS.toStrict $ serialise script

scriptSerialised :: PlutusScript PlutusScriptV2
scriptSerialised = PlutusScriptSerialised scriptSBS

writeSerialisedScript :: IO (Either (FileError ()) ())
writeSerialisedScript = writeFileTextEnvelope "compiled/MintingPolicy.plutus" Nothing scriptSerialised
```

Finally, we can load the module in `cabal repl` from our `nix-shell` and compile the minting policy.

```haskell
Prelude> :l src/MintingPolicy.hs
[1 of 1] Compiling MintingPolicy    ( src/MintingPolicy.hs, /home/plutus/hpm-plutus/hpm-validators/dist-newstyle/build/x86_64-linux/ghc-8.10.7/hpm-validators-0.1.0.0/build/MintingPolicy.o )
Ok, one module loaded.
Prelude MintingPolicy> writeSerialisedScript
Right ()
```

### Testing the validator

To create the transactions for testing, we need to first get the policy ID from the policy script. From a new directory under `testnet/MintingPolicy/` the command looks like this:

```bash
cardano-cli transaction policyid --script-file ../../compiled/MintingPolicy.plutus
a18972b3b83c9ff2f048380048cfdd28752f5c7430b75678065e3098
```

Also, `cardano-cli` accepts only hex token names, so before we can use it as an argument, we need to hexlify our token name via:

```bash
echo -n "HPM" | xxd -ps
48504d
```

Finally, to test this minting policy we can write our usual testing scripts. The `check-utxos.sh` scripts lists UTxOs available at `01.addr` (customer) and `02.addr` (store).

```bash
#!/usr/bin/env bash

NWMAGIC=2 # preview testnet
export CARDANO_NODE_SOCKET_PATH=$CNODE_HOME/sockets/node0.socket

customer=$(cardano-cli query utxo \
--address $(cat ../normal_address/01.addr) \
--testnet-magic $NWMAGIC)

store=$(cardano-cli query utxo \
--address $(cat ../normal_address/02.addr) \
--testnet-magic $NWMAGIC)

echo "Customer UTxOs:"
echo "${customer}"
echo ""

echo "Store UTxOs"
echo "${store}"
echo ""
```

```bash
./check-utxos.sh 
Customer UTxOs:
                           TxHash                                 TxIx        Amount
--------------------------------------------------------------------------------------
5dc5111e257f8e68b0978c9619e57bbb12d365c0ec45d879115866bb674156ae     0        1826915 lovelace + TxOutDatumNone
d20a1e9707e9fbd9adf606e9e9e168cfd9969431defc5869c4424f38673dddc5     0        10000000000 lovelace + TxOutDatumNone
ede24e9e40ca82830c75d827b5c3b090132c1afaebd3a4256655fb5d2382474a     0        9649776 lovelace + TxOutDatumNone
ee346be463426509daec07aba24a8905c5f55965daebb39f842a49191d83f9e1     0        1829006 lovelace + TxOutDatumNone

Store UTxOs
                           TxHash                                 TxIx        Amount
--------------------------------------------------------------------------------------
1bbb408f6cc96fd12de602539aa81989c3778d712132fa7a95de9f48ebf2e4ed     0        19684501 lovelace + TxOutDatumNone
59590fab00fb430d205151c59ca7e00af38e9945d778abdae6897f368aa39591     0        19682109 lovelace + TxOutDatumNone
667f81c9a89946d83f5975d9d97534df42be85a5a5aa1161b7af0ecb3d6592d0     0        19673177 lovelace + TxOutDatumNone
```

We can first test the minting policy by trying to mint an invalid number of tokens for the price. Let's say we want 10 tokens (price 100 ADA), but we only pay 90 ADA in our `mint-tokens-invalid.sh` script. To create minting transactions, we use the `--mint` argument which has the following syntax:

```bash
--mint VALUE             Mint multi-asset value(s) with the multi-asset cli
                           syntax. You must specify a script witness.

--mint "<TOKEN_QUANTITY> <TOKEN_POLICY_ID>.<TOKEN_NAME>"
```

```bash
#!/usr/bin/env bash

NWMAGIC=2 # preview testnet
export CARDANO_NODE_SOCKET_PATH=$CNODE_HOME/sockets/node0.socket

cardano-cli transaction build \
    --testnet-magic $NWMAGIC \
    --change-address $(cat ../address/01.addr) \
    --tx-in 0ecbdedf2f535c9931e4b36aa2b13fac93e9afa84d9b4797cc93ee24d42922fc#2 \
    --tx-in-collateral ee346be463426509daec07aba24a8905c5f55965daebb39f842a49191d83f9e1#0 \
    --tx-out $(cat ../address/02.addr)+90000000 \
    --mint "10 a18972b3b83c9ff2f048380048cfdd28752f5c7430b75678065e3098.48504d" \
    --mint-script-file ../../compiled/MintingPolicy.plutus \
    --mint-redeemer-value [] \
    --out-file tx.body
```

If we try running it, we get an `Invalid mint` error message that we defined in our validator:

```bash
./mint-tokens-invalid.sh 
Command failed: transaction build  Error: The following scripts have execution failures:
the script for policyId 0 (in ascending order of the PolicyIds) 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: Invalid mint
```

Now, let's try paying the right amount for the 10 tokens in `mint-tokens-valid.sh`.

```bash
#!/usr/bin/env bash

NWMAGIC=2 # preview testnet
export CARDANO_NODE_SOCKET_PATH=$CNODE_HOME/sockets/node0.socket

cardano-cli transaction build \
    --testnet-magic $NWMAGIC \
    --change-address $(cat ../address/01.addr) \
    --tx-in d20a1e9707e9fbd9adf606e9e9e168cfd9969431defc5869c4424f38673dddc5#0 \
    --tx-in-collateral ee346be463426509daec07aba24a8905c5f55965daebb39f842a49191d83f9e1#0 \
    --tx-out $(cat ../address/02.addr)+100000000 \
    --tx-out $(cat ../address/01.addr)+2000000+"10 a18972b3b83c9ff2f048380048cfdd28752f5c7430b75678065e3098.48504d" \
    --mint "10 a18972b3b83c9ff2f048380048cfdd28752f5c7430b75678065e3098.48504d" \
    --mint-script-file ../../compiled/MintingPolicy.plutus \
    --mint-redeemer-value [] \
    --out-file tx.body

cardano-cli transaction sign \
    --tx-body-file tx.body \
    --signing-key-file ../address/01.skey \
    --testnet-magic $NWMAGIC \
    --out-file tx.signed

cardano-cli transaction submit \
    --testnet-magic $NWMAGIC \
    --tx-file tx.signed
```

```bash
./mint-tokens-valid.sh 
Estimated transaction fee: Lovelace 387496
Transaction successfully submitted.
```

Checking the UTxO state after this transaction shows that the `Store` received the 100 ADA payment and the `Customer` received 10 minted tokens!

```bash
./check-utxos.sh 
Customer UTxOs:
                           TxHash                                 TxIx        Amount
--------------------------------------------------------------------------------------
5dc5111e257f8e68b0978c9619e57bbb12d365c0ec45d879115866bb674156ae     0        1826915 lovelace + TxOutDatumNone
ede24e9e40ca82830c75d827b5c3b090132c1afaebd3a4256655fb5d2382474a     0        9649776 lovelace + TxOutDatumNone
ee346be463426509daec07aba24a8905c5f55965daebb39f842a49191d83f9e1     0        1829006 lovelace + TxOutDatumNone
fbbf7a532ff30176087966c129f8fe44aa9e3462e4224e4fbfe3e162b1569ded     1        2000000 lovelace + 10 a18972b3b83c9ff2f048380048cfdd28752f5c7430b75678065e3098.48504d + TxOutDatumNone
fbbf7a532ff30176087966c129f8fe44aa9e3462e4224e4fbfe3e162b1569ded     2        9897612504 lovelace + TxOutDatumNone

Store UTxOs
                           TxHash                                 TxIx        Amount
--------------------------------------------------------------------------------------
1bbb408f6cc96fd12de602539aa81989c3778d712132fa7a95de9f48ebf2e4ed     0        19684501 lovelace + TxOutDatumNone
59590fab00fb430d205151c59ca7e00af38e9945d778abdae6897f368aa39591     0        19682109 lovelace + TxOutDatumNone
667f81c9a89946d83f5975d9d97534df42be85a5a5aa1161b7af0ecb3d6592d0     0        19673177 lovelace + TxOutDatumNone
fbbf7a532ff30176087966c129f8fe44aa9e3462e4224e4fbfe3e162b1569ded     0        100000000 lovelace + TxOutDatumNone
```


# Emulating the blockchain

So far, we have been using the `cardano-node` to submit transactions to the testnet in order to interact with our validators. While this is a valid way of investigating and testing behaviour, it can become tedious. Fortunately, we have another way of testing validators through *simulation* using the [`Plutus.Trace.Emulator` module](https://intersectMBO.github.io/plutus-apps/main/plutus-contract/html/Plutus-Trace-Emulator.html). This module can be used to create a temporary emulated blockchain for testing validators without the need for an actual live Cardano network (such as preview, preprod or mainnet).

The two main components for emulation are the `Contract` monad and the `EmulatorTrace` monad. The `Contract` monad represents the off-chain code, i.e. the code that builds and submits transactions for `cardano-node` to validate. The `EmulatorTrace` monad is a contract trace that can be run in the Plutus emulator and prints information about the emulated blockchain, its transactions and wallet/script balances.

We will first take a closer look at `EmulatorTrace`. We can run it without testing any validators just to see that an emulated blockchain is created. We can open a `cabal repl` from the `nix-shell` and import the `Plutus.Trace.Emulator` module:

```
ghci> import Plutus.Trace.Emulator
```

The function we generally want to use for emulation is `runEmulatorTraceIO` which gives us the most meaningful information printed to `stdout`. We can check its signature on [Haddock](https://intersectmbo.github.io/plutus-apps/main/plutus-contract/html/Plutus-Trace-Emulator.html#v:runEmulatorTraceIO).

`runEmulatorTraceIO :: EmulatorTrace () -> IO ()`.

It accepts an `EmulatorTrace ()` and returns an `IO ()`. So what is an [`EmulatorTrace`](https://intersectMBO.github.io/plutus-apps/main/plutus-contract/html/Plutus-Trace-Emulator.html#t:EmulatorTrace)? Well, it has a somewhat complex definition that we do not need to understand in detail:

```haskell
type EmulatorEffects = StartContract
                    ': BaseEmulatorEffects

type BaseEmulatorEffects =
             [ RunContract
             , Assert
             , Waiting
             , EmulatorControl
             , EmulatedWalletAPI
             , LogMsg String
             , Error EmulatorRuntimeError
             ]

type EmulatorTrace = Eff EmulatorEffects
```

It is enough to know that it is a monad containing everything required to emulate the blockchain.

Back to the `runEmulatorTraceIO` function - let's run it with the simple example from the docs `runEmulatorTraceIO (void $ waitNSlots 1)`. We will need to import the `void` function from `Data.Functor`:

```
ghci> import Data.Functor (void)
ghci> runEmulatorTraceIO (void $ waitNSlots 1)
Slot 00000: TxnValidate 43ba666cc8a22a04b63a3b605ce14146dfa5ed999986625ad90c1bc16dabdd84 []
Slot 00000: SlotAdd Slot 1
Slot 00001: W[7]: InsertionSuccess: New tip is Tip(Slot 1, BlockId 9e944371f5292bcd66e4e498bbc313b92ae884154f0eca1ddf75cd0ec69ddc47, BlockNumber 0). UTxO state was added to the end.
Slot 00001: W[8]: InsertionSuccess: New tip is Tip(Slot 1, BlockId 9e944371f5292bcd66e4e498bbc313b92ae884154f0eca1ddf75cd0ec69ddc47, BlockNumber 0). UTxO state was added to the end.
Slot 00001: W[6]: InsertionSuccess: New tip is Tip(Slot 1, BlockId 9e944371f5292bcd66e4e498bbc313b92ae884154f0eca1ddf75cd0ec69ddc47, BlockNumber 0). UTxO state was added to the end.
Slot 00001: W[4]: InsertionSuccess: New tip is Tip(Slot 1, BlockId 9e944371f5292bcd66e4e498bbc313b92ae884154f0eca1ddf75cd0ec69ddc47, BlockNumber 0). UTxO state was added to the end.
Slot 00001: W[2]: InsertionSuccess: New tip is Tip(Slot 1, BlockId 9e944371f5292bcd66e4e498bbc313b92ae884154f0eca1ddf75cd0ec69ddc47, BlockNumber 0). UTxO state was added to the end.
Slot 00001: W[1]: InsertionSuccess: New tip is Tip(Slot 1, BlockId 9e944371f5292bcd66e4e498bbc313b92ae884154f0eca1ddf75cd0ec69ddc47, BlockNumber 0). UTxO state was added to the end.
Slot 00001: W[10]: InsertionSuccess: New tip is Tip(Slot 1, BlockId 9e944371f5292bcd66e4e498bbc313b92ae884154f0eca1ddf75cd0ec69ddc47, BlockNumber 0). UTxO state was added to the end.
Slot 00001: W[9]: InsertionSuccess: New tip is Tip(Slot 1, BlockId 9e944371f5292bcd66e4e498bbc313b92ae884154f0eca1ddf75cd0ec69ddc47, BlockNumber 0). UTxO state was added to the end.
Slot 00001: W[3]: InsertionSuccess: New tip is Tip(Slot 1, BlockId 9e944371f5292bcd66e4e498bbc313b92ae884154f0eca1ddf75cd0ec69ddc47, BlockNumber 0). UTxO state was added to the end.
Slot 00001: W[5]: InsertionSuccess: New tip is Tip(Slot 1, BlockId 9e944371f5292bcd66e4e498bbc313b92ae884154f0eca1ddf75cd0ec69ddc47, BlockNumber 0). UTxO state was added to the end.
Slot 00001: SlotAdd Slot 2
Slot 00002: W[7]: InsertionSuccess: New tip is Tip(Slot 2, BlockId 76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71, BlockNumber 1). UTxO state was added to the end.
Slot 00002: W[8]: InsertionSuccess: New tip is Tip(Slot 2, BlockId 76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71, BlockNumber 1). UTxO state was added to the end.
Slot 00002: W[6]: InsertionSuccess: New tip is Tip(Slot 2, BlockId 76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71, BlockNumber 1). UTxO state was added to the end.
Slot 00002: W[4]: InsertionSuccess: New tip is Tip(Slot 2, BlockId 76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71, BlockNumber 1). UTxO state was added to the end.
Slot 00002: W[2]: InsertionSuccess: New tip is Tip(Slot 2, BlockId 76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71, BlockNumber 1). UTxO state was added to the end.
Slot 00002: W[1]: InsertionSuccess: New tip is Tip(Slot 2, BlockId 76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71, BlockNumber 1). UTxO state was added to the end.
Slot 00002: W[10]: InsertionSuccess: New tip is Tip(Slot 2, BlockId 76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71, BlockNumber 1). UTxO state was added to the end.
Slot 00002: W[9]: InsertionSuccess: New tip is Tip(Slot 2, BlockId 76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71, BlockNumber 1). UTxO state was added to the end.
Slot 00002: W[3]: InsertionSuccess: New tip is Tip(Slot 2, BlockId 76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71, BlockNumber 1). UTxO state was added to the end.
Slot 00002: W[5]: InsertionSuccess: New tip is Tip(Slot 2, BlockId 76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71, BlockNumber 1). UTxO state was added to the end.
Slot 00002: SlotAdd Slot 3
Slot 00003: W[7]: InsertionSuccess: New tip is Tip(Slot 3, BlockId 76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71, BlockNumber 2). UTxO state was added to the end.
Slot 00003: W[8]: InsertionSuccess: New tip is Tip(Slot 3, BlockId 76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71, BlockNumber 2). UTxO state was added to the end.
Slot 00003: W[6]: InsertionSuccess: New tip is Tip(Slot 3, BlockId 76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71, BlockNumber 2). UTxO state was added to the end.
Slot 00003: W[4]: InsertionSuccess: New tip is Tip(Slot 3, BlockId 76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71, BlockNumber 2). UTxO state was added to the end.
Slot 00003: W[2]: InsertionSuccess: New tip is Tip(Slot 3, BlockId 76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71, BlockNumber 2). UTxO state was added to the end.
Slot 00003: W[1]: InsertionSuccess: New tip is Tip(Slot 3, BlockId 76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71, BlockNumber 2). UTxO state was added to the end.
Slot 00003: W[10]: InsertionSuccess: New tip is Tip(Slot 3, BlockId 76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71, BlockNumber 2). UTxO state was added to the end.
Slot 00003: W[9]: InsertionSuccess: New tip is Tip(Slot 3, BlockId 76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71, BlockNumber 2). UTxO state was added to the end.
Slot 00003: W[3]: InsertionSuccess: New tip is Tip(Slot 3, BlockId 76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71, BlockNumber 2). UTxO state was added to the end.
Slot 00003: W[5]: InsertionSuccess: New tip is Tip(Slot 3, BlockId 76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71, BlockNumber 2). UTxO state was added to the end.
Final balances
Wallet 7: 
    {, ""}: 100000000
Wallet 8: 
    {, ""}: 100000000
Wallet 6: 
    {, ""}: 100000000
Wallet 4: 
    {, ""}: 100000000
Wallet 2: 
    {, ""}: 100000000
Wallet 1: 
    {, ""}: 100000000
Wallet 10: 
    {, ""}: 100000000
Wallet 9: 
    {, ""}: 100000000
Wallet 3: 
    {, ""}: 100000000
Wallet 5: 
    {, ""}: 100000000
```

Okay, we got an emulated blockchain! The only transaction we can see is the initial one `Slot 00000: TxnValidate 43ba666cc8a22a04b63a3b605ce14146dfa5ed999986625ad90c1bc16dabdd84 []`. This transaction created the initial wallet distribution. By default, this is ten wallets with 100 ADA each, as shown in the logs. The balances at the end of the simulation are unchanged since we did not do any transactions after the initial one.

We can also see that the log messages regarding new blocks are duplicated for each of the wallets: `Slot 00001: W[1]: InsertionSuccess: New tip is Tip(Slot 1, BlockId 9e944371f5292bcd66e4e498bbc313b92ae884154f0eca1ddf75cd0ec69ddc47, BlockNumber 0). UTxO state was added to the end.`.

An advanced question would be how to configure the emulation differently, for example, with a different initial ADA distribution or with a different trace format. The defaults will do just fine for examples in this course, but for those interested, there is another function [`runEmulatorTraceIO'`](https://intersectMBO.github.io/plutus-apps/main/plutus-contract/html/Plutus-Trace-Emulator.html#v:runEmulatorTraceIO-39-) which accepts additional configurations that can be customised:`runEmulatorTraceIO' :: TraceConfig -> EmulatorConfig -> EmulatorTrace () -> IO ()`

If you are interested, you can dive down into the definitions of [`TraceConfig`](https://intersectMBO.github.io/plutus-apps/main/plutus-contract/html/Plutus-Trace-Emulator.html#t:TraceConfig) and [`EmulatorConfig`](https://intersectMBO.github.io/plutus-apps/main/plutus-contract/html/Plutus-Trace-Emulator.html#t:EmulatorConfig).


# Testing a validator with the emulator

Now, we will test a validator that we created earlier with the Plutus emulator. We will use the `GuessingGame.hs` validator to define two emulator traces, one for a valid script spend and one for an invalid script spend. We will edit the `GuessingGame.hs` file directly, adding the new tracing functions. As part of this exercise, we will also learn about the `Contract` monad, which we will use to create and submit transactions in the emulation.

### Writing the emulator trace

Since `EmulatorTrace` is a monad, we will use [do-notation](https://haskell.hpmeducation.com/interactive-programming/sequencing-actions) to define its actions. In general, what we want to do is have a contract function that describes the sequence of transactions that will be generated and submitted. We then call the [`activateContractWallet`](https://intersectMBO.github.io/plutus-apps/main/plutus-contract/html/Plutus-Trace-Emulator.html#v:activateContractWallet) function with a wallet (we can use `knownWallet 1` - corresponding to the first of the 10 default wallets in the emulator) and the contract:

```haskell
emulatorTrace :: EmulatorTrace ()
emulatorTrace = do
    void Prelude.$ activateContractWallet (knownWallet 1) contract
    void Prelude.$ Emulator.waitNSlots 2
```

We can also define a helper function for running the trace:

```haskell
runTrace :: IO ()
runTrace = runEmulatorTraceIO emulatorTrace
```

### Writing the contract

To run a meaningful `EmulatorTrace`, we have to define a contract that can be used for emulation. The contract type is [`Contract w s e a`](https://intersectMBO.github.io/plutus-apps/main/plutus-contract/html/Plutus-Contract.html#t:Contract):

* `w` is the *state* type of the contract. The state can be updated from inside the contract and is generally used for communication between contract instances. It should not be confused with general logging which is always available through the `Contract.logInfo` function.
* `s` stands for *schema*, a list of endpoints available to the contract
* `e` is the type of error that will be generated if an exception is thrown
* `a` is the type of the final value the contract produces if no exception is thrown

For simple examples, such as ours, we do not need to use a contract state, an endpoint schema, or produce a final value. Therefore, a simple type signature for our contract for the `GuessingGame` validator will be:

`contract :: Contract () Empty Text ()`

`Empty` for `s` means no endpoints are available, and we just use `Text` to log error messages. Since `Contract` is a monad, we can use do-notation again. We can start off with some logging:

<pre class="language-haskell"><code class="lang-haskell"><strong>contract :: Contract () Empty Text ()
</strong>contract = do
    now &#x3C;- currentNodeClientTimeRange
    Contract.logInfo @String $ "Logging from inside the contract, contract time is: " ++ show now
    Contract.logInfo @String $ "First transaction: send funds to script and set a datum to be guessed"

</code></pre>

{% hint style="warning" %}
The `@String` syntax requires the `TypeApplications` GHC extension to be activated.
{% endhint %}

Okay, now we need to create the first transaction. This is done by using the [`Ledger.Tx.Constraints`](https://intersectMBO.github.io/plutus-apps/main/plutus-tx-constraints/html/Ledger-Tx-Constraints.html) module.

{% hint style="info" %}
The more [recent release of `plutus-apps`](https://github.com/intersectMBO/plutus-apps/releases/tag/v1.2.0) has the following change:

* `plutus-ledger-constraints` was replaced with `plutus-tx-constraints`.

Since we are using an older commit, we still use the old import:

```haskell
import Ledger.Constraints as Constraints
```

{% endhint %}

We define the constraints of the transaction, i.e. what we want it to do, and the contract constructs a valid transaction based on its constraints. We want the first transaction to send some ADA to the script address along with a datum that will need to be guessed to spend it later, so we use the [`mustPayToOtherScriptWithDatumInTx`](https://intersectMBO.github.io/plutus-apps/main/plutus-tx-constraints/html/Ledger-Tx-Constraints.html#v:mustPayToOtherScriptWithDatumInTx) function. After we submit the transaction we use [`awaitTxConfirmed`](https://intersectMBO.github.io/plutus-apps/main/plutus-contract/html/Plutus-Contract.html#v:awaitTxConfirmed) to make sure the transaction is accounted for on the emulated chain.

```haskell
...
    let tx1 = Constraints.mustPayToOtherScriptWithDatumInTx valHash unitDatum $ Ada.lovelaceValueOf 25000000
    ledgerTx1 <- submitTx tx1
    awaitTxConfirmed $ getCardanoTxId ledgerTx1
    Contract.logInfo @String $ "tx1 successfully submitted"
```

Next, we want to try to spend the newly generated script UTxO by matching the datum with the redeemer. This is a bit more tricky because we have to tell the contract where to find the UTxO via `lookups`. In this case, we are spending a script output, so the lookup must know the validator behind the script address (as we have seen before with `cardano-cli`, to construct a valid transaction spending the script output, we must supply the validator). To make it a bit clearer, we will add a logging line to inspect the `utxos` and `lookups` in the contract and inspect it later.

First, we have to get the UTxO(s) at the script address with `utxosAt scriptAddress`. We create two helper functions for referencing the script address and the validator hash:

```haskell
scriptAddress  :: Ledger.Address
scriptAddress  = Ledger.scriptHashAddress valHash

valHash :: PSU.V2.ValidatorHash
valHash = PSU.V2.validatorHash validator
```

Note that this will get all the UTxOs and for simplicity (since we know there will always be only one), we can take just one with the `head` function. The `lookups` we need for this transaction are the `validator` itself, which we define with [`Constraints.plutusV2OtherScript`](https://intersectMBO.github.io/plutus-apps/main/plutus-tx-constraints/html/Ledger-Tx-Constraints.html#v:plutusV2OtherScript) and the UTxO(s) that are sitting at the script address that we can get with [`Constraints.unspentOutputs`](https://intersectMBO.github.io/plutus-apps/main/plutus-tx-constraints/html/Ledger-Tx-Constraints.html#v:unspentOutputs). We join these two monoidal values together with `<>` (`mappend`):

<pre class="language-haskell"><code class="lang-haskell"><strong>...
</strong>    Contract.logInfo @String $ "Second transaction: spend script output with the right redeemer"
    utxos &#x3C;- utxosAt scriptAddress
    let oref = head (fst &#x3C;$> Map.toList utxos)
        lookups =
            Constraints.plutusV2OtherScript validator
              &#x3C;> Constraints.unspentOutputs utxos
</code></pre>

Now, we just need to construct the transaction with the correct redeemer that matches the datum (in our case just the `unitRedeemer`). We use the [`Constraints.mustSpendScriptOutput`](https://intersectMBO.github.io/plutus-apps/main/plutus-tx-constraints/html/Ledger-Tx-Constraints.html#v:mustSpendScriptOutput) function and specify the output reference that we defined `oref` along with the `unitRedeemer`. We also must include the `unitDatum` in the transaction via [`Constraints.mustIncludeDatumInTx`](https://intersectMBO.github.io/plutus-apps/main/plutus-tx-constraints/html/Ledger-Tx-Constraints.html#v:mustIncludeDatumInTx):

<pre class="language-haskell"><code class="lang-haskell"><strong>...
</strong>        tx2 =
            Constraints.mustSpendScriptOutput oref unitRedeemer
              &#x3C;> Constraints.mustIncludeDatumInTx unitDatum
</code></pre>

The final part is simply submitting the transaction with our given constraints. We use [`submitTxConstraintsWith`](https://intersectMBO.github.io/plutus-apps/main/plutus-contract/html/Plutus-Contract.html#v:submitTxConstraintsWith) and `awaitTxConfirmed`. Before we do, we can log the `oref` and `lookups` as mentioned before:

```haskell
...
    Contract.logInfo @String $ "Oref: " ++ show oref ++ ", Lookups: " ++ show lookups
    ledgerTx2 <- submitTxConstraintsWith @Void lookups tx2
    Contract.logInfo @String $ "waiting for tx2 confirmed..."
    awaitTxConfirmed $ getCardanoTxId ledgerTx2
    Contract.logInfo @String $ "tx2 successfully submitted"
```

There are a lot of different imports that we need to take care of for all of the above code to work, so below is a full reference of the imports. We have to import some extra modules from the standard `Prelude`, most importantly `Semigroup` as there seems to be some issue when using the emulator with the `PlutuxTx` version of `Semigroup`. We also need to hide the module from the `PlutusTx.Prelude`.

```haskell
import PlutusTx.Prelude hiding (Semigroup (..))
import Prelude (IO, String, show, Semigroup (..))

import qualified Plutus.Script.Utils.V2.Scripts as PSU.V2
import Ledger
  (
    getCardanoTxId,
    unitDatum,
    unitRedeemer,
    scriptHashAddress,
    Address
  )
import Ledger.Ada as Ada
import Data.Map as Map
import Data.Functor (void)
import Data.Text (Text)
import Data.Void (Void)
import Wallet.Emulator.Wallet (knownWallet)
import Plutus.Contract as Contract
import Ledger.Constraints as Constraints
import Plutus.Trace.Emulator as Emulator
  ( EmulatorTrace,
    activateContractWallet,
    runEmulatorTraceIO,
    waitNSlots,
  )
```

The entire emulator code all together looks like this:

```haskell
scriptAddress  :: Ledger.Address
scriptAddress  = Ledger.scriptHashAddress valHash

valHash :: PSU.V2.ValidatorHash
valHash = PSU.V2.validatorHash validator

contract :: Contract () Empty Text ()
contract = do
    now <- currentNodeClientTimeRange
    Contract.logInfo @String $ "Logging from inside the contract, contract time is: " ++ show now
    Contract.logInfo @String $ "First transaction: send funds to script and set a datum to be guessed"
    let tx1 = Constraints.mustPayToOtherScriptWithDatumInTx valHash unitDatum $ Ada.lovelaceValueOf 25000000
    ledgerTx1 <- submitTx tx1
    awaitTxConfirmed $ getCardanoTxId ledgerTx1
    Contract.logInfo @String $ "tx1 successfully submitted"
    Contract.logInfo @String $ "Second transaction: spend script output with the right redeemer"
    utxos <- utxosAt scriptAddress
    let oref = head (fst <$> Map.toList utxos)
        lookups =
            Constraints.plutusV2OtherScript validator
              <> Constraints.unspentOutputs utxos
        tx2 =
            Constraints.mustSpendScriptOutput oref unitRedeemer
              <> Constraints.mustIncludeDatumInTx unitDatum
    Contract.logInfo @String $ "Oref: " ++ show oref ++ ", Lookups: " ++ show lookups
    ledgerTx2 <- submitTxConstraintsWith @Void lookups tx2
    Contract.logInfo @String $ "waiting for tx2 confirmed..."
    awaitTxConfirmed $ getCardanoTxId ledgerTx2
    Contract.logInfo @String $ "tx2 successfully submitted"

emulatorTrace :: EmulatorTrace ()
emulatorTrace = do
    void $ activateContractWallet (knownWallet 1) contract
    void $ Emulator.waitNSlots 2

runTrace :: IO ()
runTrace = runEmulatorTraceIO emulatorTrace
```

We also need to add the `runTrace` function to the module export list:

```haskell
module GuessingGame
  (
    scriptSerialised,
    writeSerialisedScript,
    runTrace
  )
where ...
```

### Running the emulator

Finally, we can load the module and run the trace:

```
ghci> :l src/GuessingGame.hs
ghci GuessingGame> runTrace
 
Slot 00000: TxnValidate 43ba666cc8a22a04b63a3b605ce14146dfa5ed999986625ad90c1bc16dabdd84 []
Slot 00000: SlotAdd Slot 1
Slot 00001: W[7]: InsertionSuccess: New tip is Tip(Slot 1, BlockId 9e944371f5292bcd66e4e498bbc313b92ae884154f0eca1ddf75cd0ec69ddc47, BlockNumber 0). UTxO state was added to the end.
Slot 00001: W[8]: InsertionSuccess: New tip is Tip(Slot 1, BlockId 9e944371f5292bcd66e4e498bbc313b92ae884154f0eca1ddf75cd0ec69ddc47, BlockNumber 0). UTxO state was added to the end.
Slot 00001: W[6]: InsertionSuccess: New tip is Tip(Slot 1, BlockId 9e944371f5292bcd66e4e498bbc313b92ae884154f0eca1ddf75cd0ec69ddc47, BlockNumber 0). UTxO state was added to the end.
Slot 00001: W[4]: InsertionSuccess: New tip is Tip(Slot 1, BlockId 9e944371f5292bcd66e4e498bbc313b92ae884154f0eca1ddf75cd0ec69ddc47, BlockNumber 0). UTxO state was added to the end.
Slot 00001: W[2]: InsertionSuccess: New tip is Tip(Slot 1, BlockId 9e944371f5292bcd66e4e498bbc313b92ae884154f0eca1ddf75cd0ec69ddc47, BlockNumber 0). UTxO state was added to the end.
Slot 00001: W[1]: InsertionSuccess: New tip is Tip(Slot 1, BlockId 9e944371f5292bcd66e4e498bbc313b92ae884154f0eca1ddf75cd0ec69ddc47, BlockNumber 0). UTxO state was added to the end.
Slot 00001: W[10]: InsertionSuccess: New tip is Tip(Slot 1, BlockId 9e944371f5292bcd66e4e498bbc313b92ae884154f0eca1ddf75cd0ec69ddc47, BlockNumber 0). UTxO state was added to the end.
Slot 00001: W[9]: InsertionSuccess: New tip is Tip(Slot 1, BlockId 9e944371f5292bcd66e4e498bbc313b92ae884154f0eca1ddf75cd0ec69ddc47, BlockNumber 0). UTxO state was added to the end.
Slot 00001: W[3]: InsertionSuccess: New tip is Tip(Slot 1, BlockId 9e944371f5292bcd66e4e498bbc313b92ae884154f0eca1ddf75cd0ec69ddc47, BlockNumber 0). UTxO state was added to the end.
Slot 00001: W[5]: InsertionSuccess: New tip is Tip(Slot 1, BlockId 9e944371f5292bcd66e4e498bbc313b92ae884154f0eca1ddf75cd0ec69ddc47, BlockNumber 0). UTxO state was added to the end.
Slot 00001: 00000000-0000-4000-8000-000000000000 {Wallet W[1]}:
  Contract instance started
Slot 00001: *** CONTRACT LOG: "Logging from inside the contract, contract time is: (POSIXTime {getPOSIXTime = 1596059092000},POSIXTime {getPOSIXTime = 1596059092999})"
Slot 00001: *** CONTRACT LOG: "First transaction: send funds to script and set a datum to be guessed"
Slot 00001: 00000000-0000-4000-8000-000000000000 {Wallet W[1]}:
  Contract log: Object (fromList [("mkTxLogLookups",Object (fromList [("slOtherData",Array []),("slOtherScripts",Array []),("slOwnPaymentPubKeyHash",Null),("slOwnStakingCredential",Null),("slPaymentPubKeyHashes",Array []),("slTxOutputs",Array []),("slTypedValidator",Null)])),("mkTxLogResult",Object (fromList [("Right",Object (fromList [("tag",String "UnbalancedEmulatorTx"),("unBalancedEmulatorTx",Object (fromList [("txCertificates",Array []),("txCollateralInputs",Array []),("txData",Array [Array [String "923918e403bf43c34b4ef6b48eb2ee04babed17320d8d1b9ff9ad086e86f44ec",Object (fromList [("getDatum",String "d87980")])]]),("txFee",Object (fromList [("getValue",Array [])])),("txInputs",Array []),("txMetadata",Null),("txMint",Object (fromList [("getValue",Array [])])),("txMintingWitnesses",Array []),("txOutputs",Array [Object (fromList [("getTxOut",Object (fromList [("address",String "addr_test1wz3r0qhn7u38h7scq2k65vewg9fr6ztrnet904l3e4aft0chgqzep"),("datum",Object (fromList [("constructor",Number 0.0),("fields",Array [])])),("datumhash",String "923918e403bf43c34b4ef6b48eb2ee04babed17320d8d1b9ff9ad086e86f44ec"),("inlineDatum",Null),("referenceScript",Null),("value",Object (fromList [("lovelace",Number 2.5e7)]))]))])]),("txReferenceInputs",Array []),("txReturnCollateral",Null),("txScripts",Array []),("txSignatures",Array []),("txTotalCollateral",Null),("txValidRange",Object (fromList [("ivFrom",Array [Object (fromList [("tag",String "NegInf")]),Bool True]),("ivTo",Array [Object (fromList [("tag",String "PosInf")]),Bool True])])),("txWithdrawals",Array [])])),("unBalancedTxRequiredSignatories",Array []),("unBalancedTxUtxoIndex",Array [])]))])),("mkTxLogTxConstraints",Object (fromList [("txConstraintFuns",Array []),("txConstraints",Array [Object (fromList [("contents",Array [Object (fromList [("addressCredential",Object (fromList [("contents",String "a23782f3f7227bfa1802adaa332e41523d09639e5657d7f1cd7a95bf"),("tag",String "ScriptCredential")])),("addressStakingCredential",Null)]),Object (fromList [("contents",Object (fromList [("getDatum",String "d87980")])),("tag",String "TxOutDatumInTx")]),Null,Object (fromList [("getValue",Array [Array [Object (fromList [("unCurrencySymbol",String "")]),Array [Array [Object (fromList [("unTokenName",String "")]),Number 2.5e7]]]])])]),("tag",String "MustPayToAddress")])]),("txOwnInputs",Array []),("txOwnOutputs",Array [])]))])
Slot 00001: W[1]: TxSubmit: ac35b5e8f3649d55ae589a19e26a0413e6e8fd8911fcbf7371c4174fbb6c599c
Slot 00001: TxnValidate ac35b5e8f3649d55ae589a19e26a0413e6e8fd8911fcbf7371c4174fbb6c599c []
Slot 00001: SlotAdd Slot 2
Slot 00002: W[7]: InsertionSuccess: New tip is Tip(Slot 2, BlockId ce08edfdc283bf3735f357e13a7cabf68923867717483467cf38b87997732b3b, BlockNumber 1). UTxO state was added to the end.
Slot 00002: W[8]: InsertionSuccess: New tip is Tip(Slot 2, BlockId ce08edfdc283bf3735f357e13a7cabf68923867717483467cf38b87997732b3b, BlockNumber 1). UTxO state was added to the end.
Slot 00002: W[6]: InsertionSuccess: New tip is Tip(Slot 2, BlockId ce08edfdc283bf3735f357e13a7cabf68923867717483467cf38b87997732b3b, BlockNumber 1). UTxO state was added to the end.
Slot 00002: W[4]: InsertionSuccess: New tip is Tip(Slot 2, BlockId ce08edfdc283bf3735f357e13a7cabf68923867717483467cf38b87997732b3b, BlockNumber 1). UTxO state was added to the end.
Slot 00002: W[2]: InsertionSuccess: New tip is Tip(Slot 2, BlockId ce08edfdc283bf3735f357e13a7cabf68923867717483467cf38b87997732b3b, BlockNumber 1). UTxO state was added to the end.
Slot 00002: W[1]: InsertionSuccess: New tip is Tip(Slot 2, BlockId ce08edfdc283bf3735f357e13a7cabf68923867717483467cf38b87997732b3b, BlockNumber 1). UTxO state was added to the end.
Slot 00002: W[10]: InsertionSuccess: New tip is Tip(Slot 2, BlockId ce08edfdc283bf3735f357e13a7cabf68923867717483467cf38b87997732b3b, BlockNumber 1). UTxO state was added to the end.
Slot 00002: W[9]: InsertionSuccess: New tip is Tip(Slot 2, BlockId ce08edfdc283bf3735f357e13a7cabf68923867717483467cf38b87997732b3b, BlockNumber 1). UTxO state was added to the end.
Slot 00002: W[3]: InsertionSuccess: New tip is Tip(Slot 2, BlockId ce08edfdc283bf3735f357e13a7cabf68923867717483467cf38b87997732b3b, BlockNumber 1). UTxO state was added to the end.
Slot 00002: W[5]: InsertionSuccess: New tip is Tip(Slot 2, BlockId ce08edfdc283bf3735f357e13a7cabf68923867717483467cf38b87997732b3b, BlockNumber 1). UTxO state was added to the end.
Slot 00002: *** CONTRACT LOG: "tx1 successfully submitted"
Slot 00002: *** CONTRACT LOG: "Second transaction: spend script output with the right redeemer"
Slot 00002: *** CONTRACT LOG: "Oref: TxOutRef {txOutRefId = ac35b5e8f3649d55ae589a19e26a0413e6e8fd8911fcbf7371c4174fbb6c599c, txOutRefIdx = 0}, Lookups: ScriptLookups {slTxOutputs = fromList [(TxOutRef {txOutRefId = ac35b5e8f3649d55ae589a19e26a0413e6e8fd8911fcbf7371c4174fbb6c599c, txOutRefIdx = 0},ScriptDecoratedTxOut {_decoratedTxOutValidatorHash = a23782f3f7227bfa1802adaa332e41523d09639e5657d7f1cd7a95bf, _decoratedTxOutStakingCredential = Nothing, _decoratedTxOutValue = Value (Map [(,Map [(\"\",25000000)])]), _decoratedTxOutScriptDatum = (923918e403bf43c34b4ef6b48eb2ee04babed17320d8d1b9ff9ad086e86f44ec,DatumInBody (Datum {getDatum = Constr 0 []})), _decoratedTxOutReferenceScript = Nothing, _decoratedTxOutValidator = Nothing})], slOtherScripts = fromList [(a23782f3f7227bfa1802adaa332e41523d09639e5657d7f1cd7a95bf,Versioned {unversioned = <Script>, version = PlutusV2})], slOtherData = fromList [], slPaymentPubKeyHashes = fromList [], slTypedValidator = Nothing, slOwnPaymentPubKeyHash = Nothing, slOwnStakingCredential = Nothing}"
Slot 00002: 00000000-0000-4000-8000-000000000000 {Wallet W[1]}:
  Contract log: Object (fromList [("mkTxLogLookups",Object (fromList [("slOtherData",Array []),("slOtherScripts",Array [Array [Object (fromList [("getScriptHash",String "a23782f3f7227bfa1802adaa332e41523d09639e5657d7f1cd7a95bf")]),Object (fromList [("unversioned",String "581a0100002225335333573466ebc00c008488008488004448004581"),("version",String "PlutusV2")])]]),("slOwnPaymentPubKeyHash",Null),("slOwnStakingCredential",Null),("slPaymentPubKeyHashes",Array []),("slTxOutputs",Array [Array [Object (fromList [("txOutRefId",Object (fromList [("getTxId",String "ac35b5e8f3649d55ae589a19e26a0413e6e8fd8911fcbf7371c4174fbb6c599c")])),("txOutRefIdx",Number 0.0)]),Object (fromList [("_decoratedTxOutReferenceScript",Null),("_decoratedTxOutScriptDatum",Array [String "923918e403bf43c34b4ef6b48eb2ee04babed17320d8d1b9ff9ad086e86f44ec",Object (fromList [("contents",Object (fromList [("getDatum",String "d87980")])),("tag",String "DatumInBody")])]),("_decoratedTxOutStakingCredential",Null),("_decoratedTxOutValidator",Null),("_decoratedTxOutValidatorHash",String "a23782f3f7227bfa1802adaa332e41523d09639e5657d7f1cd7a95bf"),("_decoratedTxOutValue",Object (fromList [("getValue",Array [Array [Object (fromList [("unCurrencySymbol",String "")]),Array [Array [Object (fromList [("unTokenName",String "")]),Number 2.5e7]]]])])),("tag",String "ScriptDecoratedTxOut")])]]),("slTypedValidator",Null)])),("mkTxLogResult",Object (fromList [("Right",Object (fromList [("tag",String "UnbalancedEmulatorTx"),("unBalancedEmulatorTx",Object (fromList [("txCertificates",Array []),("txCollateralInputs",Array []),("txData",Array [Array [String "923918e403bf43c34b4ef6b48eb2ee04babed17320d8d1b9ff9ad086e86f44ec",Object (fromList [("getDatum",String "d87980")])]]),("txFee",Object (fromList [("getValue",Array [])])),("txInputs",Array [Object (fromList [("txInputRef",Object (fromList [("txOutRefId",Object (fromList [("getTxId",String "ac35b5e8f3649d55ae589a19e26a0413e6e8fd8911fcbf7371c4174fbb6c599c")])),("txOutRefIdx",Number 0.0)])),("txInputType",Object (fromList [("contents",Array [Object (fromList [("getRedeemer",String "d87980")]),Object (fromList [("Left",String "a23782f3f7227bfa1802adaa332e41523d09639e5657d7f1cd7a95bf")]),String "923918e403bf43c34b4ef6b48eb2ee04babed17320d8d1b9ff9ad086e86f44ec"]),("tag",String "TxScriptAddress")]))])]),("txMetadata",Null),("txMint",Object (fromList [("getValue",Array [])])),("txMintingWitnesses",Array []),("txOutputs",Array []),("txReferenceInputs",Array []),("txReturnCollateral",Null),("txScripts",Array [Array [Object (fromList [("getScriptHash",String "a23782f3f7227bfa1802adaa332e41523d09639e5657d7f1cd7a95bf")]),Object (fromList [("unversioned",String "581a0100002225335333573466ebc00c008488008488004448004581"),("version",String "PlutusV2")])]]),("txSignatures",Array []),("txTotalCollateral",Null),("txValidRange",Object (fromList [("ivFrom",Array [Object (fromList [("tag",String "NegInf")]),Bool True]),("ivTo",Array [Object (fromList [("tag",String "PosInf")]),Bool True])])),("txWithdrawals",Array [])])),("unBalancedTxRequiredSignatories",Array []),("unBalancedTxUtxoIndex",Array [Array [Object (fromList [("txOutRefId",Object (fromList [("getTxId",String "ac35b5e8f3649d55ae589a19e26a0413e6e8fd8911fcbf7371c4174fbb6c599c")])),("txOutRefIdx",Number 0.0)]),Object (fromList [("getTxOut",Object (fromList [("address",String "addr_test1wz3r0qhn7u38h7scq2k65vewg9fr6ztrnet904l3e4aft0chgqzep"),("datum",Null),("datumhash",String "923918e403bf43c34b4ef6b48eb2ee04babed17320d8d1b9ff9ad086e86f44ec"),("inlineDatum",Null),("referenceScript",Null),("value",Object (fromList [("lovelace",Number 2.5e7)]))]))])]])]))])),("mkTxLogTxConstraints",Object (fromList [("txConstraintFuns",Array []),("txConstraints",Array [Object (fromList [("contents",Array [Object (fromList [("txOutRefId",Object (fromList [("getTxId",String "ac35b5e8f3649d55ae589a19e26a0413e6e8fd8911fcbf7371c4174fbb6c599c")])),("txOutRefIdx",Number 0.0)]),Object (fromList [("getRedeemer",String "d87980")]),Null]),("tag",String "MustSpendScriptOutput")]),Object (fromList [("contents",Object (fromList [("getDatum",String "d87980")])),("tag",String "MustIncludeDatumInTx")])]),("txOwnInputs",Array []),("txOwnOutputs",Array [])]))])
Slot 00002: W[1]: TxSubmit: 3287e0dc25c58ad1550995deb3f4931ff642fc6545ea66c9e0432c0fc78f8808
Slot 00002: *** CONTRACT LOG: "waiting for tx2 confirmed..."
Slot 00002: TxnValidate 3287e0dc25c58ad1550995deb3f4931ff642fc6545ea66c9e0432c0fc78f8808 []
Slot 00002: SlotAdd Slot 3
Slot 00003: W[7]: InsertionSuccess: New tip is Tip(Slot 3, BlockId 64c51d0cd6ce8034738a548b1271c8285fe310d851054e2f68bf9057fa44ec36, BlockNumber 2). UTxO state was added to the end.
Slot 00003: W[8]: InsertionSuccess: New tip is Tip(Slot 3, BlockId 64c51d0cd6ce8034738a548b1271c8285fe310d851054e2f68bf9057fa44ec36, BlockNumber 2). UTxO state was added to the end.
Slot 00003: W[6]: InsertionSuccess: New tip is Tip(Slot 3, BlockId 64c51d0cd6ce8034738a548b1271c8285fe310d851054e2f68bf9057fa44ec36, BlockNumber 2). UTxO state was added to the end.
Slot 00003: W[4]: InsertionSuccess: New tip is Tip(Slot 3, BlockId 64c51d0cd6ce8034738a548b1271c8285fe310d851054e2f68bf9057fa44ec36, BlockNumber 2). UTxO state was added to the end.
Slot 00003: W[2]: InsertionSuccess: New tip is Tip(Slot 3, BlockId 64c51d0cd6ce8034738a548b1271c8285fe310d851054e2f68bf9057fa44ec36, BlockNumber 2). UTxO state was added to the end.
Slot 00003: W[1]: InsertionSuccess: New tip is Tip(Slot 3, BlockId 64c51d0cd6ce8034738a548b1271c8285fe310d851054e2f68bf9057fa44ec36, BlockNumber 2). UTxO state was added to the end.
Slot 00003: W[10]: InsertionSuccess: New tip is Tip(Slot 3, BlockId 64c51d0cd6ce8034738a548b1271c8285fe310d851054e2f68bf9057fa44ec36, BlockNumber 2). UTxO state was added to the end.
Slot 00003: W[9]: InsertionSuccess: New tip is Tip(Slot 3, BlockId 64c51d0cd6ce8034738a548b1271c8285fe310d851054e2f68bf9057fa44ec36, BlockNumber 2). UTxO state was added to the end.
Slot 00003: W[3]: InsertionSuccess: New tip is Tip(Slot 3, BlockId 64c51d0cd6ce8034738a548b1271c8285fe310d851054e2f68bf9057fa44ec36, BlockNumber 2). UTxO state was added to the end.
Slot 00003: W[5]: InsertionSuccess: New tip is Tip(Slot 3, BlockId 64c51d0cd6ce8034738a548b1271c8285fe310d851054e2f68bf9057fa44ec36, BlockNumber 2). UTxO state was added to the end.
Slot 00003: *** CONTRACT LOG: "tx2 successfully submitted"
Slot 00003: 00000000-0000-4000-8000-000000000000 {Wallet W[1]}:
  Contract instance stopped (no errors)
Slot 00003: SlotAdd Slot 4
Slot 00004: W[7]: InsertionSuccess: New tip is Tip(Slot 4, BlockId 76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71, BlockNumber 3). UTxO state was added to the end.
Slot 00004: W[8]: InsertionSuccess: New tip is Tip(Slot 4, BlockId 76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71, BlockNumber 3). UTxO state was added to the end.
Slot 00004: W[6]: InsertionSuccess: New tip is Tip(Slot 4, BlockId 76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71, BlockNumber 3). UTxO state was added to the end.
Slot 00004: W[4]: InsertionSuccess: New tip is Tip(Slot 4, BlockId 76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71, BlockNumber 3). UTxO state was added to the end.
Slot 00004: W[2]: InsertionSuccess: New tip is Tip(Slot 4, BlockId 76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71, BlockNumber 3). UTxO state was added to the end.
Slot 00004: W[1]: InsertionSuccess: New tip is Tip(Slot 4, BlockId 76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71, BlockNumber 3). UTxO state was added to the end.
Slot 00004: W[10]: InsertionSuccess: New tip is Tip(Slot 4, BlockId 76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71, BlockNumber 3). UTxO state was added to the end.
Slot 00004: W[9]: InsertionSuccess: New tip is Tip(Slot 4, BlockId 76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71, BlockNumber 3). UTxO state was added to the end.
Slot 00004: W[3]: InsertionSuccess: New tip is Tip(Slot 4, BlockId 76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71, BlockNumber 3). UTxO state was added to the end.
Slot 00004: W[5]: InsertionSuccess: New tip is Tip(Slot 4, BlockId 76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71, BlockNumber 3). UTxO state was added to the end.
Final balances
Wallet 7: 
    {, ""}: 100000000
Wallet 8: 
    {, ""}: 100000000
Wallet 6: 
    {, ""}: 100000000
Wallet 4: 
    {, ""}: 100000000
Wallet 2: 
    {, ""}: 100000000
Wallet 1: 
    {, ""}: 99647071
Wallet 10: 
    {, ""}: 100000000
Wallet 9: 
    {, ""}: 100000000
Wallet 3: 
    {, ""}: 100000000
Wallet 5: 
    {, ""}: 100000000
```

Besides seeing that the script output was successfully spent in the second transaction, we can see that our `lookups` contain information about the output ref and the script itself, which the emulator needs as basic information about where to find the required data for this transaction. After prettifying the output log a bit, it looks like this:

```
Slot 00002: *** CONTRACT LOG: 
"Oref:
  TxOutRef {
    txOutRefId = ac35b5e8f3649d55ae589a19e26a0413e6e8fd8911fcbf7371c4174fbb6c599c, 
    txOutRefIdx = 0},

Lookups:
  ScriptLookups {
    slTxOutputs = fromList [
      (
        TxOutRef {
          txOutRefId = ac35b5e8f3649d55ae589a19e26a0413e6e8fd8911fcbf7371c4174fbb6c599c, txOutRefIdx = 0
          },
        ScriptDecoratedTxOut {
            _decoratedTxOutValidatorHash = a23782f3f7227bfa1802adaa332e41523d09639e5657d7f1cd7a95bf, _decoratedTxOutStakingCredential = Nothing,
            _decoratedTxOutValue = Value (Map [(,Map [(\"\",25000000)])]),
            _decoratedTxOutScriptDatum = (
              923918e403bf43c34b4ef6b48eb2ee04babed17320d8d1b9ff9ad086e86f44ec,
              DatumInBody (
                Datum {getDatum = Constr 0 []}
              )
            ),
            _decoratedTxOutReferenceScript = Nothing,
            _decoratedTxOutValidator = Nothing
          }
      )
    ],
    slOtherScripts = fromList [
      (a23782f3f7227bfa1802adaa332e41523d09639e5657d7f1cd7a95bf,
      Versioned {unversioned = <Script>, version = PlutusV2})
    ],
    slOtherData = fromList [],
    slPaymentPubKeyHashes = fromList [],
    slTypedValidator = Nothing,
    slOwnPaymentPubKeyHash = Nothing,
    slOwnStakingCredential = Nothing
  }"
"
```


# References

### General documentation

[Plutus Technical Report](https://ci.iog.io/job/input-output-hk-plutus/master/x86_64-linux.packages.plutus-report/latest/download/1)\
[Plutus Code Specification](https://ci.iog.io/job/input-output-hk-plutus/master/x86_64-linux.packages.plutus-core-spec/latest/download/1)\
[The Extended UTxO Model](https://ci.iog.io/job/input-output-hk-plutus/master/x86_64-linux.packages.extended-utxo-spec/latest/download/1)\
[EUTxO Model Handbook](https://ucarecdn.com/6d3813f2-6886-4c61-833f-e78ba5f887d7/EUTXOhandbook_for_EC.pdf)\
[Plutus Haskell style guide](https://github.com/intersectMBO/plutus/blob/master/STYLEGUIDE.adoc)\
[Cardano Docs - Plutus](https://docs.cardano.org/plutus/learn-about-plutus/) [The Plutus Platform](https://www.youtube.com/watch?v=usMPt8KpBeI)

### Repositories

[plutus](https://github.com/intersectMBO/plutus) - [docs](https://plutus.readthedocs.io/)\
[plutus-apps](https://github.com/intersectMBO/plutus-apps) - [docs](https://plutus-apps.readthedocs.io/en/latest/)\
[plutus-scripts](https://github.com/james-iohk/plutus-scripts)

### Research papers

[The Extended UTxO model](https://iohk.io/en/research/library/papers/the-extended-utxo-model/)[Native Custom Tokens in the Extended UTxO Model](https://iohk.io/en/research/library/papers/native-custom-tokens-in-the-extended-utxo-model/)\
[UTxOma: UTxO with Multi-Asset Support](https://iohk.io/en/research/library/papers/utxomautxo-with-multi-asset-support/)

### Blog posts

[Plutus Tx: compiling Haskell into Plutus Core](https://iohk.io/en/blog/posts/2021/02/02/plutus-tx-compiling-haskell-into-plutus-core/)


