Smart Contract

ShowUpStaking

A.a19273383554e1e1.ShowUpStaking

Valid From

123,168,555

Deployed

6d ago
Feb 21, 2026, 10:25:02 PM UTC

Dependents

5 imports
1import FungibleToken from 0xf233dcee88fe0abe
2import FlowToken from 0x1654653399040a61
3import ShowUpEvents from 0xa19273383554e1e1
4
5access(all) contract ShowUpStaking {
6    
7    // Events
8    access(all) event StakeDeposited(eventId: String, user: Address, amount: UFix64)
9    access(all) event StakeWithdrawn(eventId: String, user: Address, amount: UFix64)
10    access(all) event StakeForfeited(eventId: String, user: Address, amount: UFix64)
11    
12    // Paths
13    access(all) let StakeVaultStoragePath: StoragePath
14    access(all) let StakeVaultPublicPath: PublicPath
15    
16    // Stake Vault Resource Interface
17    access(all) resource interface StakeVaultPublic {
18        access(all) fun getStakedAmount(eventId: String): UFix64
19        access(all) fun getStakedEvents(): [String]
20    }
21    
22    // Individual Stake Resource
23    access(all) resource Stake {
24        access(all) let eventId: String
25        access(all) var amount: UFix64
26        access(all) let timestamp: UFix64
27        access(all) var isReturned: Bool
28        
29        init(eventId: String, amount: UFix64) {
30            self.eventId = eventId
31            self.amount = amount
32            self.timestamp = getCurrentBlock().timestamp
33            self.isReturned = false
34        }
35        
36        access(all) fun getAmount(): UFix64 {
37            return self.amount
38        }
39        
40        access(contract) fun markReturned() {
41            self.isReturned = true
42        }
43    }
44    
45    // Stake Vault Resource - holds all stakes for a user
46    access(all) resource StakeVault: StakeVaultPublic {
47        access(all) var stakes: @{String: Stake}
48        access(all) let vault: @FlowToken.Vault
49        
50        init() {
51            self.stakes <- {}
52            self.vault <- FlowToken.createEmptyVault(vaultType: Type<@FlowToken.Vault>()) as! @FlowToken.Vault
53        }
54        
55        // Deposit stake for an event
56        access(all) fun depositStake(eventId: String, stake: @FlowToken.Vault) {
57            pre {
58                !self.stakes.containsKey(eventId): "Already staked for this event"
59                stake.balance > 0.0: "Stake amount must be greater than 0"
60            }
61            
62            let amount = stake.balance
63            self.vault.deposit(from: <-stake)
64            let stakeResource <- create Stake(eventId: eventId, amount: amount)
65            let oldStake <- self.stakes[eventId] <- stakeResource
66            destroy oldStake
67            
68            emit StakeDeposited(eventId: eventId, user: self.owner?.address!, amount: amount)
69        }
70        
71        // Withdraw stake after checking in
72        access(all) fun withdrawStake(eventId: String): @FlowToken.Vault {
73            pre {
74                self.stakes.containsKey(eventId): "No stake found for this event"
75            }
76            
77            let stake <- self.stakes.remove(key: eventId)!
78            let amount = stake.getAmount()
79            stake.markReturned()
80            destroy stake
81            
82            // Withdraw from main vault
83            let withdrawnVault <- self.vault.withdraw(amount: amount)
84            
85            emit StakeWithdrawn(eventId: eventId, user: self.owner?.address!, amount: amount)
86            return <-(withdrawnVault as! @FlowToken.Vault)
87        }
88        
89        // Forfeit stake (called by contract owner for no-shows)
90        access(contract) fun forfeitStake(eventId: String): @FlowToken.Vault {
91            pre {
92                self.stakes.containsKey(eventId): "No stake found for this event"
93            }
94            
95            let stake <- self.stakes.remove(key: eventId)!
96            let amount = stake.getAmount()
97            destroy stake
98            
99            // Withdraw from main vault  
100            let withdrawnVault <- self.vault.withdraw(amount: amount)
101            
102            emit StakeForfeited(eventId: eventId, user: self.owner?.address!, amount: amount)
103            return <-(withdrawnVault as! @FlowToken.Vault)
104        }
105        
106        access(all) fun getStakedAmount(eventId: String): UFix64 {
107            if let stake = &self.stakes[eventId] as &Stake? {
108                return stake.getAmount()
109            }
110            return 0.0
111        }
112        
113        access(all) fun getStakedEvents(): [String] {
114            return self.stakes.keys
115        }
116        
117        access(all) fun getTotalStaked(): UFix64 {
118            var total: UFix64 = 0.0
119            for eventId in self.stakes.keys {
120                total = total + self.getStakedAmount(eventId: eventId)
121            }
122            return total
123        }
124    }
125    
126    // Create Stake Vault
127    access(all) fun createStakeVault(): @StakeVault {
128        return <-create StakeVault()
129    }
130    
131    // Public function to stake for an event
132    access(all) fun stakeForEvent(
133        userVault: &StakeVault, 
134        paymentVault: @FlowToken.Vault, 
135        eventId: String,
136        eventsCollection: &ShowUpEvents.EventsCollection
137    ) {
138        pre {
139            paymentVault.balance > 0.0: "Payment amount must be greater than 0"
140        }
141        
142        let amount = paymentVault.balance
143        
144        // Deposit stake in user's vault
145        userVault.depositStake(eventId: eventId, stake: <-paymentVault)
146        
147        // Record stake in events collection
148        eventsCollection.stakeForEvent(
149            eventId: eventId, 
150            staker: userVault.owner?.address!, 
151            amount: amount
152        )
153    }
154    
155    // Public function to check in and return stake
156    access(all) fun checkInAndReturnStake(
157        userVault: &StakeVault,
158        eventId: String,
159        eventsCollection: &ShowUpEvents.EventsCollection
160    ): @FlowToken.Vault {
161        // Check in user
162        eventsCollection.checkInUser(eventId: eventId, user: userVault.owner?.address!)
163        
164        // Return stake
165        return <-userVault.withdrawStake(eventId: eventId)
166    }
167    
168    init() {
169        self.StakeVaultStoragePath = /storage/ShowUpStakeVault
170        self.StakeVaultPublicPath = /public/ShowUpStakeVault
171    }
172}
173