Smart Contract
RandomPicker
A.85ba07db77467695.RandomPicker
1import RandomConsumer from 0x45caec600164c9e6
2
3access(all) contract RandomPicker {
4 /// The RandomConsumer.Consumer resource used to request & fulfill randomness
5 access(self) let consumer: @RandomConsumer.Consumer
6 /// The canonical path for common Receipt storage
7 /// Note: production systems would consider handling path collisions
8 access(all) let ReceiptStoragePath: StoragePath
9
10 access(all) event Committed(values: [UInt64], commitBlock: UInt64, receiptID: UInt64)
11 access(all) event Revealed(winningResult: UInt64, values: [UInt64], commitBlock: UInt64, receiptID: UInt64)
12
13 /// The Receipt resource is used to store the values and the associated randomness request. By listing the
14 /// RandomConsumer.RequestWrapper conformance, this resource inherits all the default implementations of the
15 /// interface. This is why the Receipt resource has access to the getRequestBlock() and popRequest() functions
16 /// without explicitly defining them.
17 ///
18 access(all) resource Receipt : RandomConsumer.RequestWrapper {
19 access(all) let values: [UInt64]
20 /// The associated randomness request which contains the block height at which the request was made
21 /// and whether the request has been fulfilled.
22 access(all) var request: @RandomConsumer.Request?
23
24 init(values: [UInt64], request: @RandomConsumer.Request) {
25 self.values = values
26 self.request <- request
27 }
28 }
29
30 access(all) fun commit(values: [UInt64]): @Receipt {
31 pre {
32 values.length > 0: "Array of values cannot be empty"
33 }
34
35 let request: @RandomConsumer.Request <- self.consumer.requestRandomness()
36 let receipt: @RandomPicker.Receipt <- create Receipt(values: values, request: <- request)
37
38 emit Committed(
39 values: values,
40 commitBlock: receipt.getRequestBlock()!,
41 receiptID: receipt.uuid
42 )
43
44 return <-receipt
45 }
46
47 access(all) fun reveal(receipt: @Receipt): UInt64 {
48 pre {
49 receipt.getRequestBlock()! <= getCurrentBlock().height:
50 "Must wait at least 1 block to reveal"
51 receipt.request != nil:
52 "Already revealed"
53 }
54
55 let values: [UInt64] = receipt.values
56 let commitBlock: UInt64 = receipt.getRequestBlock()!
57 let receiptID = receipt.uuid
58 let request: @RandomConsumer.Request <- receipt.popRequest()
59
60 let index: UInt64 = self.consumer.fulfillRandomInRange(request: <-request, min: 0, max: UInt64(values.length - 1))
61 let winningResult: UInt64 = values[index]
62
63 emit Revealed(
64 winningResult: winningResult,
65 values: values,
66 commitBlock: commitBlock,
67 receiptID: receiptID
68 )
69
70 destroy receipt
71 return winningResult
72 }
73
74 init() {
75 self.consumer <- RandomConsumer.createConsumer()
76
77 self.ReceiptStoragePath = /storage/FlowRandomPicker_GOWTF
78 }
79
80}
81
82
83
84
85
86
87
88
89
90
91
92