Smart Contract

RandomPicker

A.85ba07db77467695.RandomPicker

Deployed

11h ago
Feb 28, 2026, 05:34:40 AM UTC

Dependents

0 imports
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