-
Notifications
You must be signed in to change notification settings - Fork 29
/
auto-alex.clar
467 lines (397 loc) · 14.5 KB
/
auto-alex.clar
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
(impl-trait .trait-ownable.ownable-trait)
(impl-trait .trait-sip-010.sip-010-trait)
(define-constant ERR-NOT-AUTHORIZED (err u1000))
(define-fungible-token auto-alex)
(define-data-var contract-owner principal tx-sender)
(define-map approved-contracts principal bool)
(define-data-var token-name (string-ascii 32) "Auto ALEX")
(define-data-var token-symbol (string-ascii 10) "auto-alex")
(define-data-var token-uri (optional (string-utf8 256)) (some u"https://cdn.alexlab.co/metadata/token-auto-alex.json"))
(define-data-var token-decimals uint u8)
(define-read-only (get-contract-owner)
(ok (var-get contract-owner))
)
(define-public (set-contract-owner (owner principal))
(begin
(try! (check-is-owner))
(ok (var-set contract-owner owner))
)
)
;; --- Authorisation check
(define-private (check-is-owner)
(ok (asserts! (is-eq tx-sender (var-get contract-owner)) ERR-NOT-AUTHORIZED))
)
(define-private (check-is-approved)
(ok (asserts! (default-to false (map-get? approved-contracts tx-sender)) ERR-NOT-AUTHORIZED))
)
;; Other
(define-public (set-name (new-name (string-ascii 32)))
(begin
(try! (check-is-owner))
(ok (var-set token-name new-name))
)
)
(define-public (set-symbol (new-symbol (string-ascii 10)))
(begin
(try! (check-is-owner))
(ok (var-set token-symbol new-symbol))
)
)
(define-public (set-decimals (new-decimals uint))
(begin
(try! (check-is-owner))
(ok (var-set token-decimals new-decimals))
)
)
(define-public (set-token-uri (new-uri (optional (string-utf8 256))))
(begin
(try! (check-is-owner))
(ok (var-set token-uri new-uri))
)
)
(define-public (add-approved-contract (new-approved-contract principal))
(begin
(try! (check-is-owner))
(ok (map-set approved-contracts new-approved-contract true))
)
)
(define-public (set-approved-contract (owner principal) (approved bool))
(begin
(try! (check-is-owner))
(ok (map-set approved-contracts owner approved))
)
)
;; --- Public functions
;; sip010-ft-trait
(define-public (transfer (amount uint) (sender principal) (recipient principal) (memo (optional (buff 34))))
(begin
(asserts! (is-eq sender tx-sender) ERR-NOT-AUTHORIZED)
(try! (ft-transfer? auto-alex amount sender recipient))
(match memo to-print (print to-print) 0x)
(ok true)
)
)
(define-read-only (get-name)
(ok (var-get token-name))
)
(define-read-only (get-symbol)
(ok (var-get token-symbol))
)
(define-read-only (get-decimals)
(ok (var-get token-decimals))
)
(define-read-only (get-balance (who principal))
(ok (ft-get-balance auto-alex who))
)
(define-read-only (get-total-supply)
(ok (ft-get-supply auto-alex))
)
(define-read-only (get-token-uri)
(ok (var-get token-uri))
)
;; --- Protocol functions
(define-constant ONE_8 u100000000)
;; @desc mint
;; @restricted ContractOwner/Approved Contract
;; @params token-id
;; @params amount
;; @params recipient
;; @returns (response bool)
(define-public (mint (amount uint) (recipient principal))
(begin
(asserts! (or (is-ok (check-is-approved)) (is-ok (check-is-owner))) ERR-NOT-AUTHORIZED)
(ft-mint? auto-alex amount recipient)
)
)
;; @desc burn
;; @restricted ContractOwner/Approved Contract
;; @params token-id
;; @params amount
;; @params sender
;; @returns (response bool)
(define-public (burn (amount uint) (sender principal))
(begin
(asserts! (or (is-ok (check-is-approved)) (is-ok (check-is-owner))) ERR-NOT-AUTHORIZED)
(ft-burn? auto-alex amount sender)
)
)
;; @desc pow-decimals
;; @returns uint
(define-private (pow-decimals)
(pow u10 (unwrap-panic (get-decimals)))
)
;; @desc fixed-to-decimals
;; @params amount
;; @returns uint
(define-read-only (fixed-to-decimals (amount uint))
(/ (* amount (pow-decimals)) ONE_8)
)
;; @desc decimals-to-fixed
;; @params amount
;; @returns uint
(define-private (decimals-to-fixed (amount uint))
(/ (* amount ONE_8) (pow-decimals))
)
;; @desc get-total-supply-fixed
;; @params token-id
;; @returns (response uint)
(define-read-only (get-total-supply-fixed)
(ok (decimals-to-fixed (unwrap-panic (get-total-supply))))
)
;; @desc get-balance-fixed
;; @params token-id
;; @params who
;; @returns (response uint)
(define-read-only (get-balance-fixed (account principal))
(ok (decimals-to-fixed (unwrap-panic (get-balance account))))
)
;; @desc transfer-fixed
;; @params token-id
;; @params amount
;; @params sender
;; @params recipient
;; @returns (response bool)
(define-public (transfer-fixed (amount uint) (sender principal) (recipient principal) (memo (optional (buff 34))))
(transfer (fixed-to-decimals amount) sender recipient memo)
)
;; @desc mint-fixed
;; @params token-id
;; @params amount
;; @params recipient
;; @returns (response bool)
(define-public (mint-fixed (amount uint) (recipient principal))
(mint (fixed-to-decimals amount) recipient)
)
;; @desc burn-fixed
;; @params token-id
;; @params amount
;; @params sender
;; @returns (response bool)
(define-public (burn-fixed (amount uint) (sender principal))
(burn (fixed-to-decimals amount) sender)
)
(define-private (mint-fixed-many-iter (item {amount: uint, recipient: principal}))
(mint-fixed (get amount item) (get recipient item))
)
(define-public (mint-fixed-many (recipients (list 200 {amount: uint, recipient: principal})))
(begin
(asserts! (or (is-ok (check-is-approved)) (is-ok (check-is-owner))) ERR-NOT-AUTHORIZED)
(ok (map mint-fixed-many-iter recipients))
)
)
;; constants
;;
(define-constant ERR-INVALID-LIQUIDITY (err u2003))
(define-constant ERR-REWARD-CYCLE-NOT-COMPLETED (err u10017))
(define-constant ERR-STAKING-NOT-AVAILABLE (err u10015))
(define-constant ERR-GET-BALANCE-FIXED-FAIL (err u6001))
(define-constant ERR-NOT-ACTIVATED (err u2043))
(define-constant ERR-ACTIVATED (err u2044))
(define-constant ERR-USER-ID-NOT-FOUND (err u10003))
(define-constant ERR-INSUFFICIENT-BALANCE (err u2045))
(define-constant ERR-INVALID-PERCENT (err u5000))
(define-data-var end-cycle uint u340282366920938463463374607431768211455)
(define-data-var start-block uint u340282366920938463463374607431768211455)
(define-read-only (get-start-block)
(var-get start-block)
)
(define-public (set-start-block (new-start-block uint))
(begin
(try! (check-is-owner))
(ok (var-set start-block new-start-block))
)
)
(define-read-only (get-end-cycle)
(var-get end-cycle)
)
(define-public (set-end-cycle (new-end-cycle uint))
(begin
(try! (check-is-owner))
(ok (var-set end-cycle new-end-cycle))
)
)
;; data maps and vars
;;
(define-data-var total-supply uint u0)
(define-data-var bounty-in-fixed uint u100000000) ;; 1 ALEX
(define-read-only (get-bounty-in-fixed)
(ok (var-get bounty-in-fixed))
)
(define-public (set-bounty-in-fixed (new-bounty-in-fixed uint))
(begin
(try! (check-is-owner))
(ok (var-set bounty-in-fixed new-bounty-in-fixed))
)
)
;; private functions
;;
(define-private (get-staking-reward (reward-cycle uint))
(contract-call? .alex-reserve-pool get-staking-reward .age000-governance-token (get-user-id) reward-cycle)
)
(define-private (get-staker-at-cycle (reward-cycle uint))
(contract-call? .alex-reserve-pool get-staker-at-cycle-or-default .age000-governance-token reward-cycle (get-user-id))
)
(define-private (get-user-id)
(default-to u0 (contract-call? .alex-reserve-pool get-user-id .age000-governance-token tx-sender))
)
(define-private (get-reward-cycle (stack-height uint))
(contract-call? .alex-reserve-pool get-reward-cycle .age000-governance-token stack-height)
)
(define-private (stake-tokens (amount-tokens uint) (lock-period uint))
(contract-call? .alex-reserve-pool stake-tokens .age000-governance-token amount-tokens lock-period)
)
(define-private (claim-staking-reward (reward-cycle uint))
(contract-call? .alex-reserve-pool claim-staking-reward .age000-governance-token reward-cycle)
)
;; public functions
;;
;; @desc get the next capital base of the vault
;; @desc next-base = principal to be staked at the next cycle
;; @desc + principal to be claimed at the next cycle and staked for the following cycle
;; @desc + reward to be claimed at the next cycle and staked for the following cycle
(define-read-only (get-next-base)
(let
(
(current-cycle (unwrap! (get-reward-cycle block-height) ERR-STAKING-NOT-AVAILABLE))
)
(ok
(+
(get amount-staked (as-contract (get-staker-at-cycle (+ current-cycle u1))))
(get to-return (as-contract (get-staker-at-cycle current-cycle)))
(as-contract (get-staking-reward current-cycle))
)
)
)
)
;; @desc get the intrinsic value of auto-alex
;; @desc intrinsic = next capital base of the vault / total supply of auto-alex
(define-read-only (get-intrinsic)
(ok (div-down (try! (get-next-base)) (var-get total-supply)))
)
(define-read-only (get-token-given-position (dx uint))
(ok
(if (is-eq u0 (var-get total-supply))
dx ;; initial position
(div-down (mul-down (var-get total-supply) dx) (try! (get-next-base)))
)
)
)
(define-read-only (is-cycle-bountiable (reward-cycle uint))
(> (as-contract (get-staking-reward reward-cycle)) (var-get bounty-in-fixed))
)
;; @desc add to position
;; @desc transfers dx to vault, stake them for 32 cycles and mints auto-alex, the number of which is determined as % of total supply / next base
;; @param dx the number of $ALEX in 8-digit fixed point notation
(define-public (add-to-position (dx uint))
(let
(
(current-cycle (unwrap! (get-reward-cycle block-height) ERR-STAKING-NOT-AVAILABLE))
)
(asserts! (> (var-get end-cycle) current-cycle) ERR-STAKING-NOT-AVAILABLE)
(asserts! (>= block-height (var-get start-block)) ERR-NOT-ACTIVATED)
(asserts! (> dx u0) ERR-INVALID-LIQUIDITY)
(let
(
(sender tx-sender)
(cycles-to-stake (if (> (var-get end-cycle) (+ current-cycle u32)) u32 (- (var-get end-cycle) current-cycle)))
(new-supply (try! (get-token-given-position dx)))
(new-total-supply (+ (var-get total-supply) new-supply))
)
;; transfer dx to contract to stake for max cycles
(try! (contract-call? .age000-governance-token transfer-fixed dx sender (as-contract tx-sender) none))
(as-contract (try! (stake-tokens dx cycles-to-stake)))
;; mint pool token and send to tx-sender
(var-set total-supply new-total-supply)
(try! (ft-mint? auto-alex (fixed-to-decimals new-supply) sender))
(print { object: "pool", action: "position-added", data: {new-supply: new-supply, total-supply: new-total-supply }})
(ok true)
)
)
)
(define-private (sum-claimed (claimed-response (response (tuple (entitled-token uint) (to-return uint)) uint)) (sum-so-far uint))
(match claimed-response
claimed (+ sum-so-far (get to-return claimed) (get entitled-token claimed))
err sum-so-far
)
)
;; claims alex for the reward-cycles and mint auto-alex
(define-public (claim-and-mint (reward-cycles (list 200 uint)))
(let
(
(claimed (unwrap-panic (contract-call? .staking-helper claim-staking-reward .age000-governance-token reward-cycles)))
)
(try! (add-to-position (fold sum-claimed claimed u0)))
(ok claimed)
)
)
;; @desc triggers external event that claims all that's available and stake for another 32 cycles
;; @desc this can be triggered by anyone at a fee (at the moment 0.1% of whatever is claimed)
;; @param reward-cycle the target cycle to claim (and stake for current cycle + 32 cycles). reward-cycle must be < current cycle.
(define-public (claim-and-stake (reward-cycle uint))
(let
(
;; claim all that's available to claim for the reward-cycle
(claimed (and (> (as-contract (get-user-id)) u0) (is-ok (as-contract (claim-staking-reward reward-cycle)))))
(balance (unwrap! (contract-call? .age000-governance-token get-balance-fixed (as-contract tx-sender)) ERR-GET-BALANCE-FIXED-FAIL))
(bounty (var-get bounty-in-fixed))
(current-cycle (unwrap! (get-reward-cycle block-height) ERR-STAKING-NOT-AVAILABLE))
)
(asserts! (>= block-height (var-get start-block)) ERR-NOT-ACTIVATED)
(asserts! (> current-cycle reward-cycle) ERR-REWARD-CYCLE-NOT-COMPLETED)
(asserts! (> balance bounty) ERR-INSUFFICIENT-BALANCE)
(asserts! (>= (var-get end-cycle) current-cycle) ERR-STAKING-NOT-AVAILABLE)
(let
(
(sender tx-sender)
(cycles-to-stake (if (>= (var-get end-cycle) (+ current-cycle u32)) u32 (- (var-get end-cycle) current-cycle)))
)
(and (> cycles-to-stake u0) (as-contract (try! (stake-tokens (- balance bounty) cycles-to-stake))))
(and (> bounty u0) (as-contract (try! (contract-call? .age000-governance-token transfer-fixed bounty tx-sender sender none))))
(ok true)
)
)
)
(define-public (reduce-position (percent uint))
(let
(
(sender tx-sender)
(current-cycle (unwrap! (get-reward-cycle block-height) ERR-STAKING-NOT-AVAILABLE))
;; claim last cycle just in case claim-and-stake has not yet been triggered
(claimed (as-contract (try! (claim-staking-reward (var-get end-cycle)))))
(balance (unwrap! (contract-call? .age000-governance-token get-balance-fixed (as-contract tx-sender)) ERR-GET-BALANCE-FIXED-FAIL))
(sender-balance (unwrap! (get-balance-fixed sender) ERR-GET-BALANCE-FIXED-FAIL))
(reduce-supply (mul-down percent sender-balance))
(reduce-balance (div-down (mul-down balance reduce-supply) (var-get total-supply)))
(new-total-supply (- (var-get total-supply) reduce-supply))
)
(asserts! (>= block-height (var-get start-block)) ERR-NOT-ACTIVATED)
(asserts! (and (<= percent ONE_8) (> percent u0)) ERR-INVALID-PERCENT)
;; only if beyond end-cycle and no staking positions
(asserts!
(and
(> current-cycle (var-get end-cycle))
(is-eq u0 (get amount-staked (as-contract (get-staker-at-cycle current-cycle))))
)
ERR-REWARD-CYCLE-NOT-COMPLETED
)
;; transfer relevant balance to sender
(as-contract (try! (contract-call? .age000-governance-token transfer-fixed reduce-balance tx-sender sender none)))
;; burn pool token
(var-set total-supply new-total-supply)
(try! (ft-burn? auto-alex (fixed-to-decimals reduce-supply) sender))
(print { object: "pool", action: "position-removed", data: {reduce-supply: reduce-supply, total-supply: new-total-supply }})
(ok reduce-balance)
)
)
(define-private (mul-down (a uint) (b uint))
(/ (* a b) ONE_8)
)
(define-private (div-down (a uint) (b uint))
(if (is-eq a u0)
u0
(/ (* a ONE_8) b)
)
)
;; contract initialisation
;; (set-contract-owner .executor-dao)
;; (contract-call? .alex-vault add-approved-token .auto-alex)