Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,11 @@ The fake PAB consists of the following modules:
- adding collaterals,
- modifying tx outs to contain the minimum amount of lovelaces
- balancing non ada outputs

## Collateral handling

Current version handles collateral under the hood.

Before contract being executed, single transaction submitted to create collateral UTxO at "own" address. Default amount for collateral UTxO is 10 Ada. It also can be set via config.

BPI identifies collateral UTxO by its value. If "own" address already has UTxO with amount set in config, this UTxO will be used as collateral. UTxO that was picked as collateral is stored in memory, so each time BPI will use same UTxO for collateral. Also, collateral is not returned among other UTxOs inside `Contract` monad, e.g. from eDSL functions like `utxosAt`. So it is safe to use such functions without the risk of consuming collateral by accident.
54 changes: 46 additions & 8 deletions src/BotPlutusInterface/Contract.hs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ import BotPlutusInterface.Types (
Tip (block, slot),
TxFile (Signed),
collateralValue,
pcCollateralSize,
pcOwnPubKeyHash,
)
import Cardano.Api (
AsType (..),
Expand Down Expand Up @@ -105,7 +107,27 @@ runContract ::
Contract w s e a ->
IO (Either e a)
runContract contractEnv (Contract effs) = do
runM $ handlePABEffect @w contractEnv $ raiseEnd $ handleContract contractEnv effs
-- try to create collateral before any contract is executed
res <- crateCollateralUtxo
case res of
Left e -> error $ mkError e
Right () -> runUserContract
where
crateCollateralUtxo =
runM $ handlePABEffect @w contractEnv (handleCollateral contractEnv)

runUserContract =
runM $
handlePABEffect @w contractEnv $
raiseEnd $
handleContract contractEnv effs

mkError e =
let collateralAmt = pcCollateralSize $ cePABConfig contractEnv
in "Tried to create collateral UTxO with " <> show collateralAmt
<> " lovealces, but failed:\n"
<> show e
<> "\nContract execution aborted."

handleContract ::
forall (w :: Type) (e :: Type) (a :: Type).
Expand Down Expand Up @@ -503,37 +525,53 @@ handleCollateral ::
ContractEnvironment w ->
Eff effs (Either WAPI.WalletAPIError ())
handleCollateral cEnv = do
let ownPkh = pcOwnPubKeyHash $ cePABConfig cEnv
result <- (fmap swapEither . runEitherT) $
do
let helperLog :: PP.Doc () -> ExceptT CollateralUtxo (Eff effs) ()
helperLog msg = newEitherT $ Right <$> printBpiLog @w (Debug [CollateralLog]) msg

collateralNotInMem <-
newEitherT $
maybeToLeft "Collateral UTxO not found in contract env."
maybeToLeft ("PKH: " <> pretty ownPkh <> ". Collateral UTxO not found in contract env.")
<$> getInMemCollateral @w

helperLog collateralNotInMem

collateralNotInWallet <- newEitherT $ swapEither <$> findCollateralAtOwnPKH cEnv

helperLog
("Collateral UTxO not found or failed to be found in wallet: " <> pretty collateralNotInWallet)
( "PKH: " <> pretty ownPkh <> ". Collateral UTxO not found or failed to be found in wallet: "
<> pretty collateralNotInWallet
)

helperLog "Creating collateral UTxO."
helperLog ("PKH: " <> pretty ownPkh <> ". Creating collateral UTxO.")

notCreatedCollateral <- newEitherT $ swapEither <$> makeCollateral @w cEnv

helperLog
("Failed to create collateral UTxO: " <> pretty notCreatedCollateral)
( "PKH: " <> pretty ownPkh <> ". Failed to create collateral UTxO: "
<> pretty notCreatedCollateral
)

pure ("Failed to create collateral UTxO: " <> show notCreatedCollateral)
pure
( "PKH: " <> show ownPkh <> ". Failed to create collateral UTxO: "
<> show notCreatedCollateral
)

case result of
Right collteralUtxo ->
setInMemCollateral @w collteralUtxo
>> Right <$> printBpiLog @w (Debug [CollateralLog]) "successfully set the collateral utxo in env."
Left err -> pure $ Left $ WAPI.OtherError $ T.pack $ "Failed to make collateral: " <> show err
>> Right
<$> printBpiLog @w
(Debug [CollateralLog])
("PKH: " <> pretty ownPkh <> ". Successfully set the collateral utxo in env.")
Left err ->
pure $
Left $
WAPI.OtherError $
T.pack $
"PKH: " <> show ownPkh <> ". Failed to make collateral: " <> show err

{- | Create collateral UTxO by submitting Tx.
Then try to find created UTxO at own PKH address.
Expand Down