Source code on Github
module EUTxO where

open import Prelude
open import Prelude.Lists.Membership

PolicyID  = 
TokenName = 
Quantity  = 

Tokens = Map⟨ TokenName  Quantity 
Value  = Map⟨ PolicyID   Tokens 
Slot  = 
DATA  = 
Hash  = 

Address   = Hash
PubKey    = Hash
Signature = Hash

variable
  v v′ v″ : Value
  slot : Slot
postulate instance
  Ord-Tokens    : Ord Tokens
  DecOrd-Tokens : DecOrd Tokens
instance
  Semigroup-ℕ  = Semigroup-ℕ-+
  Monoid-ℕ     = Monoid-ℕ-+
  Monoid-Value : Monoid Tokens
  Monoid-Value = λ where .ε  

private variable A : Type 
postulate
  _♯ : A  Hash
  ♯-injective : Injective≡ {A = A} _♯

 : List Value  Value
 [] = 
 (v  vs) = v   vs

record TxOutput : Type where
  constructor _at_
  field value    : Value
        address  : Address
        datum    : DATA
open TxOutput public
unquoteDecl DecEq-TxO = DERIVE DecEq [ quote TxOutput , DecEq-TxO ]

record TxOutputRef : Type where
  constructor _indexed-at_
  field txId  : Hash
        index : 
open TxOutputRef public
unquoteDecl DecEq-TxOR = DERIVE DecEq [ quote TxOutputRef , DecEq-TxOR ]

record InputInfo : Type where
  field output        : TxOutput
        outputRef     : TxOutputRef
        validatorHash : Hash
        redeemerHash  : Hash
unquoteDecl DecEq-InputInfo = DERIVE DecEq [ quote InputInfo , DecEq-InputInfo ]

record TxInfo : Type where
  field inputs  : List InputInfo
        outputs : List TxOutput
        mint   : Value
unquoteDecl DecEq-TxInfo = DERIVE DecEq [ quote TxInfo , DecEq-TxInfo ]

Redeemer = DATA
Datum    = DATA
ScriptValidator = TxInfo {-× Hash-}  Datum  Redeemer  Bool
MintingPolicy   = TxInfo × PolicyID  Redeemer  Bool
postulate instance DecEq-MP : DecEq MintingPolicy

record TxInput : Type where
  field outputRef : TxOutputRef
        validator : TxInfo  DATA  DATA  Bool
        redeemer datum : DATA
open TxInput public

record Tx : Type where
  field inputs   : List TxInput
        outputs  : List TxOutput
        mint     : Value
        mintRdrs : Map⟨ MintingPolicy  Redeemer 
        interval : Slot × Slot
        sigs     : Map⟨ PubKey  Hash 
open Tx public
variable tx : Tx
postulate checkSig : Tx  PubKey  Hash  Type

-- A ledger is a list of transactions.
L = List Tx
variable l : L

instance
  Semigroup-L : Semigroup L
  Semigroup-L ._◇_ = _++_

  Monoid-L : Monoid L
  Monoid-L .ε = []

-- Auxiliary definitions.

outputRefs : Tx  List TxOutputRef
outputRefs = map outputRef  inputs

Resolved : Pred₀ Tx
Resolved tx =  {r}  r  outputRefs tx  TxOutput

ResolvedInput  = TxInput × TxOutput
ResolvedInputs = List ResolvedInput

resolveInputs :  tx  Resolved tx  ResolvedInputs
resolveInputs tx rtx = mapWith∈ (tx .inputs) λ {i} i∈ 
  i , rtx (∈-map⁺ outputRef i∈)

mkInputInfo : ResolvedInput  InputInfo
mkInputInfo (i , o) = record
  { output        = o
  ; outputRef     = i .outputRef
  ; validatorHash = i .validator 
  ; redeemerHash  = i .redeemer  }

mkTxInfo :  tx  Resolved tx  TxInfo
mkTxInfo tx rtx = record
  { inputs  = mkInputInfo <$> resolveInputs tx rtx
  ; outputs = tx .outputs
  ; mint    = tx .mint }

postulate
  resolvedOutRefs≡ :  tx (rtx : Resolved tx) 
      (InputInfo.outputRef  mkInputInfo <$> resolveInputs tx rtx)
     (outputRef <$> tx .inputs)

--

-- The state of a ledger maps output references locked by a validator to a value.
UTxO = Map⟨ TxOutputRef  TxOutput 
variable utxos utxos′ : UTxO

mkUtxo :  {out} tx  out  outputs tx  TxOutputRef × TxOutput
mkUtxo {out} tx out∈ = (tx ) indexed-at toℕ (L.Any.index out∈) , out

utxoTx : Tx  UTxO
utxoTx tx = fromList $ mapWith∈ (tx .outputs) (mkUtxo tx)

postulate
  ∉utxoTx        :  {or}  tx   or .txId  or ∉ᵈ utxoTx tx
  utxoTx-values≡ :  {tx}  values (utxoTx tx)  tx .outputs

∑ᵐ : UTxO  Value
∑ᵐ =   map value  values

postulate ∑ᵐ-∪ : ∑ᵐ (utxos  utxos′)  ∑ᵐ utxos  ∑ᵐ utxos′

∑outs≡ : ∑ᵐ (utxoTx tx)   (value <$> tx .outputs)
∑outs≡ = cong (  map value) utxoTx-values≡

applyTx : Tx  (UTxO  UTxO)
applyTx tx utxo = (utxo ─ᵏˢ outputRefs tx)  utxoTx tx

utxo : L  UTxO
utxo = λ where
  []  
  (tx  l)  applyTx tx (utxo l)

record IsValidTx (slot : Slot) (tx : Tx) (utxos : UTxO) : Type where
  field
    noDoubleSpending :
      ·Unique (outputRefs tx)

    validInterval : let (from , to) = tx .interval in
      (from  slot) × (slot  to)

    validOutputRefs :
      ∀[ ref  outputRefs tx ]
        (ref ∈ᵈ utxos)

  rtx : Resolved tx
  rtx = (utxos ‼_)  L.All.lookup validOutputRefs

  txInfo         = mkTxInfo      tx rtx
  resolvedInputs = resolveInputs tx rtx

  field
    preservesValues :
      tx .mint   (value  proj₂ <$> resolvedInputs)   (value <$> tx .outputs)

  -- ** script validation
    allInputsValidate :
      ∀[ i  tx .inputs ]
        T (i .validator txInfo (i .datum) (i .redeemer))

    validateValidHashes :
      ∀[ (i , o)  resolvedInputs ]
        (o .address  i .validator )

  -- ** minting policies
    validMintRedeemers :
      keys (tx .mint)  (_♯ <$> keys (tx .mintRdrs))

    allPoliciesValidate :
      ∀[ (p , r)  toList (tx .mintRdrs) ]
        T (p (txInfo , p ) r)

  -- ** signatures
    validSignatures :
      ∀[ (pk , s)  toList (tx .sigs) ]
        checkSig tx pk s

  -- derived properties
  open ≡-Reasoning

  outRefs≡ : (InputInfo.outputRef <$> txInfo .TxInfo.inputs)
            outputRefs tx
  outRefs≡ =
    begin
      InputInfo.outputRef <$> txInfo .TxInfo.inputs
    ≡⟨⟩
      InputInfo.outputRef <$> (mkInputInfo <$> resolvedInputs)
    ≡˘⟨ L.map-compose resolvedInputs 
      InputInfo.outputRef  mkInputInfo <$> resolvedInputs
    ≡⟨ resolvedOutRefs≡ tx rtx 
      outputRef <$> tx .inputs
    ≡⟨⟩
      outputRefs tx
    

  ∑utxoTx≡ : ∑ᵐ (utxoTx tx)
            tx .mint   (value  proj₂ <$> resolvedInputs)
  ∑utxoTx≡ = begin
    ∑ᵐ (utxoTx tx)                                  ≡⟨ ∑outs≡ 
     (value <$> tx .outputs)                       ≡˘⟨ preservesValues 
    tx .mint   (value  proj₂ <$> resolvedInputs) 

  postulate
    ∑utxos─∪≡ : ∑ᵐ (utxos ─ᵏˢ outputRefs tx)
                (value  proj₂ <$> resolvedInputs)
               ∑ᵐ utxos

open IsValidTx public

postulate isValidTx? :  slot tx s  Dec (IsValidTx slot tx s)

isValidTx : Slot  Tx  UTxO  Bool
isValidTx slot tx s =  isValidTx? slot tx s 

checkTx : Slot  UTxO  Tx  Bool
checkTx slot s tx =  isValidTx? slot tx s 

-- ** LEDGER small-step relation
data _⊢_—⟨_∣LEDGER⟩→_ : SSRel Slot UTxO Tx where

  ApplyTx : let utxos′ = applyTx tx utxos in
    T (checkTx slot utxos tx)
    ───────────────────────────────────
    slot  utxos —⟨ tx ∣LEDGER⟩→ utxos′