Branch data Line data Source code
1 : : ;; Title: BME00 Governance Token
2 : : ;; Synopsis:
3 : : ;; This extension defines the governance token of BigMarket DAO.
4 : : ;; Description:
5 : : ;; The governance token is a simple SIP010-compliant fungible token
6 : : ;; with some added functions to make it easier to manage by
7 : : ;; BigMarket DAO proposals and extensions.
8 : : ;; The operations vesting schedule and recipients can be updated (see current-key and
9 : : ;; set-core-team-vesting) up till the first claim. If more recipients are added they
10 : : ;; allocation is proportionally diluted.
11 : :
12 : : (impl-trait .governance-token-trait.governance-token-trait)
13 : : (impl-trait 'SP2AKWJYC7BNY18W1XXKPGP0YVEK63QJG4793Z2D4.sip-010-trait-ft-standard.sip-010-trait)
14 : : (impl-trait 'SP3JP0N1ZXGASRJ0F7QAHWFPGTVK9T2XNXDB908Z.extension-trait.extension-trait)
15 : :
16 : : (define-fungible-token bmg-token u100000000000000) ;; 100M
17 : : (define-fungible-token bmg-token-locked)
18 : :
19 : : (define-constant core-team-max-vesting u1500000000000) ;; 15% of total supply (10,000,000 BIG)
20 : : (define-constant SCALE u1000000)
21 : :
22 : : (define-constant err-unauthorised (err u3000))
23 : : (define-constant err-not-token-owner (err u3001))
24 : : (define-constant err-not-core-team (err u3002))
25 : : (define-constant err-no-vesting-schedule (err u3003))
26 : : (define-constant err-nothing-to-claim (err u3004))
27 : : (define-constant err-core-vesting-limit (err u3005))
28 : : (define-constant err-cliff-not-reached (err u3006))
29 : : (define-constant err-recipients-are-locked (err u3007))
30 : : (define-constant err-transfers-blocked (err u3008))
31 : :
32 : : (define-data-var token-name (string-ascii 32) "BigMarket Governance Token")
33 : : (define-data-var token-symbol (string-ascii 10) "BIG")
34 : : (define-data-var token-uri (optional (string-utf8 256)) none)
35 : : (define-data-var token-decimals uint u6)
36 : : (define-data-var core-team-size uint u0)
37 : :
38 : : (define-data-var token-price uint u100000)
39 : : (define-data-var transfers-active bool false)
40 : :
41 : : (define-map core-team-vesting-tracker principal uint) ;; Tracks vested amount per recipient
42 : :
43 : : ;; ---- Vesting Storage ----
44 : : (define-data-var claim-made bool false)
45 : : (define-data-var current-key uint u0)
46 : : (define-map core-team-vesting {current-key: uint, recipient: principal}
47 : : {total-amount: uint, start-block: uint, duration: uint, claimed: uint}
48 : : )
49 : :
50 : : ;; --- Authorisation check
51 : :
52 : 421 : (define-public (is-dao-or-extension)
53 [ + ][ + + ]: 1085 : (ok (asserts! (or (is-eq tx-sender .bigmarket-dao) (contract-call? .bigmarket-dao is-extension contract-caller)) err-unauthorised))
54 : : )
55 : :
56 : : ;; ---- Vesting Methods ----
57 : :
58 : : ;; --- Vesting logic and sale
59 : 3 : (define-public (set-transfers-active (new-transfers-active bool))
60 : 3 : (begin
61 : 3 : (try! (is-dao-or-extension))
62 : 2 : (var-set transfers-active new-transfers-active)
63 : 2 : (ok true)
64 : : )
65 : : )
66 : 3 : (define-read-only (get-transfers-active) (var-get transfers-active))
67 : :
68 : 3 : (define-public (set-token-price (new-token-price uint))
69 : 5 : (begin
70 : 5 : (try! (is-dao-or-extension))
71 : 2 : (var-set token-price new-token-price)
72 : 2 : (ok true)
73 : : )
74 : : )
75 : :
76 : 421 : (define-public (set-core-team-vesting (core-team (list 200 {recipient: principal, start-block: uint, duration: uint})))
77 : 424 : (begin
78 : 424 : (try! (is-dao-or-extension))
79 [ + ]: 423 : (asserts! (not (var-get claim-made)) err-recipients-are-locked)
80 : 422 : (var-set current-key (+ u1 (var-get current-key)))
81 : 422 : (var-set core-team-size (len core-team))
82 : 422 : (as-contract (fold set-core-team-vesting-iter core-team (ok true)))
83 : : )
84 : : )
85 : 421 : (define-private (set-core-team-vesting-iter (item {recipient: principal, start-block: uint, duration: uint}) (previous-result (response bool uint)))
86 : 2108 : (begin
87 : 2108 : (try! previous-result)
88 : 2108 : (let (
89 : 2108 : (amount-scaled (/ (* core-team-max-vesting SCALE) (var-get core-team-size)))
90 : 2108 : (amount (/ amount-scaled SCALE))
91 : : )
92 : 2108 : (map-set core-team-vesting {current-key: (var-get current-key), recipient: (get recipient item)}
93 : 2108 : {total-amount: amount, start-block: (get start-block item), duration: (get duration item), claimed: u0})
94 : 2108 : (map-set core-team-vesting-tracker (get recipient item) amount)
95 : 2108 : (print {event: "set-core-team-vesting", amount: amount, start-block: (get start-block item), duration: (get duration item), current-key: (var-get current-key)})
96 : 2108 : (ok true)
97 : : )
98 : : )
99 : : )
100 : :
101 : 8 : (define-public (core-claim)
102 : 11 : (let
103 : : (
104 : 11 : (vesting (unwrap! (map-get? core-team-vesting {current-key: (var-get current-key), recipient: tx-sender}) err-no-vesting-schedule))
105 : 10 : (current-block burn-block-height)
106 : 10 : (user tx-sender)
107 : 10 : (start-block (get start-block vesting))
108 : 10 : (duration (get duration vesting))
109 : 10 : (total-amount (get total-amount vesting))
110 : 10 : (claimed (get claimed vesting))
111 [ + - ]: 10 : (elapsed (if (> current-block start-block) (- current-block start-block) u0))
112 : 10 : (vested-scaled (if (> elapsed duration)
113 [ + ]: 6 : (* total-amount SCALE)
114 [ + ]: 4 : (/ (* (* total-amount elapsed) SCALE) duration)))
115 : 10 : (vested (/ vested-scaled SCALE))
116 : 10 : (claimable (- vested claimed))
117 : 10 : (midpoint (+ start-block (/ duration u2)))
118 : : )
119 : :
120 [ + ]: 10 : (asserts! (> burn-block-height midpoint) err-cliff-not-reached)
121 [ + ]: 9 : (asserts! (> claimable u0) err-nothing-to-claim)
122 : 8 : (try! (as-contract (ft-mint? bmg-token claimable user)))
123 : :
124 : 8 : (map-set core-team-vesting {current-key: (var-get current-key), recipient: tx-sender}
125 : 8 : (merge vesting {claimed: (+ claimed claimable)}))
126 : 8 : (var-set claim-made true)
127 : 8 : (print {event: "core-claim", claimed: claimed, recipient: tx-sender, claimable: claimable, elapsed: elapsed, vested: vested})
128 : 8 : (ok claimable)
129 : : )
130 : : )
131 : :
132 : 7 : (define-read-only (get-vesting-schedule (who principal))
133 : 14 : (map-get? core-team-vesting {current-key: (var-get current-key), recipient: who})
134 : : )
135 : :
136 : : ;; --- Internal DAO functions
137 : :
138 : : ;; governance-token-trait
139 : :
140 : 3 : (define-public (bmg-transfer (amount uint) (sender principal) (recipient principal))
141 : 3 : (begin
142 : 3 : (try! (is-dao-or-extension))
143 : 2 : (ft-transfer? bmg-token amount sender recipient)
144 : : )
145 : : )
146 : :
147 : 114 : (define-public (bmg-lock (amount uint) (owner principal))
148 : 165 : (begin
149 : 165 : (try! (is-dao-or-extension))
150 : 164 : (try! (ft-burn? bmg-token amount owner))
151 : 161 : (ft-mint? bmg-token-locked amount owner)
152 : : )
153 : : )
154 : :
155 : 5 : (define-public (bmg-unlock (amount uint) (owner principal))
156 : 5 : (begin
157 : 5 : (try! (is-dao-or-extension))
158 : 4 : (try! (ft-burn? bmg-token-locked amount owner))
159 : 4 : (ft-mint? bmg-token amount owner)
160 : : )
161 : : )
162 : :
163 : 6 : (define-public (bmg-mint (amount uint) (recipient principal))
164 : 12 : (begin
165 : 12 : (try! (is-dao-or-extension))
166 : 11 : (ft-mint? bmg-token amount recipient)
167 : : )
168 : : )
169 : :
170 : 4 : (define-public (bmg-burn (amount uint) (owner principal))
171 : 4 : (begin
172 : 4 : (try! (is-dao-or-extension))
173 : 3 : (ft-burn? bmg-token amount owner)
174 : :
175 : : )
176 : : )
177 : :
178 : : ;; Other
179 : :
180 : 3 : (define-public (set-name (new-name (string-ascii 32)))
181 : 3 : (begin
182 : 3 : (try! (is-dao-or-extension))
183 : 2 : (ok (var-set token-name new-name))
184 : : )
185 : : )
186 : :
187 : 3 : (define-public (set-symbol (new-symbol (string-ascii 10)))
188 : 3 : (begin
189 : 3 : (try! (is-dao-or-extension))
190 : 2 : (ok (var-set token-symbol new-symbol))
191 : : )
192 : : )
193 : :
194 : 3 : (define-public (set-decimals (new-decimals uint))
195 : 3 : (begin
196 : 3 : (try! (is-dao-or-extension))
197 : 2 : (ok (var-set token-decimals new-decimals))
198 : : )
199 : : )
200 : :
201 : 1 : (define-public (set-token-uri (new-uri (optional (string-utf8 256))))
202 : 1 : (begin
203 : 1 : (try! (is-dao-or-extension))
204 : 0 : (ok (var-set token-uri new-uri))
205 : : )
206 : : )
207 : :
208 : 421 : (define-private (bmg-mint-many-iter (item {amount: uint, recipient: principal}))
209 : 2105 : (ft-mint? bmg-token (get amount item) (get recipient item))
210 : : )
211 : :
212 : 421 : (define-public (bmg-mint-many (recipients (list 200 {amount: uint, recipient: principal})))
213 : 421 : (begin
214 : 421 : (try! (is-dao-or-extension))
215 : 421 : (ok (map bmg-mint-many-iter recipients))
216 : : )
217 : : )
218 : :
219 : : ;; --- Public functions
220 : :
221 : : ;; sip-010-trait
222 : :
223 : 7 : (define-public (transfer (amount uint) (sender principal) (recipient principal) (memo (optional (buff 34))))
224 : 32 : (begin
225 [ - ][ + - ]: 32 : (asserts! (or (is-eq tx-sender sender) (is-eq contract-caller sender)) err-not-token-owner)
226 [ - ][ + + ]: 32 : (asserts! (or (var-get transfers-active) (unwrap! (is-dao-or-extension) err-unauthorised)) err-transfers-blocked)
227 : 31 : (ft-transfer? bmg-token amount sender recipient)
228 : : )
229 : : )
230 : :
231 : 2 : (define-read-only (get-name)
232 : 3 : (ok (var-get token-name))
233 : : )
234 : :
235 : 2 : (define-read-only (get-symbol)
236 : 3 : (ok (var-get token-symbol))
237 : : )
238 : :
239 : 2 : (define-read-only (get-decimals)
240 : 3 : (ok (var-get token-decimals))
241 : : )
242 : :
243 : 4 : (define-read-only (get-balance (who principal))
244 : 8 : (ok (+ (ft-get-balance bmg-token who) (ft-get-balance bmg-token-locked who)))
245 : : )
246 : :
247 : 2 : (define-read-only (get-total-supply)
248 : 3 : (ok (+ (ft-get-supply bmg-token) (ft-get-supply bmg-token-locked)))
249 : : )
250 : :
251 : 1 : (define-read-only (get-token-uri)
252 : 1 : (ok (var-get token-uri))
253 : : )
254 : :
255 : : ;; governance-token-trait
256 : :
257 : 0 : (define-read-only (bmg-get-balance (who principal))
258 : 0 : (get-balance who)
259 : : )
260 : :
261 : : ;; governance-weight threshold check - does who own at least factor per cent of total supply
262 : 1 : (define-read-only (bmg-has-percentage-balance (who principal) (factor uint))
263 : 2 : (ok (>= (* (unwrap-panic (get-balance who)) factor) (* (unwrap-panic (get-total-supply)) u1000)))
264 : : )
265 : :
266 : 1 : (define-read-only (bmg-get-locked (owner principal))
267 : 1 : (ok (ft-get-balance bmg-token-locked owner))
268 : : )
269 : :
270 : : ;; --- Extension callback
271 : :
272 : 2 : (define-public (callback (sender principal) (memo (buff 34)))
273 : 2 : (ok true)
274 : : )
|