-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathStandingBid.hs
180 lines (152 loc) · 6.6 KB
/
StandingBid.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
{-# LANGUAGE TemplateHaskell #-}
module HydraAuctionOnchain.Validators.StandingBid
( PStandingBidRedeemer (NewBidRedeemer, MoveToHydraRedeemer, ConcludeAuctionRedeemer)
, standingBidValidator
) where
import HydraAuctionOnchain.Errors.Validators.StandingBid (PStandingBidError (..))
import HydraAuctionOnchain.Helpers
( pdecodeInlineDatum
, pfindUniqueInputWithToken
, pfindUniqueOutputWithAddress
, pgetOwnInput
, ponlyOneInputFromAddress
, putxoAddress
)
import HydraAuctionOnchain.Lib.ScriptContext (pinputSpentWithRedeemer)
import HydraAuctionOnchain.Types.AuctionTerms (PAuctionTerms, pbiddingPeriod)
import HydraAuctionOnchain.Types.Error (errCode, passert, passertMaybe)
import HydraAuctionOnchain.Types.StandingBidState (PStandingBidState, pvalidateNewBid)
import HydraAuctionOnchain.Types.Tokens
( auctionEscrowTokenName
, ptxOutContainsStandingBidToken
)
import HydraAuctionOnchain.Validators.AuctionEscrow (pisConcluding)
import Plutarch.Api.V2 (PCurrencySymbol, PScriptContext, PTxInInfo, PTxInfo)
import Plutarch.Extra.Interval (pcontains)
import Plutarch.Extra.ScriptContext (ptxSignedBy)
import Plutarch.Monadic qualified as P
----------------------------------------------------------------------
-- Redeemers
data PStandingBidRedeemer (s :: S)
= NewBidRedeemer (Term s (PDataRecord '[]))
| MoveToHydraRedeemer (Term s (PDataRecord '[]))
| ConcludeAuctionRedeemer (Term s (PDataRecord '[]))
deriving stock (Generic)
deriving anyclass (PlutusType, PIsData, PShow, PEq)
instance DerivePlutusType PStandingBidRedeemer where
type DPTStrat _ = PlutusTypeData
----------------------------------------------------------------------
-- Validator
standingBidValidator
:: Term
s
( PCurrencySymbol
:--> PAuctionTerms
:--> PStandingBidState
:--> PStandingBidRedeemer
:--> PScriptContext
:--> PUnit
)
standingBidValidator = phoistAcyclic $
plam $ \auctionCs auctionTerms oldBidState redeemer ctx -> P.do
txInfo <- plet $ pfield @"txInfo" # ctx
-- (STBD0) The validator's own input should exist.
ownInput <-
plet $
passertMaybe
$(errCode StandingBid'Error'MissingStandingBidInput)
(pgetOwnInput # ctx)
-- (STBD1) There should only be one standing bid input.
passert $(errCode StandingBid'Error'TooManyOwnScriptInputs) $
ponlyOneInputFromAddress # (putxoAddress # ownInput) # txInfo
-- (STBD2) The standing bid input should contain the standing
-- bid token.
passert $(errCode StandingBid'Error'OwnInputMissingToken) $
ptxOutContainsStandingBidToken # auctionCs #$ pfield @"resolved" # ownInput
-- (STBD3) There should be no tokens minted or burned.
mintValue <- plet $ pfield @"mint" # txInfo
passert $(errCode StandingBid'Error'UnexpectedTokensMintedBurned) $
pfromData mintValue #== mempty
-- Branching checks based on the redeemer used.
pmatch redeemer $ \case
NewBidRedeemer _ ->
pcheckNewBid # txInfo # auctionCs # auctionTerms # ownInput # oldBidState
MoveToHydraRedeemer _ ->
pcheckMoveToHydra # txInfo # auctionTerms
ConcludeAuctionRedeemer _ ->
pcheckConcludeAuction # txInfo # auctionCs
----------------------------------------------------------------------
-- NewBid
pcheckNewBid
:: Term
s
( PTxInfo
:--> PCurrencySymbol
:--> PAuctionTerms
:--> PTxInInfo
:--> PStandingBidState
:--> PUnit
)
pcheckNewBid = phoistAcyclic $
plam $ \txInfo auctionCs auctionTerms ownInput oldBidState -> P.do
-- (STBD4) The standing bid output should exist.
ownOutput <-
plet $
passertMaybe
$(errCode StandingBid'NewBid'Error'MissingOwnOutput)
(pfindUniqueOutputWithAddress # (putxoAddress # ownInput) # txInfo)
-- (STBD5) The standing bid output should contain a standing
-- bid token.
passert $(errCode StandingBid'NewBid'Error'OwnOutputMissingToken) $
ptxOutContainsStandingBidToken # auctionCs # ownOutput
-- (STBD6) The standing bid output's datum should be decodable
-- as a standing bid state.
newBidState <-
plet $
passertMaybe
$(errCode StandingBid'NewBid'Error'FailedToDecodeNewBid)
(pdecodeInlineDatum # ownOutput)
-- (STBD7) The transition from the old bid state to the new
-- bid state should be valid.
passert $(errCode StandingBid'NewBid'Error'InvalidNewBidState) $
pvalidateNewBid # auctionCs # auctionTerms # oldBidState # newBidState
-- (STBD8) This redeemer can only be used during
-- the bidding period.
txInfoValidRange <- plet $ pfield @"validRange" # txInfo
passert $(errCode StandingBid'NewBid'Error'IncorrectValidityInterval) $
pcontains # (pbiddingPeriod # auctionTerms) # txInfoValidRange
pcon PUnit
----------------------------------------------------------------------
-- MoveToHydra
pcheckMoveToHydra :: Term s (PTxInfo :--> PAuctionTerms :--> PUnit)
pcheckMoveToHydra = phoistAcyclic $
plam $ \txInfo auctionTerms -> P.do
txInfoFields <- pletFields @["signatories", "validRange"] txInfo
-- (STBD9) The transaction should be signed by all the delegates.
delegates <- plet $ pfield @"delegates" # auctionTerms
passert $(errCode StandingBid'MoveToHydra'Error'MissingDelegateSignatures) $
pall # plam (\sig -> ptxSignedBy # txInfoFields.signatories # sig) # delegates
-- (STBD10) This redeemer can only be used during
-- the bidding period.
passert $(errCode StandingBid'MoveToHydra'Error'IncorrectValidityInterval) $
pcontains # (pbiddingPeriod # auctionTerms) # txInfoFields.validRange
pcon PUnit
----------------------------------------------------------------------
-- ConcludeAuction
pcheckConcludeAuction :: Term s (PTxInfo :--> PCurrencySymbol :--> PUnit)
pcheckConcludeAuction = phoistAcyclic $
plam $ \txInfo auctionCs -> P.do
-- (STBD11) There is an input that contains
-- the auction escrow token.
auctionEscrowUtxo <-
plet $
passertMaybe
$(errCode StandingBid'ConcludeAuction'Error'MissingAuctionEscrowInput)
(pfindUniqueInputWithToken # auctionCs # auctionEscrowTokenName # txInfo)
-- (STBD12) The auction escrow input is being spent with the
-- `BidderBuys` or `SellerReclaims` redeemer. Implicitly, this
-- means that the auction is concluding with either the winning
-- bidder buying the auction lot or the seller reclaiming it.
passert $(errCode StandingBid'ConcludeAuction'Error'InvalidAuctionEscrowRedeemer) $
pinputSpentWithRedeemer # pisConcluding # txInfo # auctionEscrowUtxo
pcon PUnit