Smart Contract
FlowYieldVaultsClosedBeta
A.b1d63873c3cc9f79.FlowYieldVaultsClosedBeta
1access(all) contract FlowYieldVaultsClosedBeta {
2
3 access(all) entitlement Admin
4 access(all) entitlement Beta
5
6 access(all) resource BetaBadge {
7 access(all) let assignedTo: Address
8 init(_ addr: Address) {
9 self.assignedTo = addr
10 }
11 access(all) view fun getOwner(): Address {
12 return self.assignedTo
13 }
14 }
15
16 // --- Paths ---
17 access(all) let UserBetaCapStoragePath: StoragePath
18 access(all) let AdminHandleStoragePath: StoragePath
19
20 // --- Registry: which capability was issued to which address, and revocation flags ---
21 access(all) struct AccessInfo {
22 access(all) let capID: UInt64
23 access(all) let isRevoked: Bool
24
25 init(_ capID: UInt64, _ isRevoked: Bool) {
26 self.capID = capID
27 self.isRevoked = isRevoked
28 }
29 }
30 access(all) var issuedCapIDs: {Address: AccessInfo}
31
32 // --- Events ---
33 access(all) event BetaGranted(addr: Address, capID: UInt64)
34 access(all) event BetaRevoked(addr: Address, capID: UInt64?)
35
36 /// Per-user badge storage path (under the *contract/deployer* account)
37 access(contract) fun _badgePath(_ addr: Address): StoragePath {
38 return StoragePath(identifier: "FlowYieldVaultsBetaBadge_".concat(addr.toString()))!
39 }
40
41 /// Ensure the admin-owned badge exists for the user
42 access(contract) fun _ensureBadge(_ addr: Address) {
43 let p = self._badgePath(addr)
44 if self.account.storage.type(at: p) == nil {
45 self.account.storage.save(<-create BetaBadge(addr), to: p)
46 }
47 }
48
49 access(contract) fun _destroyBadge(_ addr: Address) {
50 let p = self._badgePath(addr)
51 if let badge <- self.account.storage.load<@BetaBadge>(from: p) {
52 destroy badge
53 }
54 }
55
56 /// Issue a capability from the contract/deployer account and record its ID
57 access(contract) fun _issueBadgeCap(_ addr: Address): Capability<auth(Beta) &BetaBadge> {
58 let p = self._badgePath(addr)
59 let cap: Capability<auth(Beta) &BetaBadge> =
60 self.account.capabilities.storage.issue<auth(Beta) &BetaBadge>(p)
61
62 self.issuedCapIDs[addr] = AccessInfo(cap.id, false)
63
64 if let ctrl = self.account.capabilities.storage.getController(byCapabilityID: cap.id) {
65 ctrl.setTag("flowyieldvaults-beta")
66 }
67
68 emit BetaGranted(addr: addr, capID: cap.id)
69 return cap
70 }
71
72 /// Clean up any previously issued controller before issuing a fresh capability.
73 access(contract) fun _cleanupExistingGrant(_ addr: Address) {
74 if let info = self.issuedCapIDs[addr] {
75 if let ctrl = self.account.capabilities.storage.getController(byCapabilityID: info.capID) {
76 ctrl.delete()
77 emit BetaRevoked(addr: addr, capID: info.capID)
78 }
79 }
80 }
81
82 /// Delete the recorded controller, revoking *all copies* of the capability
83 access(contract) fun _revokeByAddress(_ addr: Address) {
84 let info = self.issuedCapIDs[addr] ?? panic("No cap recorded for address")
85 let ctrl = self.account.capabilities.storage.getController(byCapabilityID: info.capID)
86 ?? panic("Missing controller for recorded cap ID")
87 ctrl.delete()
88 self.issuedCapIDs[addr] = AccessInfo(info.capID, true)
89 self._destroyBadge(addr)
90 emit BetaRevoked(addr: addr, capID: info.capID)
91 }
92
93 // 2) A small in-account helper resource that performs privileged ops
94 access(all) resource AdminHandle {
95 access(Admin) fun grantBeta(addr: Address): Capability<auth(FlowYieldVaultsClosedBeta.Beta) &FlowYieldVaultsClosedBeta.BetaBadge> {
96 FlowYieldVaultsClosedBeta._cleanupExistingGrant(addr)
97 FlowYieldVaultsClosedBeta._ensureBadge(addr)
98 return FlowYieldVaultsClosedBeta._issueBadgeCap(addr)
99 }
100
101 access(Admin) fun revokeByAddress(addr: Address) {
102 FlowYieldVaultsClosedBeta._revokeByAddress(addr)
103 }
104 }
105
106 /// Read-only check used by any gated entrypoint
107 access(all) view fun getBetaCapID(_ addr: Address): UInt64? {
108 if let info = self.issuedCapIDs[addr] {
109 if info.isRevoked {
110 return nil
111 }
112 return info.capID
113 }
114 return nil
115 }
116
117 access(all) view fun validateBeta(_ addr: Address?, _ betaRef: auth(Beta) &BetaBadge): Bool {
118 if addr == nil {
119 return false
120 }
121 let recordedID: UInt64? = self.getBetaCapID(addr!)
122 if recordedID == nil {
123 return false
124 }
125
126 if betaRef.getOwner() != addr {
127 return false
128 }
129
130 return true
131 }
132
133 init() {
134 self.AdminHandleStoragePath = StoragePath(
135 identifier: "FlowYieldVaultsClosedBetaAdmin_\(self.account.address)"
136 )!
137 self.UserBetaCapStoragePath = StoragePath(
138 identifier: "FlowYieldVaultsUserBetaCap_\(self.account.address)"
139 )!
140
141 self.issuedCapIDs = {}
142
143 // Create and store the admin handle in *this* (deployer) account
144 self.account.storage.save(<-create AdminHandle(), to: self.AdminHandleStoragePath)
145 }
146}
147