-
Notifications
You must be signed in to change notification settings - Fork 13
/
stackswap-farming-v2c5.clar
841 lines (750 loc) · 26.8 KB
/
stackswap-farming-v2c5.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
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
(use-trait liquidity-token 'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275.liquidity-token-trait-v4c.liquidity-token-trait)
(use-trait oracle-trait 'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275.stackwap-oracle-trait-v1b.oracle-trait)
(define-constant ERR_STAKING_NOT_AVAILABLE u4300)
(define-constant ERR_CANNOT_STAKE u4301)
(define-constant ERR_INSUFFICIENT_BALANCE u4302)
(define-constant ERR_REWARD_ROUND_NOT_COMPLETED u4303)
(define-constant ERR_NOTHING_TO_REDEEM u4304)
(define-constant ERR_PERMISSION_DENIED u4305)
(define-constant ERR_INVALID_ROUTER u4306)
(define-constant ERR_POOL_NOT_ENROLLED u4307)
(define-constant ERR_INVALID_STSW_TOKEN u4309)
(define-constant ERR_ALREADY_MIGRATED u4310)
(define-constant ERR_ROUTING_FAIL u4311)
(define-constant ERR_TRANSFER_FAIL u4312)
(define-constant ERR_TOKEN_ALREADY_IN_POOL u4313)
(define-constant ERR_FARM_ENDED u4314)
(define-constant ERR_FARM_NOT_ENDED u4315)
(define-constant ERR_UNSTAKELIST_FULL u4316)
;; Farm List Control
(define-data-var lp_count uint u0)
(define-read-only (getLPCount)
(ok (var-get lp_count))
)
(define-map FarmablePools
principal
{
token : (string-ascii 12),
type : bool
}
)
(define-map FarmablePoolsIdx
uint
principal
)
(define-read-only (getFarmContracts (farm-id uint))
(unwrap-panic (map-get? FarmablePoolsIdx farm-id))
)
(define-read-only (isFarmAvailable (pool principal))
(is-some (map-get? FarmablePools pool))
)
;; Farming Constants
(define-constant FIRST_FARMING_BLOCK u38083)
(define-constant REWARD_ROUND_LENGTH u1008) ;; how long a reward round is (144 * 7) u1008
(define-constant MAX_REWARD_ROUNDS u64)
(define-constant REWARD_ROUND_INDEXES (list u0 u1 u2 u3 u4 u5 u6 u7 u8 u9 u10 u11 u12 u13 u14 u15 u16 u17 u18 u19 u20 u21 u22 u23 u24 u25 u26 u27 u28 u29 u30 u31 u32 u33 u34 u35 u36 u37 u38 u39 u40 u41 u42 u43 u44 u45 u46 u47 u48 u49 u50 u51 u52 u53 u54 u55 u56 u57 u58 u59 u60 u61 u62 u63))
;; FARMING CONFIGURATION
;; BASIC_BLOCK_MINING_REWARD : u952000000
;; BASIC_ROUND_MINING_REWARD = BASIC_BLOCK_MINING_REWARD * 144 * 7 * 0.7
(define-constant MIN_STAKING_ROUND_REWARDS u10000000)
;;Farming Variables & DATA
(define-data-var farm_end_round uint u9999999999)
(define-data-var farm_start_round uint u13)
;; set before the 'change round' start
;; during the round, one can't change the block reward
(define-data-var reward_per_round uint u26869248000)
(define-map LPTotalData
principal ;; LP
{
amountLP: uint,
weight: uint
}
)
(define-read-only (getLPTotalData (pool principal))
(map-get? LPTotalData pool)
)
(define-private (getLPTotalDataOrDefault (pool principal))
(default-to { amountLP: u0, weight: u1 }
(map-get? LPTotalData pool))
)
(define-map LPUserData
{
user: principal,
pool: principal
}
{
amountLP: uint,
unclaimedList: (list 200 uint)
}
)
(define-read-only (getLPUserData (pool principal) (user principal))
(map-get? LPUserData { user: user, pool: pool })
)
(define-private (getLPUserDataOrDefault (pool principal) (user principal))
(default-to
{
amountLP: u0,
unclaimedList: (list )
}
(map-get? LPUserData { user: user, pool: pool }))
)
(define-map TotalRoundData
uint ;; round
{
value: uint,
reward: uint
}
)
(define-read-only (getTotalRoundData (round uint))
(map-get? TotalRoundData round)
)
(define-read-only (getTotalRoundDataOrDefault (round uint))
(default-to
{
value: u0,
reward: (var-get reward_per_round)
}
(map-get? TotalRoundData round))
)
(define-map LPRoundData
{
pool: principal,
round: uint
}
{
value: uint,
weight: uint,
amountLP: uint,
price: uint
}
)
(define-read-only (getLPRoundData (pool principal) (round uint))
(map-get? LPRoundData { pool: pool, round: round })
)
(define-private (getLPRoundDataOrDefault (pool principal) (round uint))
(default-to
{
value: u0,
weight: u0,
amountLP: u0,
price: u0
}
(map-get? LPRoundData { pool: pool, round: round }))
)
(define-map LPUserRoundData
{
pool: principal,
user: principal,
round: uint
}
{
amountLP: uint,
returnLP: uint
}
)
(define-read-only (getLPUserRoundData (pool principal) (user principal) (round uint))
(map-get? LPUserRoundData { pool: pool, user: user, round: round })
)
(define-private (getLPUserRoundDataOrDefault (pool principal) (user principal) (round uint))
(default-to
{
amountLP: u0,
returnLP: u0
}
(map-get? LPUserRoundData { pool: pool, user: user, round: round }))
)
;; Farming Functions
(define-read-only (getRewardRound (stacksHeight uint))
(if (>= stacksHeight FIRST_FARMING_BLOCK)
(some (/ (- stacksHeight FIRST_FARMING_BLOCK) REWARD_ROUND_LENGTH))
none)
)
(define-read-only (getFirstBlockOfRound (round uint))
(+ FIRST_FARMING_BLOCK (* REWARD_ROUND_LENGTH round))
)
(define-read-only (getFarmingReward (pool principal) (user principal) (round uint) )
(getEntitledStakingReward user round block-height pool)
)
(define-private (getEntitledStakingReward (user principal) (round uint) (stacksHeight uint) (pool principal))
(let
(
(tempTotalData (getTotalRoundDataOrDefault round))
(tempLPRoundData (getLPRoundDataOrDefault pool round))
(tempLPUserRoundData (getLPUserRoundDataOrDefault pool user round))
(userValue (* (* (get weight tempLPRoundData) (get price tempLPRoundData)) (get amountLP tempLPUserRoundData)))
)
(match (getRewardRound stacksHeight)
currentRound
(if (or (<= currentRound round) (is-eq u0 userValue) (< (var-get farm_end_round) round) (is-eq u0 (get value tempTotalData)))
{reward: u0, returnLP: (get returnLP tempLPUserRoundData)}
{reward: (/ (* (getStakingRewardsPerRound round (get reward tempTotalData)) userValue) (get value tempTotalData)),
returnLP: (get returnLP tempLPUserRoundData)}
)
{reward: u0, returnLP: (get returnLP tempLPUserRoundData)}
)
)
)
;; ;; STAKING ACTIONS
(define-public (stakeTokens (amount_tokens uint) (pool <liquidity-token>) (lock_period uint) (oracle <oracle-trait>))
(begin
(asserts! (isFarmAvailable (contract-of pool)) (err ERR_POOL_NOT_ENROLLED))
(asserts! (contract-call? 'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275.stackswap-security-list-v1a is-secure-router-or-user contract-caller) (err ERR_INVALID_ROUTER))
(let (
(user tx-sender)
(startHeight block-height)
(current_round (unwrap! (getRewardRound startHeight) (err ERR_STAKING_NOT_AVAILABLE)))
(start_round (var-get farm_start_round))
(round (+ u1 (if (> start_round current_round) start_round current_round)))
(tempLPUserData (getLPUserDataOrDefault (contract-of pool) user))
(tempLPTotalData (getLPTotalDataOrDefault (contract-of pool)))
(new_list (unwrap! (addItemsToList (get unclaimedList tempLPUserData) lock_period round) (err ERR_UNSTAKELIST_FULL)))
)
(asserts! (and (> lock_period u0) (<= lock_period MAX_REWARD_ROUNDS))
(err ERR_CANNOT_STAKE))
(asserts! (<= (+ round lock_period) (var-get farm_end_round)) (err ERR_FARM_ENDED))
(asserts! (> amount_tokens u0) (err ERR_CANNOT_STAKE))
(unwrap! (contract-call? pool transfer amount_tokens user (as-contract tx-sender) none)
(err ERR_INSUFFICIENT_BALANCE))
(map-set LPTotalData
(contract-of pool)
{
amountLP: (+ (get amountLP tempLPTotalData) amount_tokens),
weight: (get weight tempLPTotalData)
}
)
(map-set LPUserData
{
user: user,
pool: (contract-of pool)
}
{
amountLP: (+ (get amountLP tempLPUserData) amount_tokens),
unclaimedList: new_list
}
)
(try! (match (fold stakeTokensClosure REWARD_ROUND_INDEXES (ok {
user: user,
amountLP: amount_tokens,
pool: (contract-of pool),
first: round,
last: (+ round lock_period)
}))
okValue (ok true)
errValue (err errValue)
))
(try! (updateRoundStatus pool current_round oracle))
)
(ok true)
)
)
(define-private (stakeTokensClosure (reward_round_idx uint)
(commitmentResponse (response
{
user: principal,
amountLP: uint,
pool: principal,
first: uint,
last: uint
}
uint
)))
(match commitmentResponse
commitment
(let
(
(round (+ (get first commitment) reward_round_idx))
)
(begin
(if (and (>= round (get first commitment)) (< round (get last commitment)))
(begin
(if (is-eq round (- (get last commitment) u1))
(setTokensStaked (get user commitment) round (get amountLP commitment) (get amountLP commitment) (get pool commitment))
(setTokensStaked (get user commitment) round (get amountLP commitment) u0 (get pool commitment))
)
true
)
false
)
commitmentResponse
)
)
errValue commitmentResponse
)
)
(define-private (setTokensStaked (user principal) (round uint) (amount_staked uint) (to_return uint) (pool principal))
(let
(
(tempLPRoundData (getLPRoundDataOrDefault pool round))
(tempLPUserRoundData (getLPUserRoundDataOrDefault pool user round))
)
(map-set LPRoundData
{
pool: pool,
round: round
}
(merge tempLPRoundData {
amountLP: (+ amount_staked (get amountLP tempLPRoundData))
}
)
)
(map-set LPUserRoundData
{
pool: pool,
user: user,
round: round
}
{
amountLP: (+ amount_staked (get amountLP tempLPUserRoundData)),
returnLP: (+ to_return (get returnLP tempLPUserRoundData))
}
)
)
)
(define-public (claimStakingReward (round uint) (pool <liquidity-token>) (oracle <oracle-trait>))
(let
(
(stacksHeight block-height)
(user tx-sender)
(current_round (unwrap! (getRewardRound stacksHeight) (err ERR_STAKING_NOT_AVAILABLE)))
(entitled_reward_res (getEntitledStakingReward user round stacksHeight (contract-of pool)))
(entitled_reward (get reward entitled_reward_res))
(to_return (get returnLP entitled_reward_res))
(tempLPUserData (getLPUserDataOrDefault (contract-of pool) user))
(tempLPTotalData (getLPTotalDataOrDefault (contract-of pool)))
)
(asserts! (contract-call? 'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275.stackswap-security-list-v1a is-secure-router-or-user contract-caller) (err ERR_INVALID_ROUTER))
(asserts!
(> current_round round)
(err ERR_REWARD_ROUND_NOT_COMPLETED))
(asserts! (or (> to_return u0) (> entitled_reward u0)) (err ERR_NOTHING_TO_REDEEM))
(asserts! (<= round (var-get farm_end_round)) (err ERR_FARM_ENDED))
(map-delete LPUserRoundData
{
pool: (contract-of pool),
user: user,
round: round
}
)
(if (> to_return u0)
(begin
(try! (as-contract (contract-call? pool transfer to_return tx-sender user none)))
(map-set LPUserData
{
pool: (contract-of pool),
user: user
}
{
amountLP: (- (get amountLP tempLPUserData) to_return),
unclaimedList: (deleteItemFromList (get unclaimedList tempLPUserData) round)
}
)
(map-set LPTotalData
(contract-of pool)
(merge tempLPTotalData {amountLP : (- (get amountLP tempLPTotalData) to_return)})
)
)
(map-set LPUserData
{
pool: (contract-of pool),
user: user
}
{
amountLP: (get amountLP tempLPUserData),
unclaimedList: (deleteItemFromList (get unclaimedList tempLPUserData) round)
}
)
)
(if (> entitled_reward u0)
(unwrap! (as-contract (contract-call? 'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275.stsw-token-v4a transfer entitled_reward tx-sender user none)) (err ERR_TRANSFER_FAIL))
true
)
(try! (updateRoundStatus pool current_round oracle))
(ok true)
)
)
(define-public (updateLPCurrentRoundStatus (pool <liquidity-token>) (oracle <oracle-trait>))
(let (
(stacksHeight block-height)
(user tx-sender)
(current_round (unwrap! (getRewardRound stacksHeight) (err ERR_STAKING_NOT_AVAILABLE)))
)
(asserts! (contract-call? 'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275.stackswap-security-list-v1a is-secure-router-or-user contract-caller) (err ERR_INVALID_ROUTER))
(try! (updateRoundStatus pool current_round oracle))
(ok true)
)
)
(define-private (updateRoundStatus (pool <liquidity-token>) (round uint) (oracle <oracle-trait>))
(let (
(tempLPTotalData (getLPTotalDataOrDefault (contract-of pool)))
(tempTotalRoundData (getTotalRoundDataOrDefault round))
(tempLPRoundData (getLPRoundDataOrDefault (contract-of pool) round))
(price (try! (getLPPrice pool oracle)))
(new_lp_value (* (* (get amountLP tempLPRoundData) (get weight tempLPTotalData)) price))
)
(asserts! (isFarmAvailable (contract-of pool)) (err ERR_POOL_NOT_ENROLLED))
(map-set TotalRoundData
round
{
value : (- (+ (get value tempTotalRoundData) new_lp_value) (get value tempLPRoundData)),
reward : (var-get reward_per_round)
}
)
(map-set LPRoundData
{
pool : (contract-of pool),
round : round
}
{
value : new_lp_value,
weight : (get weight tempLPTotalData),
price : price,
amountLP: (get amountLP tempLPRoundData)
}
)
(ok true)
)
)
(define-public (unstakeLP (round uint) (pool <liquidity-token>))
(let
(
(stacksHeight block-height)
(user tx-sender)
(current_round (unwrap! (getRewardRound stacksHeight) (err ERR_STAKING_NOT_AVAILABLE)))
(tempLPUserRoundData (getLPUserRoundDataOrDefault (contract-of pool) user round))
(tempLPUserData (getLPUserDataOrDefault (contract-of pool) user))
(tempLPTotalData (getLPTotalDataOrDefault (contract-of pool)))
(to_return (get returnLP tempLPUserRoundData))
)
(asserts! (contract-call? 'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275.stackswap-security-list-v1a is-secure-router-or-user contract-caller) (err ERR_INVALID_ROUTER))
(asserts! (> to_return u0) (err ERR_NOTHING_TO_REDEEM))
(asserts! (> round (var-get farm_end_round)) (err ERR_FARM_NOT_ENDED))
(map-set LPUserRoundData
{
pool: (contract-of pool),
user: user,
round: round
}
(merge tempLPUserRoundData {returnLP : u0} )
)
(if (> to_return u0)
(begin
(try! (as-contract (contract-call? pool transfer to_return tx-sender user none)))
(map-set LPUserData
{
pool: (contract-of pool),
user: user
}
(merge tempLPUserData
{
amountLP: (- (get amountLP tempLPUserData) to_return),
}
)
)
(map-set LPTotalData
(contract-of pool)
(merge tempLPTotalData {amountLP : (- (get amountLP tempLPTotalData) to_return)})
)
true
)
false
)
(ok true)
)
)
(define-read-only (getStakingRewardsPerRound (target_round uint) (reward_basis uint))
(let (
(rounds_per_year u52)
(year_number (+ (/ target_round rounds_per_year) u1))
(staking_rewards_divider (pow u2 (/ (- year_number u1) u4)))
(actual_round_rewards (/ reward_basis staking_rewards_divider))
)
(if (>= actual_round_rewards MIN_STAKING_ROUND_REWARDS)
actual_round_rewards
MIN_STAKING_ROUND_REWARDS
)
)
)
(define-read-only (getFarmingRewardFromList (user principal) (pool principal) (unclaimedList (list 100 uint)))
(fold getEntitledStakingRewardClosure unclaimedList {
stakerId: user,
pool: pool,
rewardSum: u0
})
)
(define-private (getEntitledStakingRewardClosure (round uint)
(commitment
{
stakerId: principal,
pool: principal,
rewardSum: uint
}
))
(merge
commitment
{
rewardSum: (+ (get rewardSum commitment) (get reward (getEntitledStakingReward (get stakerId commitment) round block-height (get pool commitment))))
}
)
)
;; inner functions
;; 1 : STSW - X
;; 2 : X - STSW
;; 3 : STX - X
;; 4 : X - STX
;; 5 : lbtc - X
;; 6 : X - lbtc
(define-private (getLPPrice (pool <liquidity-token>) (oracle <oracle-trait>))
(let (
(lp_data (try! (contract-call? pool get-lp-data)))
(calc_type (unwrap-panic (map-get? FarmablePools (contract-of pool))))
(price (unwrap-panic (contract-call? oracle fetch-price (get token calc_type))))
)
(asserts! (is-eq (contract-of oracle) (unwrap-panic (contract-call? 'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275.stackswap-dao-v5k get-qualified-name-by-name "oracle-l"))) (err ERR_PERMISSION_DENIED))
(ok
(if (get type calc_type)
(/ (/ (* (* u1000000 (get balance-x lp_data)) (get last-price price)) (get shares-total lp_data)) (get decimals price))
(/ (/ (* (* u1000000 (get balance-y lp_data)) (get last-price price)) (get shares-total lp_data)) (get decimals price))
)
)
)
)
;; this is for claim lists
(define-data-var rem_item uint u0)
(define-private (removeFilter (a uint)) (not (is-eq a (var-get rem_item))))
(define-data-var size_item uint u0)
(define-data-var add_num uint u0)
(define-private (sizeFilter (a uint)) (< a (var-get size_item)))
(define-data-var check_list (list 200 uint) (list ))
(define-private (checkFilter (a uint))
(is-none (index-of (var-get check_list) a))
)
(define-private (deleteItemFromList (idx_list (list 200 uint)) (ritem uint))
(begin
(var-set rem_item ritem)
(unwrap-panic (as-max-len? (filter removeFilter idx_list) u200))
)
)
(define-private (addNumFunc (num uint))
(+ num (var-get add_num))
)
(define-private (cutSizedList (sizeitem uint) (addnum uint))
(begin
(var-set size_item sizeitem)
(var-set add_num addnum)
(map addNumFunc (unwrap-panic (as-max-len? (filter sizeFilter REWARD_ROUND_INDEXES) u64)))
)
)
(define-private (checkItemFromList (idx_list (list 200 uint)) (new_list (list 64 uint)))
(begin
(var-set check_list idx_list)
(unwrap-panic (as-max-len? (filter checkFilter new_list) u64))
)
)
(define-private (addItemsToList (idx_list (list 200 uint)) (sizeitem uint) (addnum uint))
(as-max-len? (concat idx_list (checkItemFromList idx_list (cutSizedList sizeitem addnum))) u200)
)
(define-private (cutSizedInverseList (sizeitem uint) (addnum uint))
(begin
(var-set size_item sizeitem)
(var-set add_num addnum)
(fold inverseNumFunc (unwrap-panic (as-max-len? (filter sizeFilter REWARD_ROUND_INDEXES) u200)) (list ))
)
)
(define-private (inverseNumFunc (num uint) (idx_list (list 200 uint)))
(unwrap-panic (as-max-len? (concat (list (+ num (var-get add_num))) idx_list) u200))
)
;; manage
(define-public (setFarmEndRound (end_round uint))
(begin
(asserts! (is-eq contract-caller (unwrap-panic (contract-call? 'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275.stackswap-dao-v5k get-qualified-name-by-name "farm-adder"))) (err ERR_PERMISSION_DENIED))
(ok (var-set farm_end_round end_round))
)
)
(define-read-only (getFarmEndRound)
(var-get farm_end_round)
)
;; manage
(define-public (setFarmStartRound (start_round uint))
(begin
(asserts! (is-eq contract-caller (unwrap-panic (contract-call? 'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275.stackswap-dao-v5k get-qualified-name-by-name "farm-adder"))) (err ERR_PERMISSION_DENIED))
(ok (var-set farm_start_round start_round))
)
)
(define-read-only (getFarmStartRound)
(var-get farm_start_round)
)
(define-public (addPool (new-pool <liquidity-token>) (type bool) (token (string-ascii 12)))
(let
(
(tokens (try! (contract-call? new-pool get-tokens)))
(new_pool_principal (contract-of new-pool))
)
(asserts! (is-eq contract-caller (unwrap-panic (contract-call? 'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275.stackswap-dao-v5k get-qualified-name-by-name "farm-adder"))) (err ERR_PERMISSION_DENIED))
(if (isFarmAvailable new_pool_principal)
(map-set FarmablePools new_pool_principal {type: type, token : token})
(begin
(var-set lp_count (+ (var-get lp_count) u1))
(map-set FarmablePoolsIdx (var-get lp_count) new_pool_principal )
(map-set FarmablePools new_pool_principal {type: type, token : token})
)
)
(ok true)
)
)
(define-public (removePool (remove-pool <liquidity-token>) (oracle <oracle-trait>))
(begin
(asserts! (is-eq contract-caller (unwrap-panic (contract-call? 'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275.stackswap-dao-v5k get-qualified-name-by-name "farm-adder"))) (err ERR_PERMISSION_DENIED))
(try! (changeLPWeight u0 remove-pool oracle))
(ok (map-delete FarmablePools (contract-of remove-pool)))
)
)
(define-public (changeRewardAmount (to_change uint))
(begin
(asserts! (is-eq contract-caller (contract-call? 'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275.stackswap-dao-v5k get-dao-owner)) (err ERR_PERMISSION_DENIED))
(var-set reward_per_round to_change)
(let (
(current_round (unwrap! (getRewardRound block-height) (err ERR_STAKING_NOT_AVAILABLE)))
(tempTotalRoundData (getTotalRoundDataOrDefault current_round))
)
(map-set TotalRoundData
current_round
{
value: (get value tempTotalRoundData),
reward: to_change
}
)
)
(ok true)
)
)
(define-public (changeLPWeight (to_change uint) (pool <liquidity-token>) (oracle <oracle-trait>))
(begin
(asserts! (is-eq contract-caller (contract-call? 'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275.stackswap-dao-v5k get-dao-owner)) (err ERR_PERMISSION_DENIED))
(let (
(current_round (unwrap! (getRewardRound block-height) (err ERR_STAKING_NOT_AVAILABLE)))
(tempLPTotalData (getLPTotalDataOrDefault (contract-of pool)))
)
(map-set LPTotalData
(contract-of pool)
{
amountLP: (get amountLP tempLPTotalData),
weight: to_change
}
)
(try! (updateRoundStatus pool current_round oracle))
)
(ok true)
)
)
(define-constant REWARD_CYCLE_INDEXES_REV (list u63 u62 u61 u60 u59 u58 u57 u56 u55 u54 u53 u52 u51 u50 u49 u48 u47 u46 u45 u44 u43 u42 u41 u40 u39 u38 u37 u36 u35 u34 u33 u32 u31 u30 u29 u28 u27 u26 u25 u24 u23 u22 u21 u20 u19 u18 u17 u16 u15 u14 u13 u12 u11 u10 u9 u8 u7 u6 u5 u4 u3 u2 u1 u0))
(define-map UserMigrated
{
user: principal,
pool: principal
}
bool
)
(define-read-only (isUserMigratable (pool principal) (user principal))
(is-none (map-get? UserMigrated { user: user, pool: pool }))
)
(define-public (migrateFromVersion1 (pool principal))
(let (
(user tx-sender)
(from tx-sender)
(farm1_end_round (+ (contract-call? 'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275.stackswap-farming-v1l get-farm-end-cycle) u1))
(tempLPUserData (getLPUserDataOrDefault pool user))
(unclaimed_list (get unclaimedList (unwrap! (contract-call? 'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275.stackswap-farming-v1l get-staker from pool) (err ERR_NOTHING_TO_REDEEM))))
(current_round (+ (unwrap! (getRewardRound block-height) (err ERR_STAKING_NOT_AVAILABLE)) u1))
(start_round (if (> farm1_end_round current_round) farm1_end_round current_round))
(inversedList (cutSizedInverseList (+ (- (unwrap-panic (element-at unclaimed_list (- (len unclaimed_list) u1))) start_round) u1) start_round))
(migration_result (fold migrateFromVersion1Closure inversedList {
user: user,
from: from,
pool: pool,
amountLP: u0,
current: (unwrap! (getRewardRound block-height) (err ERR_STAKING_NOT_AVAILABLE)),
}))
)
;; (print {list: inversedList, start_round : start_round})
(asserts! (isFarmAvailable pool) (err ERR_POOL_NOT_ENROLLED))
(asserts! (isUserMigratable pool from) (err ERR_ALREADY_MIGRATED))
(map-set UserMigrated {user: from, pool: pool} true)
(map-set LPUserData
{pool: pool, user: user}
(merge tempLPUserData
{
unclaimedList : (unwrap! (addItemsToList (get unclaimedList tempLPUserData)
(+
(-
(unwrap-panic (element-at unclaimed_list (- (len unclaimed_list) u1)))
start_round)
u1)
start_round) (err ERR_UNSTAKELIST_FULL))})
)
(ok true)
)
)
(define-private (migrateFromVersion1Closure (round uint)
(commitment
{
user: principal,
from: principal,
pool: principal,
amountLP: uint,
current: uint,
}
))
(if (>= (get current commitment) round)
commitment
(let (
(farm_info (contract-call? 'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275.stackswap-farming-v1l get-staker-at-cycle round (get from commitment) (get pool commitment)))
(amountLP (match farm_info
res (+ (get toReturn res) (get amountLP commitment))
(get amountLP commitment)
))
)
(if (> amountLP u0)
(begin
(setTokensStaked (get user commitment) round amountLP u0 (get pool commitment))
(merge commitment {amountLP : amountLP})
)
commitment
)
)
)
)
(define-public (migrateFromVersion1Manual (pool principal) (from principal) (user principal))
(let (
(farm1_end_round (+ (contract-call? 'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275.stackswap-farming-v1l get-farm-end-cycle) u1))
(tempLPUserData (getLPUserDataOrDefault pool user))
(unclaimed_list (get unclaimedList (unwrap! (contract-call? 'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275.stackswap-farming-v1l get-staker from pool) (err ERR_NOTHING_TO_REDEEM))))
(current_round (+ (unwrap! (getRewardRound block-height) (err ERR_STAKING_NOT_AVAILABLE)) u1))
(start_round (if (> farm1_end_round current_round) farm1_end_round current_round))
(inversedList (cutSizedInverseList (+ (- (unwrap-panic (element-at unclaimed_list (- (len unclaimed_list) u1))) start_round) u1) start_round))
(migration_result (fold migrateFromVersion1Closure inversedList {
user: user,
from: from,
pool: pool,
amountLP: u0,
current: (unwrap! (getRewardRound block-height) (err ERR_STAKING_NOT_AVAILABLE)),
}))
)
(asserts! (is-eq contract-caller (contract-call? 'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275.stackswap-dao-v5k get-dao-owner)) (err ERR_PERMISSION_DENIED))
(asserts! (isFarmAvailable pool) (err ERR_POOL_NOT_ENROLLED))
(asserts! (isUserMigratable pool from) (err ERR_ALREADY_MIGRATED))
(map-set UserMigrated {user: from, pool: pool} true)
(map-set LPUserData
{pool: pool, user: user}
(merge tempLPUserData
{
unclaimedList : (unwrap! (addItemsToList (get unclaimedList tempLPUserData)
(+
(-
(unwrap-panic (element-at unclaimed_list (- (len unclaimed_list) u1)))
start_round)
u1)
start_round) (err ERR_UNSTAKELIST_FULL))})
)
(ok true)
)
)