-
Notifications
You must be signed in to change notification settings - Fork 13
/
stx-defi.clar
150 lines (136 loc) · 7.06 KB
/
stx-defi.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
;; Define the contract's data variables
;; Maps a user's principal address to their deposited amount.
(define-map deposits { owner: principal } { amount: uint })
;; Maps a borrower's principal address to their loan details: amount and the last interaction block.
(define-map loans principal { amount: uint, last-interaction-block: uint })
;; Holds the total amount of deposits in the contract, initialized to 0.
(define-data-var total-deposits uint u0)
;; Represents the reserve funds in the pool, initialized to 0.
(define-data-var pool-reserve uint u0)
;; The interest rate for loans, represented as 10% (out of a base of 100).
(define-data-var loan-interest-rate uint u10) ;; Representing 10% interest rate
;; Error constants for various failure scenarios.
(define-constant err-no-interest (err u100))
(define-constant err-overpay (err u200))
(define-constant err-overborrow (err u300))
;; Public function for users to deposit STX into the contract.
;; Updates their balance and the total deposits in the contract.
(define-public (deposit (amount uint))
(let (
;; Fetch the current balance or default to 0 if none exists.
(current-balance (default-to u0 (get amount (map-get? deposits { owner: tx-sender }))))
)
;; Transfer the STX from sender = "ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM" to recipient = "ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.stx-defi (ie: contract identifier on the chain!)".
(try! (stx-transfer? amount tx-sender (as-contract tx-sender)))
;; Update the user's deposit amount in the map.
(map-set deposits { owner: tx-sender } { amount: (+ current-balance amount) })
;; Update the total deposits variable.
(var-set total-deposits (+ (var-get total-deposits) amount))
;; Return success.
(ok true)
)
)
;; Public function for users to borrow STX based on their deposits.
(define-public (borrow (amount uint))
(let (
;; Fetch user's deposit or default to 0.
(user-deposit (default-to u0 (get amount (map-get? deposits { owner: tx-sender }))))
;; Calculate the maximum amount the user is allowed to borrow. (which will be upto HALF of what they deposited)
(allowed-borrow (/ user-deposit u2))
;; Fetch current loan details or default to initial values.
(current-loan-details (default-to { amount: u0, last-interaction-block: u0 } (map-get? loans tx-sender )))
;; Calculate accrued interest on the current loan.
(accrued-interest (calculate-accrued-interest (get amount current-loan-details) (get last-interaction-block current-loan-details)))
;; Calculate the total amount due including interest.
(total-due (+ (get amount current-loan-details) (unwrap-panic accrued-interest)))
;; Calculate the new loan total after borrowing additional amount.
(new-loan (+ amount))
)
;; Ensure the requested borrow amount does not exceed the allowed amount.
(asserts! (<= new-loan allowed-borrow) err-overborrow)
;; Transfer the borrowed STX to the user.
(let ((recipient tx-sender))
(try! (as-contract (stx-transfer? amount tx-sender recipient)))
)
;; Update the user's loan details in the map.
(map-set loans tx-sender { amount: new-loan, last-interaction-block: burn-block-height })
;; Return success.
(ok true)
)
)
;; Read-only function to get the total balance by tx-sender
(define-read-only (get-balance-by-sender)
(ok (map-get? deposits { owner: tx-sender }))
)
;; Read-only function to get the total balance
(define-read-only (get-balance)
(ok (var-get total-deposits))
)
;; Read-only function to get the total amount owed by the user.
(define-read-only (get-amount-owed)
(let (
;; Fetch current loan details or default to initial values.
(current-loan-details (default-to { amount: u0, last-interaction-block: u0 } (map-get? loans tx-sender )))
;; Calculate accrued interest on the current loan.
(accrued-interest (calculate-accrued-interest (get amount current-loan-details) (get last-interaction-block current-loan-details)))
;; Calculate the total amount due including interest.
(total-due (+ (get amount current-loan-details) (unwrap-panic accrued-interest)))
)
;; Return the total amount due.
(ok total-due)
)
)
;; Public function for users to repay their STX loans.
(define-public (repay (amount uint))
(let (
;; Fetch current loan details or default to initial values.
(current-loan-details (default-to { amount: u0, last-interaction-block: u0 } (map-get? loans tx-sender )))
;; Calculate accrued interest since the last interaction.
(accrued-interest (unwrap! (calculate-accrued-interest (get amount current-loan-details) (get last-interaction-block current-loan-details)) err-no-interest))
;; Calculate the total amount due including accrued interest.
(total-due (+ (get amount current-loan-details) accrued-interest))
)
;; Ensure the repayment amount is not more than the total due.
(asserts! (>= total-due amount) err-overpay)
;; Transfer the repayment amount from the user to the contract.
(try! (stx-transfer? amount tx-sender (as-contract tx-sender)))
;; Update the user's loan details in the map with the new total due.
(map-set loans tx-sender { amount: (- total-due amount), last-interaction-block: burn-block-height })
;; Update the pool reserve with the paid interest.
(var-set pool-reserve (+ (var-get pool-reserve) accrued-interest))
;; Return success.
(ok true)
)
)
;; Public function for users to claim their yield based on the pool reserve and their deposits.
(define-public (claim-yield)
(let (
;; Fetch user's deposit amount or default to 0.
(user-deposit (default-to u0 (get amount (map-get? deposits { owner: tx-sender }))))
;; Calculate the yield amount based on user's share of the pool.
(yield-amount (/ (* (var-get pool-reserve) user-deposit) (var-get total-deposits)))
)
;; Transfer the yield amount from the contract to the user.
(let ((recipient tx-sender))
(try! (as-contract (stx-transfer? yield-amount tx-sender recipient)))
)
;; Update the pool reserve by subtracting the claimed yield.
(var-set pool-reserve (- (var-get pool-reserve) yield-amount))
;; Return success.
(ok true)
)
)
;; Private function to calculate the accrued interest on a loan.
(define-private (calculate-accrued-interest (principal uint) (start-block uint))
(let (
;; Calculate the number of blocks elapsed since the last interaction.
(elapsed-blocks (- burn-block-height start-block))
;; Calculate the interest based on the principal, rate, and elapsed time.
(interest (/ (* principal (var-get loan-interest-rate) elapsed-blocks) u10000))
)
;; Ensure the loan started in the past (not at block 0).
(asserts! (not (is-eq start-block u0)) (ok u0))
;; Return the calculated interest.
(ok interest)
)
)