Smart Contract

FLOATVerifiers

A.2d4c3caffbeab845.FLOATVerifiers

Valid From

84,502,484

Deployed

2d ago
Feb 26, 2026, 03:51:22 AM UTC

Dependents

3 imports
1// MADE BY: Emerald City, Jacob Tucker
2
3// This contract is probably the most confusing element of the FLOAT
4// platform. Listed here is a bunch of Structs which all implement
5// FLOAT.IVerifier. 
6
7// This pattern allows us to define arbitrary "restrictions" or "verifiers"
8// on our FLOAT Events. For example, Timelock is a verifier that makes sure
9// the current time is within the start and end date that the FLOAT Event host
10// specified when they created an event.  
11
12// The cool part is all of these verifiers are totally optional, and are only
13// passed in with the newly created event if the host wanted to enable them.  
14// You can mix and match them however you want. For example, one event I could
15// use both Timelock and Limited, and for another event I could just use Secret.  
16
17// Each verifier must have a `verify` function that takes in a generalized `params`
18// argument so we can pass user data through as well as info about the event itself.  
19// This is important for Secret for example because we want to pass the users guess
20// of the secret code through. For Limited, we need to know the totalSupply of the event,
21// so we pass it through as well.
22
23import FLOAT from 0x2d4c3caffbeab845
24import FungibleToken from 0xf233dcee88fe0abe
25import FlowToken from 0x1654653399040a61
26import Crypto
27
28access(all) contract FLOATVerifiers {
29
30    // The "verifiers" to be used
31    
32    //
33    // Timelock
34    //
35    // Specifies a time range in which the 
36    // FLOAT from an event can be claimed
37    access(all) struct Timelock: FLOAT.IVerifier {
38        // An automatic switch handled by the contract
39        // to stop people from claiming after a certain time.
40        access(all) let dateStart: UFix64
41        access(all) let dateEnding: UFix64
42
43        access(account) fun verify(_ params: {String: AnyStruct}) {
44            assert(
45                getCurrentBlock().timestamp >= self.dateStart,
46                message: "This FLOAT Event has not started yet."
47            )
48            assert(
49                getCurrentBlock().timestamp <= self.dateEnding,
50                message: "Sorry! The time has run out to mint this FLOAT."
51            )
52        }
53
54        init(_dateStart: UFix64, _timePeriod: UFix64) {
55            self.dateStart = _dateStart
56            self.dateEnding = self.dateStart + _timePeriod
57        }
58    }
59
60    //
61    // Secret
62    //
63    // Specifies a secret code in order
64    // to claim a FLOAT (not very secure, but cool feature)
65    access(all) struct Secret: FLOAT.IVerifier {
66        // The secret code, set by the owner of this event.
67        access(self) let secretPhrase: String
68
69        access(account) fun verify(_ params: {String: AnyStruct}) {
70            let secretPhrase = params["secretPhrase"]! as! String
71            assert(
72                self.secretPhrase == secretPhrase, 
73                message: "You did not input the correct secret phrase."
74            )
75        }
76
77        init(_secretPhrase: String) {
78            self.secretPhrase = _secretPhrase
79        }
80    }
81
82    //
83    // Limited
84    //
85    // Specifies a limit for the amount of people
86    // who can CLAIM. Not to be confused with how many currently
87    // hold a FLOAT from this event, since users can
88    // delete their FLOATs.
89    access(all) struct Limited: FLOAT.IVerifier {
90        access(all) var capacity: UInt64
91
92        access(account) fun verify(_ params: {String: AnyStruct}) {
93            let floatEvent = params["event"]! as! &FLOAT.FLOATEvent
94            let currentCapacity = floatEvent.totalSupply
95            assert(
96                currentCapacity < self.capacity,
97                message: "This FLOAT Event is at capacity."
98            )
99        }
100
101        init(_capacity: UInt64) {
102            self.capacity = _capacity
103        }
104    }
105
106    //
107    // MultipleSecret
108    //
109    // Allows for Multiple Secret codes
110    // Everytime a secret gets used, it gets removed
111    // from the list.
112    access(all) struct MultipleSecret: FLOAT.IVerifier {
113        access(self) let secrets: {String: Bool}
114
115        access(account) fun verify(_ params: {String: AnyStruct}) {
116            let secretPhrase = params["secretPhrase"]! as! String
117            assert(
118                self.secrets[secretPhrase] != nil, 
119                message: "You did not input a correct secret phrase."
120            )
121            self.secrets.remove(key: secretPhrase)
122        }
123
124        init(_secrets: [String]) {
125            self.secrets = {}
126            for secret in _secrets {
127                self.secrets[secret] = true
128            }
129        }
130    }
131
132    //
133    // SecretV2
134    //
135    // Much more secure than Secret
136    access(all) struct SecretV2: FLOAT.IVerifier {
137        access(all) let publicKey: String
138
139        access(account) fun verify(_ params: {String: AnyStruct}) {
140            let data: [UInt8] = (params["claimee"]! as! Address).toString().utf8
141            let sig: [UInt8] = (params["secretSig"]! as! String).decodeHex()
142            let publicKey = PublicKey(publicKey: self.publicKey.decodeHex(), signatureAlgorithm: SignatureAlgorithm.ECDSA_P256)
143            // validates that the "sig" was what was produced by signing "data" using the private key paired to "publicKey"
144            let valid = publicKey.verify(signature: sig, signedData: data, domainSeparationTag: "FLOW-V0.0-user", hashAlgorithm: HashAlgorithm.SHA3_256)
145            
146            assert(
147                valid, 
148                message: "You did not input the correct secret phrase."
149            )
150        }
151
152        init(_publicKey: String) {
153            self.publicKey = _publicKey
154        }
155    }
156
157    //
158    // MinimumBalance
159    //
160    // Requires a minimum Flow Balance to succeed
161    access(all) struct MinimumBalance: FLOAT.IVerifier {
162        access(all) let amount: UFix64
163
164        access(account) fun verify(_ params: {String: AnyStruct}) {
165            let claimee: Address = params["claimee"]! as! Address
166            let flowVault = getAccount(claimee).capabilities.borrow<&FlowToken.Vault>(/public/flowTokenBalance)
167                                ?? panic("Could not borrow the Flow Token Vault")
168            
169            assert(
170                flowVault.balance >= self.amount, 
171                message: "You do not meet the minimum required Flow Token balance."
172            )
173        }
174
175        init(_amount: UFix64) {
176            self.amount = _amount
177        }
178    }
179
180    access(all) struct ChallengeAchievementPoint: FLOAT.IVerifier {
181         access(account) fun verify(_ params: {String: AnyStruct}) {
182            panic("Deprecated")
183        }
184    }
185
186    //
187    // Email
188    //
189    // Requires an admin to sign off that a user
190    // address provided their email
191    access(all) struct Email: FLOAT.IVerifier {
192        access(all) let publicKey: String
193
194        access(account) fun verify(_ params: {String: AnyStruct}) {
195            let floatEvent = params["event"]! as! &FLOAT.FLOATEvent
196            let claimeeAddressAsString: String = (params["claimee"]! as! Address).toString()
197            let messageString: String = claimeeAddressAsString.concat(" provided email for eventId ").concat(floatEvent.eventId.toString())
198            let data: [UInt8] = messageString.utf8
199            let sig: [UInt8] = (params["emailSig"]! as! String).decodeHex()
200            let publicKey = PublicKey(publicKey: self.publicKey.decodeHex(), signatureAlgorithm: SignatureAlgorithm.ECDSA_P256)
201            // validates that the "sig" was what was produced by signing "data" using the private key paired to "publicKey"
202            let valid = publicKey.verify(signature: sig, signedData: data, domainSeparationTag: "FLOW-V0.0-user", hashAlgorithm: HashAlgorithm.SHA3_256)
203            
204            assert(
205                valid, 
206                message: "You did not input the correct secret phrase."
207            )
208        }
209
210        init(_publicKey: String) {
211            self.publicKey = _publicKey
212        }
213    }
214    
215}