Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions pool/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

settings/Mainnet.toml
settings/Testnet.toml
history.txt
4 changes: 4 additions & 0 deletions pool/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

{
"deno.enable": true,
}
18 changes: 18 additions & 0 deletions pool/.vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

{
"version": "2.0.0",
"tasks": [
{
"label": "check contracts",
"group": "test",
"type": "shell",
"command": "clarinet check"
},
{
"label": "test contracts",
"group": "test",
"type": "shell",
"command": "clarinet test"
}
]
}
11 changes: 11 additions & 0 deletions pool/Clarinet.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[project]
name = "pool"
authors = []
description = ""
telemetry = true
requirements = []
analysis = ["check_checker"]
costs_version = 2
[contracts.credit-pool]
path = "contracts/credit-pool.clar"
depends_on = []
242 changes: 242 additions & 0 deletions pool/contracts/credit-pool.clar
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
;; Community Credit Pool Contract
;; Description: A secure smart contract for managing community credit advances with features for credit creation,
;; payback tracking, and pool management

;; Error codes
(define-constant ERR-ACCESS-DENIED (err u100))
(define-constant ERR-INVALID-SUM (err u101))
(define-constant ERR-INSUFFICIENT-BALANCE (err u102))
(define-constant ERR-CREDIT-NOT-FOUND (err u103))
(define-constant ERR-CREDIT-ALREADY-EXISTS (err u104))
(define-constant ERR-CREDIT-NOT-OPERATIONAL (err u105))
(define-constant ERR-PAYBACK-EXCEEDS-DEBT (err u106))
(define-constant ERR-INVALID-RATE (err u107))
(define-constant ERR-INVALID-DURATION (err u108))
(define-constant ERR-INVALID-TRANSACTION-ID (err u109))

;; Constants for validation
(define-constant MAX-RATE u5000) ;; 50% expressed as basis points
(define-constant MAX-DURATION u52560) ;; About 1 year in blocks (assuming 10-minute blocks)
(define-constant MIN-CREDIT-SUM u1000000) ;; Minimum credit amount in microSTX
(define-constant MAX-CREDIT-SUM u1000000000) ;; Maximum credit amount in microSTX

;; Data variables
(define-data-var pool-administrator principal tx-sender)
(define-data-var available-balance uint u0)
(define-data-var operational-credits uint u0)
(define-data-var next-transaction-id uint u0)

;; Contract status
(define-data-var pool-state (string-ascii 20) "OPERATIONAL")

;; Credit structure
(define-map credits
{ credit-id: uint }
{
recipient: principal,
sum: uint,
rate: uint,
duration: uint,
start-block: uint,
outstanding-debt: uint,
state: (string-ascii 20)
}
)

;; Payback history
(define-map paybacks
{ credit-id: uint, transaction-id: uint }
{
sum: uint,
block-height: uint,
timestamp: uint
}
)

;; Read-only functions

(define-read-only (get-credit-details (credit-id uint))
(map-get? credits { credit-id: credit-id })
)

(define-read-only (get-available-balance)
(ok (var-get available-balance))
)

(define-read-only (get-operational-credits)
(ok (var-get operational-credits))
)

(define-read-only (get-payback-history (credit-id uint) (transaction-id uint))
(map-get? paybacks { credit-id: credit-id, transaction-id: transaction-id })
)

(define-read-only (get-pool-state)
(ok (var-get pool-state))
)

;; Private functions

(define-private (is-pool-administrator)
(is-eq tx-sender (var-get pool-administrator))
)

(define-private (validate-credit-sum (sum uint))
(and
(>= sum MIN-CREDIT-SUM)
(<= sum MAX-CREDIT-SUM)
)
)

(define-private (validate-rate (rate uint))
(<= rate MAX-RATE)
)

(define-private (validate-duration (duration uint))
(<= duration MAX-DURATION)
)

(define-private (validate-transaction-id (transaction-id uint))
(< transaction-id (var-get next-transaction-id))
)

(define-private (update-available-balance (sum uint) (operation (string-ascii 10)))
(if (is-eq operation "add")
(var-set available-balance (+ (var-get available-balance) sum))
(var-set available-balance (- (var-get available-balance) sum))
)
)

;; Public functions

;; Initialize contract
(define-public (initialize-pool)
(begin
(asserts! (is-pool-administrator) ERR-ACCESS-DENIED)
(var-set pool-state "OPERATIONAL")
(var-set next-transaction-id u0)
(ok true)
)
)

;; Add funds to the contract
(define-public (deposit-funds (sum uint))
(begin
(asserts! (is-eq (var-get pool-state) "OPERATIONAL") ERR-CREDIT-NOT-OPERATIONAL)
(asserts! (validate-credit-sum sum) ERR-INVALID-SUM)
(try! (stx-transfer? sum tx-sender (as-contract tx-sender)))
(update-available-balance sum "add")
(ok true)
)
)

;; Create new loan
(define-public (issue-credit (credit-id uint)
(sum uint)
(rate uint)
(duration uint))
(begin
(asserts! (is-eq (var-get pool-state) "OPERATIONAL") ERR-CREDIT-NOT-OPERATIONAL)
(asserts! (validate-credit-sum sum) ERR-INVALID-SUM)
(asserts! (validate-rate rate) ERR-INVALID-RATE)
(asserts! (validate-duration duration) ERR-INVALID-DURATION)
(asserts! (<= sum (var-get available-balance)) ERR-INSUFFICIENT-BALANCE)
(asserts! (is-none (get-credit-details credit-id)) ERR-CREDIT-ALREADY-EXISTS)

(map-set credits
{ credit-id: credit-id }
{
recipient: tx-sender,
sum: sum,
rate: rate,
duration: duration,
start-block: block-height,
outstanding-debt: sum,
state: "OPERATIONAL"
}
)

(var-set operational-credits (+ (var-get operational-credits) u1))
(update-available-balance sum "subtract")
(ok true)
)
)

;; Make loan repayment
(define-public (make-payback (credit-id uint) (payback-sum uint))
(let ((credit (unwrap! (get-credit-details credit-id) ERR-CREDIT-NOT-FOUND))
(current-transaction-id (var-get next-transaction-id)))
(begin
(asserts! (is-eq (var-get pool-state) "OPERATIONAL") ERR-CREDIT-NOT-OPERATIONAL)
(asserts! (is-eq (get state credit) "OPERATIONAL") ERR-CREDIT-NOT-OPERATIONAL)
(asserts! (<= payback-sum (get outstanding-debt credit)) ERR-PAYBACK-EXCEEDS-DEBT)
(asserts! (validate-credit-sum payback-sum) ERR-INVALID-SUM)

;; Process payment
(try! (stx-transfer? payback-sum tx-sender (as-contract tx-sender)))

;; Update credit outstanding debt
(map-set credits
{ credit-id: credit-id }
(merge credit {
outstanding-debt: (- (get outstanding-debt credit) payback-sum),
state: (if (is-eq payback-sum (get outstanding-debt credit))
"SETTLED"
"OPERATIONAL")
})
)

;; Record payback with auto-incrementing transaction ID
(map-set paybacks
{ credit-id: credit-id, transaction-id: current-transaction-id }
{
sum: payback-sum,
block-height: block-height,
timestamp: block-height
}
)

;; Increment transaction ID counter
(var-set next-transaction-id (+ current-transaction-id u1))

;; Update contract state
(update-available-balance payback-sum "add")
(if (is-eq payback-sum (get outstanding-debt credit))
(var-set operational-credits (- (var-get operational-credits) u1))
true
)

(ok true)
)
)
)

;; Emergency functions (only pool administrator)

(define-public (halt-pool)
(begin
(asserts! (is-pool-administrator) ERR-ACCESS-DENIED)
(var-set pool-state "HALTED")
(ok true)
)
)

(define-public (reactivate-pool)
(begin
(asserts! (is-pool-administrator) ERR-ACCESS-DENIED)
(var-set pool-state "OPERATIONAL")
(ok true)
)
)

;; Calculate credit charges
(define-read-only (calculate-charges (principal-sum uint) (rate uint) (time uint))
(begin
(asserts! (validate-credit-sum principal-sum) ERR-INVALID-SUM)
(asserts! (validate-rate rate) ERR-INVALID-RATE)
(asserts! (validate-duration time) ERR-INVALID-DURATION)
(let ((charges (/ (* (* principal-sum rate) time) u100)))
(ok charges)
)
)
)
Loading