Skip to content

Commit

Permalink
Fix build errors
Browse files Browse the repository at this point in the history
  • Loading branch information
Mak Muftic committed Jul 21, 2021
1 parent ceb7ce2 commit 7aea641
Show file tree
Hide file tree
Showing 6 changed files with 300 additions and 39 deletions.
74 changes: 59 additions & 15 deletions NodeFactory/stable-coin/cabal.project
Expand Up @@ -15,6 +15,7 @@ source-repository-package
subdir:
freer-extras
playground-common
plutus-chain-index
plutus-core
plutus-contract
plutus-ledger
Expand All @@ -26,7 +27,7 @@ source-repository-package
prettyprinter-configurable
quickcheck-dynamic
word-array
tag: 5cdd2c3d708bf4c33514681dee096da6463273b7
tag: 81ba78edb1d634a13371397d8c8b19829345ce0d

-- The following sections are copied from the 'plutus' repository cabal.project at the revision
-- given above.
Expand All @@ -38,25 +39,30 @@ source-repository-package
-- newer version of persistent. See stack.yaml for the mirrored
-- configuration.
package eventful-sql-common
ghc-options: -XDerivingStrategies -XStandaloneDeriving -XUndecidableInstances -XDataKinds -XFlexibleInstances
ghc-options: -XDerivingStrategies -XStandaloneDeriving -XUndecidableInstances -XDataKinds -XFlexibleInstances -XMultiParamTypeClasses

allow-newer:
-- Has a commit to allow newer aeson, not on Hackage yet
monoidal-containers:aeson
-- Pins to an old version of Template Haskell, unclear if/when it will be updated
, size-based:template-haskell
size-based:template-haskell

-- The following two dependencies are needed by plutus.
, eventful-sql-common:persistent
, eventful-sql-common:persistent-template
, ouroboros-consensus-byron:formatting
, beam-core:aeson
, beam-sqlite:aeson
, beam-sqlite:dlist
, beam-migrate:aeson

constraints:
-- aws-lambda-haskell-runtime-wai doesn't compile with newer versions
aws-lambda-haskell-runtime <= 3.0.3
-- big breaking change here, inline-r doens't have an upper bound
, singletons < 3.0
singletons < 3.0
-- breaks eventful even more than it already was
, persistent-template < 2.12
-- bizarre issue: in earlier versions they define their own 'GEq', in newer
-- ones they reuse the one from 'some', but there isn't e.g. a proper version
-- constraint from dependent-sum-template (which is the library we actually use).
, dependent-sum > 0.6.2.0

-- See the note on nix/pkgs/default.nix:agdaPackages for why this is here.
-- (NOTE this will change to ieee754 in newer versions of nixpkgs).
Expand All @@ -82,56 +88,65 @@ source-repository-package
source-repository-package
type: git
location: https://github.com/input-output-hk/cardano-crypto.git
tag: f73079303f663e028288f9f4a9e08bcca39a923e
tag: ce8f1934e4b6252084710975bd9bbc0a4648ece4

source-repository-package
type: git
location: https://github.com/input-output-hk/cardano-base
tag: 4251c0bb6e4f443f00231d28f5f70d42876da055
tag: a715c7f420770b70bbe95ca51d3dec83866cb1bd
subdir:
binary
binary/test
slotting
cardano-crypto-class
cardano-crypto-praos
cardano-crypto-tests
strict-containers

source-repository-package
type: git
location: https://github.com/input-output-hk/cardano-prelude
tag: ee4e7b547a991876e6b05ba542f4e62909f4a571
tag: fd773f7a58412131512b9f694ab95653ac430852
subdir:
cardano-prelude
cardano-prelude-test

source-repository-package
type: git
location: https://github.com/input-output-hk/ouroboros-network
tag: 6cb9052bde39472a0555d19ade8a42da63d3e904
tag: e50613562d6d4a0f933741fcf590b0f69a1eda67
subdir:
typed-protocols
typed-protocols-examples
ouroboros-network
ouroboros-network-testing
ouroboros-network-framework
ouroboros-consensus
ouroboros-consensus-byron
ouroboros-consensus-cardano
ouroboros-consensus-shelley
io-sim
io-sim-classes
network-mux
Win32-network

source-repository-package
type: git
location: https://github.com/input-output-hk/iohk-monitoring-framework
tag: a89c38ed5825ba17ca79fddb85651007753d699d
tag: 34abfb7f4f5610cabb45396e0496472446a0b2ca
subdir:
iohk-monitoring
tracer-transformers
contra-tracer
plugins/backend-aggregation
plugins/backend-ekg
plugins/backend-monitoring
plugins/backend-trace-forwarder
plugins/scribe-systemd

source-repository-package
type: git
location: https://github.com/input-output-hk/cardano-ledger-specs
tag: 097890495cbb0e8b62106bcd090a5721c3f4b36f
tag: a3ef848542961079b7cd53d599e5385198a3035c
subdir:
byron/chain/executable-spec
byron/crypto
Expand All @@ -143,8 +158,37 @@ source-repository-package
semantics/small-steps-test
shelley/chain-and-ledger/dependencies/non-integer
shelley/chain-and-ledger/executable-spec
shelley/chain-and-ledger/shelley-spec-ledger-test
shelley-ma/impl
cardano-ledger-core
alonzo/impl

-- A lot of plutus dependencies have to be synchronized with the dependencies of
-- cardano-node. If you update cardano-node, please make sure that all dependencies
-- of cardano-node are also updated.
source-repository-package
type: git
location: https://github.com/input-output-hk/cardano-node.git
tag: b3cabae6b3bf30a0b1b4e78bc4b67282dabad0a6
subdir:
cardano-api/test
cardano-api
cardano-node
cardano-cli
cardano-config

source-repository-package
type: git
location: https://github.com/input-output-hk/Win32-network
tag: 94153b676617f8f33abe8d8182c37377d2784bd1

source-repository-package
type: git
location: https://github.com/input-output-hk/hedgehog-extras
tag: 8bcd3c9dc22cc44f9fcfe161f4638a384fc7a187

-- The following dependencies are not mirrored in the
-- stack.yaml file, but they are needed regardless by cabal.
source-repository-package
type: git
location: https://github.com/input-output-hk/goblins
Expand Down
8 changes: 5 additions & 3 deletions NodeFactory/stable-coin/plutus-stable-coin.cabal
Expand Up @@ -29,13 +29,14 @@ common lang
library
hs-source-dirs: src
exposed-modules:
NodeFactory.Plutus.Contracts.Oracle.Core
NodeFactory.Plutus.Contracts.Oracle.Funds
NodeFactory.Plutus.Contracts.Oracle.PAB
-- NodeFactory.Plutus.Contracts.Oracle.Core
-- NodeFactory.Plutus.Contracts.Oracle.Funds
-- NodeFactory.Plutus.Contracts.Oracle.PAB
-- NodeFactory.Plutus.Contracts.Oracle.Swap
NodeFactory.Plutus.Contracts.StableCoin.Types
NodeFactory.Plutus.Contracts.StableCoin.OnChain
NodeFactory.Plutus.Contracts.StableCoin.OffChain
NodeFactory.Plutus.Contracts.Currency
build-depends: aeson
, base ^>=4.14.1.0
, containers
Expand All @@ -48,6 +49,7 @@ library
, plutus-tx-plugin
, plutus-tx
, plutus-use-cases
, lens
, prettyprinter
, text
default-language: Haskell2010
Expand Down
205 changes: 205 additions & 0 deletions NodeFactory/stable-coin/src/NodeFactory/Plutus/Contracts/Currency.hs
@@ -0,0 +1,205 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE MonoLocalBinds #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE ViewPatterns #-}
{-# OPTIONS_GHC -fno-ignore-interface-pragmas #-}
-- | Implements a custom currency with a minting policy that allows
-- the minting of a fixed amount of units.
module NodeFactory.Plutus.Contracts.Currency(
OneShotCurrency(..)
, CurrencySchema
, CurrencyError(..)
, AsCurrencyError(..)
, curPolicy
-- * Actions etc
, mintContract
, mintedValue
, currencySymbol
-- * Simple minting policy currency
, SimpleMPS(..)
, mintCurrency
-- * Creating thread tokens
, createThreadToken
) where

import Control.Lens
import Plutus.Contracts.PubKey (AsPubKeyError (..), PubKeyError)
import qualified Plutus.Contracts.PubKey as PK
import PlutusTx.Prelude hiding (Monoid (..), Semigroup (..))

import Plutus.Contract as Contract

import Ledger (CurrencySymbol, PubKeyHash, TxId, TxOutRef (..), pubKeyHash,
scriptCurrencySymbol, txId)
import qualified Ledger.Ada as Ada
import qualified Ledger.Constraints as Constraints
import qualified Ledger.Contexts as V
import Ledger.Scripts
import qualified PlutusTx
import qualified Ledger.Typed.Scripts as Scripts
import Ledger.Value (AssetClass, TokenName, Value)
import qualified Ledger.Value as Value

import Data.Aeson (FromJSON, ToJSON)
import qualified Data.Map as Map
import Data.Semigroup (Last (..))
import GHC.Generics (Generic)
import qualified PlutusTx.AssocMap as AssocMap
import Prelude (Semigroup (..))
import qualified Prelude as Haskell
import Schema (ToSchema)

{-# ANN module ("HLint: ignore Use uncurry" :: Haskell.String) #-}

-- | A currency that can be created exactly once
data OneShotCurrency = OneShotCurrency
{ curRefTransactionOutput :: (TxId, Integer)
-- ^ Transaction input that must be spent when
-- the currency is minted.
, curAmounts :: AssocMap.Map TokenName Integer
-- ^ How many units of each 'TokenName' are to
-- be minted.
}
deriving stock (Generic, Haskell.Show, Haskell.Eq)
deriving anyclass (ToJSON, FromJSON)
PlutusTx.makeLift ''OneShotCurrency

currencyValue :: CurrencySymbol -> OneShotCurrency -> Value
currencyValue s OneShotCurrency{curAmounts = amts} =
let
values = map (\(tn, i) -> (Value.singleton s tn i)) (AssocMap.toList amts)
in fold values

mkCurrency :: TxOutRef -> [(TokenName, Integer)] -> OneShotCurrency
mkCurrency (TxOutRef h i) amts =
OneShotCurrency
{ curRefTransactionOutput = (h, i)
, curAmounts = AssocMap.fromList amts
}

validate :: OneShotCurrency -> () -> V.ScriptContext -> Bool
validate c@(OneShotCurrency (refHash, refIdx) _) _ ctx@V.ScriptContext{V.scriptContextTxInfo=txinfo} =
let
-- see note [Obtaining the currency symbol]
ownSymbol = V.ownCurrencySymbol ctx

minted = V.txInfoForge txinfo
expected = currencyValue ownSymbol c

-- True if the pending transaction mints the amount of
-- currency that we expect
mintOK =
let v = expected == minted
in traceIfFalse "Value minted different from expected" v

-- True if the pending transaction spends the output
-- identified by @(refHash, refIdx)@
txOutputSpent =
let v = V.spendsOutput txinfo refHash refIdx
in traceIfFalse "Pending transaction does not spend the designated transaction output" v

in mintOK && txOutputSpent

curPolicy :: OneShotCurrency -> MintingPolicy
curPolicy cur = mkMintingPolicyScript $
$$(PlutusTx.compile [|| \c -> Scripts.wrapMintingPolicy (validate c) ||])
`PlutusTx.applyCode`
PlutusTx.liftCode cur

{- note [Obtaining the currency symbol]
The currency symbol is the address (hash) of the validator. That is why
we can use 'Ledger.scriptAddress' here to get the symbol in off-chain code,
for example in 'mintedValue'.
Inside the validator script (on-chain) we can't use 'Ledger.scriptAddress',
because at that point we don't know the hash of the script yet. That
is why we use 'V.ownCurrencySymbol', which obtains the hash from the
'PolicyCtx' value.
-}

-- | The 'Value' minted by the 'OneShotCurrency' contract
mintedValue :: OneShotCurrency -> Value
mintedValue cur = currencyValue (currencySymbol cur) cur

currencySymbol :: OneShotCurrency -> CurrencySymbol
currencySymbol = scriptCurrencySymbol . curPolicy

data CurrencyError =
CurPubKeyError PubKeyError
| CurContractError ContractError
deriving stock (Haskell.Eq, Haskell.Show, Generic)
deriving anyclass (ToJSON, FromJSON)

makeClassyPrisms ''CurrencyError

instance AsContractError CurrencyError where
_ContractError = _CurContractError

instance AsPubKeyError CurrencyError where
_PubKeyError = _CurPubKeyError

-- | @mint [(n1, c1), ..., (n_k, c_k)]@ creates a new currency with
-- @k@ token names, minting @c_i@ units of each token @n_i@.
-- If @k == 0@ then no value is minted. A one-shot minting policy
-- script is used to ensure that no more units of the currency can
-- be minted afterwards.
mintContract
:: forall w s e.
( AsCurrencyError e
)
=> PubKeyHash
-> [(TokenName, Integer)]
-> Contract w s e OneShotCurrency
mintContract pk amounts = mapError (review _CurrencyError) $ do
(txOutRef, txOutTx, pkInst) <- PK.pubKeyContract pk (Ada.lovelaceValueOf 1)
let theCurrency = mkCurrency txOutRef amounts
curVali = curPolicy theCurrency
lookups = Constraints.mintingPolicy curVali
<> Constraints.otherScript (Scripts.validatorScript pkInst)
<> Constraints.unspentOutputs (Map.singleton txOutRef txOutTx)
let mintTx = Constraints.mustSpendScriptOutput txOutRef unitRedeemer
<> Constraints.mustMintValue (mintedValue theCurrency)
tx <- submitTxConstraintsWith @Scripts.Any lookups mintTx
_ <- awaitTxConfirmed (txId tx)
pure theCurrency

-- | Minting policy for a currency that has a fixed amount of tokens issued
-- in one transaction
data SimpleMPS =
SimpleMPS
{ tokenName :: TokenName
, amount :: Integer
}
deriving stock (Haskell.Eq, Haskell.Show, Generic)
deriving anyclass (FromJSON, ToJSON, ToSchema)

type CurrencySchema =
Endpoint "Create native token" SimpleMPS

-- | Use 'mintContract' to create the currency specified by a 'SimpleMPS'
mintCurrency
:: Contract (Maybe (Last OneShotCurrency)) CurrencySchema CurrencyError OneShotCurrency
mintCurrency = do
SimpleMPS{tokenName, amount} <- endpoint @"Create native token"
ownPK <- pubKeyHash <$> ownPubKey
cur <- mintContract ownPK [(tokenName, amount)]
tell (Just (Last cur))
pure cur

-- | Create a thread token for a state machine
createThreadToken :: forall s w. Contract w s CurrencyError AssetClass
createThreadToken = do
ownPK <- pubKeyHash <$> ownPubKey
let tokenName :: TokenName = "thread token"
s <- mintContract ownPK [(tokenName, 1)]
pure $ Value.assetClass (currencySymbol s) tokenName

0 comments on commit 7aea641

Please sign in to comment.