-
Notifications
You must be signed in to change notification settings - Fork 2
/
marlowe_ordered_lottery.hs
102 lines (78 loc) · 2.88 KB
/
marlowe_ordered_lottery.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
{-# LANGUAGE OverloadedStrings #-}
module Lottery where
import Language.Marlowe
import Ledger.Value
import Data.ByteString.Internal
import Data.String
{-
Marlowe Contract
N Users have k slots to deposit 1 token into the lottery role. The lottery role will select a user,
after k slots but before k*k slots, to receive all tokens that were deposited. If the lottery does
not select a user before k*k slots then all user are returned their 1 token deposit.
This script can be easily changed to account for any donation/fund raiser/group purchase.
The number n sets the maximum allow users to use the smart contract at one time.
The number k sets the timeframe for the lottery to play out.
Company: Logical Mechanism
Author: Quinn Parkinson
Year: 2021
-}
main :: IO ()
main = print . pretty $ genContracts (numUser, numUser)
numUser :: Integer
numUser = 10
-- A TokenName deposits 1 token to the lottery role.
buyin :: TokenName -> Action
buyin user = Deposit (Role "lottery") (Role user) (Token "" "") (Constant 1)
-- A user is paid all available tokens inside the lottery.
cashout :: TokenName -> Contract
cashout user = Pay (Role "lottery") (Party (Role user)) (Token "" "") (AvailableMoney (Role "lottery") (Token "" "")) Close
-- The lottery selects between user 1 and the nth user. One and n are in the bounds.
lotteryChoice :: Integer -> Action
lotteryChoice n = Choice (ChoiceId "choice" (Role "lottery")) [Bound 1 n]
-- The lottery can only select between 1 and n users for any value of n. If selected then cashout.
checkVote :: Integer -> Contract
checkVote 0 = Close
checkVote n =
If (ValueEQ
(ChoiceValue (ChoiceId "choice" (Role "lottery")))
(Constant n))
(cashout player)
(checkVote (n - 1))
where
player = fromString ("" ++ show n)
-- If the lottery does not select a user in k*k slots then return all deposits to users.
returnDeposit :: Integer -> Contract
returnDeposit 0 = Close
returnDeposit n =
Pay
(Role "lottery")
(Party (Role user))
(Token "" "")
(Constant 1)
(returnDeposit (n - 1))
where
user = fromString ("" ++ show n)
-- Give n users chose a number between 1 and n then checVote for that selected user.
choose :: Integer -> Contract
choose 0 = Close
choose n =
When
[Case
(lotteryChoice n)
(checkVote n)
] time (returnDeposit n)
where
time = 1000
-- Recursively generate the contract for N users.
genContracts :: (Integer, Integer) -> Contract
genContracts (0, 0) = Close
genContracts (0, nmax) = choose nmax
genContracts (n, nmax) =
When
[Case
(buyin player)
(genContracts (n - 1, nmax))
] time (choose (nmax - n))
where
player = fromString ("" ++ show (nmax - n + 1))
time = 100