;; title: STXSynAssets
;; version:
;; summary:
;; description:
;; Error code
(define-constant ERROR-NOT-AUTHORIZED (err u100))
(define-constant ERROR-TOKEN-BALANCE-TOO-LOW (err u101))
(define-constant ERROR-INVALID-TOKEN-QUANTITY (err u102))
(define-constant ERROR-ORACLE-DATA-STALE (err u103))
(define-constant ERROR-COLLATERAL-DEPOSIT-INSUFFICIENT (err u104))
(define-constant ERROR-COLLATERAL-BELOW-THRESHOLD (err u105))
(define-constant ERROR-PRICE-OUT-OF-BOUNDS (err u106))
(define-constant ERROR-CALCULATION-OVERFLOW (err u107))
(define-constant ERROR-INVALID-TRANSFER-RECIPIENT (err u108))
(define-constant ERROR-AMOUNT-MUST-BE-POSITIVE (err u109))
(define-constant ERROR-VAULT-NOT-FOUND (err u110))
;; System constants
(define-constant SYSTEM-ADMIN tx-sender)
(define-constant PRICE-VALIDITY-PERIOD-BLOCKS u900) ;; 15 minutes in blocks
(define-constant COLLATERAL-SAFETY-RATIO u150) ;; 150%
(define-constant COLLATERAL-LIQUIDATION-RATIO u120) ;; 120%
(define-constant MIN-TOKEN-ISSUANCE-AMOUNT u100000000) ;; 1.00 tokens (8 decimals)
(define-constant MAX-ALLOWED-PRICE u1000000000000) ;; Price ceiling for safety
(define-constant UINT_MAX u340282366920938463463374607431768211455) ;; 2^128 - 1
;; Contract principal - UPDATE THIS after deployment with actual contract address
;; Example: 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.stx-collaatx
(define-constant CONTRACT-OWNER tx-sender)
;; System state variables
(define-data-var oracle-update-block-height uint u0)
(define-data-var current-market-price uint u0)
(define-data-var global-token-supply uint u0)
;; Data storage structures
(define-map user-token-holdings principal uint)
(define-map collateralized-positions
principal
{
staked-collateral: uint,
issued-synthetic-tokens: uint,
position-open-price: uint
}
)
;;;; Private Function
;; Internal helper functions
(define-private (process-token-transfer (sender principal) (receiver principal) (transfer-amount uint))
(let (
(sender-current-balance (get-user-token-balance sender))
)
;; Safety checks
(asserts! (> transfer-amount u0) ERROR-AMOUNT-MUST-BE-POSITIVE)
(asserts! (not (is-eq sender receiver)) ERROR-INVALID-TRANSFER-RECIPIENT)
(asserts! (>= sender-current-balance transfer-amount) ERROR-TOKEN-BALANCE-TOO-LOW)
(asserts! (is-some (map-get? user-token-holdings sender)) ERROR-NOT-AUTHORIZED)
(match (secure-add (get-user-token-balance receiver) transfer-amount)
receiver-new-balance
(match (secure-subtract sender-current-balance transfer-amount)
sender-new-balance
(begin
(map-set user-token-holdings sender sender-new-balance)
(map-set user-token-holdings receiver receiver-new-balance)
(ok true))
error ERROR-CALCULATION-OVERFLOW)
error ERROR-CALCULATION-OVERFLOW))
)
;; Protected arithmetic operations
(define-private (secure-multiply (value-a uint) (value-b uint))
(let ((product-result (* value-a value-b)))
(asserts! (or (is-eq value-a u0) (is-eq (/ product-result value-a) value-b)) ERROR-CALCULATION-OVERFLOW)
(ok product-result)))
(define-private (secure-add (value-a uint) (value-b uint))
(let ((sum-result (+ value-a value-b)))
(asserts! (>= sum-result value-a) ERROR-CALCULATION-OVERFLOW)
(ok sum-result)))
(define-private (secure-subtract (value-a uint) (value-b uint))
(begin
(asserts! (>= value-a value-b) ERROR-CALCULATION-OVERFLOW)
(ok (- value-a value-b))))
;; Query functions
(define-read-only (get-user-token-balance (account-holder principal))
(default-to u0 (map-get? user-token-holdings account-holder))
)
(define-read-only (get-circulating-supply)
(var-get global-token-supply)
)
(define-read-only (get-market-price)
(var-get current-market-price)
)
(define-read-only (get-position-details (position-owner principal))
(map-get? collateralized-positions position-owner)
)
(define-read-only (calculate-position-health-ratio (position-owner principal))
(let (
(position-data (unwrap! (get-position-details position-owner) (err u0)))
(latest-price (var-get current-market-price))
)
(if (> (get issued-synthetic-tokens position-data) u0)
(match (secure-multiply (get staked-collateral position-data) u100)
collateral-value-base (match (secure-multiply collateral-value-base u100)
collateral-value-adjusted (match (secure-multiply (get issued-synthetic-tokens position-data) latest-price)
synthetic-value (ok (/ collateral-value-adjusted synthetic-value))
error ERROR-CALCULATION-OVERFLOW)
error ERROR-CALCULATION-OVERFLOW)
error ERROR-CALCULATION-OVERFLOW)
(err u0)))
)
;;; PUBLIC FUNCTIONS ;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Helper function for contract to send STX (Clarity 4 compatible)
(define-private (contract-send-stx (amount uint) (recipient principal))
(stx-transfer? amount tx-sender recipient)
)
;; External functions
(define-public (set-price-feed-value (new-price uint))
(begin
(asserts! (is-eq tx-sender SYSTEM-ADMIN) ERROR-NOT-AUTHORIZED)
(asserts! (> new-price u0) ERROR-PRICE-OUT-OF-BOUNDS)
(asserts! (< new-price MAX-ALLOWED-PRICE) ERROR-PRICE-OUT-OF-BOUNDS)
(var-set current-market-price new-price)
(var-set oracle-update-block-height stacks-block-height)
(ok true))
)
(define-public (create-synthetic-tokens (token-amount uint))
(let (
(latest-market-price (var-get current-market-price))
)
(asserts! (> token-amount u0) ERROR-AMOUNT-MUST-BE-POSITIVE)
(asserts! (>= token-amount MIN-TOKEN-ISSUANCE-AMOUNT) ERROR-INVALID-TOKEN-QUANTITY)
(asserts! (<= (- stacks-block-height (var-get oracle-update-block-height))
PRICE-VALIDITY-PERIOD-BLOCKS)
ERROR-ORACLE-DATA-STALE)
(match (secure-multiply token-amount (/ latest-market-price u100))
base-collateral-needed
(match (secure-multiply base-collateral-needed (/ COLLATERAL-SAFETY-RATIO u100))
total-collateral-required
(match (stx-transfer? total-collateral-required tx-sender CONTRACT-OWNER)
transfer-success
(begin
(map-set collateralized-positions tx-sender
{
staked-collateral: total-collateral-required,
issued-synthetic-tokens: token-amount,
position-open-price: latest-market-price
})
(match (secure-add (get-user-token-balance tx-sender) token-amount)
updated-user-balance
(begin
(map-set user-token-holdings tx-sender updated-user-balance)
(match (secure-add (var-get global-token-supply) token-amount)
new-total-supply
(begin
(var-set global-token-supply new-total-supply)
(ok true))
error ERROR-CALCULATION-OVERFLOW))
error ERROR-CALCULATION-OVERFLOW))
error ERROR-COLLATERAL-DEPOSIT-INSUFFICIENT)
error ERROR-CALCULATION-OVERFLOW)
error ERROR-CALCULATION-OVERFLOW))
)
(define-public (destroy-synthetic-tokens (token-amount uint))
(let (
(position-data (unwrap! (get-position-details tx-sender)
ERROR-VAULT-NOT-FOUND))
(user-balance (get-user-token-balance tx-sender))
)
(asserts! (> token-amount u0) ERROR-AMOUNT-MUST-BE-POSITIVE)
(asserts! (>= user-balance token-amount) ERROR-TOKEN-BALANCE-TOO-LOW)
(asserts! (>= (get issued-synthetic-tokens position-data) token-amount)
ERROR-NOT-AUTHORIZED)
(match (secure-multiply (get staked-collateral position-data) token-amount)
collateral-calculation
(let (
(collateral-to-release (/ collateral-calculation
(get issued-synthetic-tokens position-data)))
)
;; Clarity 4: Removed as-contract. Contract must be authorized to send STX.
;; You may need to add authorization logic or use post-conditions.
(try! (stx-transfer? collateral-to-release CONTRACT-OWNER tx-sender))
(match (secure-subtract (get staked-collateral position-data)
collateral-to-release)
remaining-collateral
(match (secure-subtract (get issued-synthetic-tokens position-data)
token-amount)
remaining-tokens
(begin
(map-set collateralized-positions tx-sender
{
staked-collateral: remaining-collateral,
issued-synthetic-tokens: remaining-tokens,
position-open-price: (var-get current-market-price)
})
(match (secure-subtract user-balance token-amount)
new-user-balance
(begin
(map-set user-token-holdings tx-sender new-user-balance)
(match (secure-subtract (var-get global-token-supply)
token-amount)
new-total-supply
(begin
(var-set global-token-supply new-total-supply)
(ok true))
error ERROR-CALCULATION-OVERFLOW))
error ERROR-CALCULATION-OVERFLOW))
error ERROR-CALCULATION-OVERFLOW)
error ERROR-CALCULATION-OVERFLOW))
error ERROR-CALCULATION-OVERFLOW))
)
(define-public (send-synthetic-tokens (recipient principal) (amount uint))
(begin
;; Validation checks
(asserts! (> amount u0) ERROR-AMOUNT-MUST-BE-POSITIVE)
(asserts! (<= amount (get-user-token-balance tx-sender)) ERROR-TOKEN-BALANCE-TOO-LOW)
(asserts! (not (is-eq tx-sender recipient)) ERROR-INVALID-TRANSFER-RECIPIENT)
;; Process the transfer after validations
(process-token-transfer tx-sender recipient amount))
)
(define-public (add-collateral (collateral-amount uint))
(let (
(position-data (default-to
{
staked-collateral: u0,
issued-synthetic-tokens: u0,
position-open-price: u0
}
(get-position-details tx-sender)))
)
(asserts! (> collateral-amount u0) ERROR-AMOUNT-MUST-BE-POSITIVE)
(try! (stx-transfer? collateral-amount tx-sender CONTRACT-OWNER))
(match (secure-add (get staked-collateral position-data)
collateral-amount)
updated-collateral
(begin
(map-set collateralized-positions tx-sender
{
staked-collateral: updated-collateral,
issued-synthetic-tokens: (get issued-synthetic-tokens position-data),
position-open-price: (var-get current-market-price)
})
(ok true))
error ERROR-CALCULATION-OVERFLOW))
)
(define-public (force-close-position (position-owner principal))
(let (
(position-data (unwrap! (get-position-details position-owner)
ERROR-VAULT-NOT-FOUND))
(health-ratio (unwrap! (calculate-position-health-ratio position-owner)
ERROR-NOT-AUTHORIZED))
)
(asserts! (< health-ratio COLLATERAL-LIQUIDATION-RATIO)
ERROR-NOT-AUTHORIZED)
;; Transfer liquidated collateral to caller
;; Clarity 4: Removed as-contract. Contract must be authorized to send STX.
;; You may need to add authorization logic or use post-conditions.
(try! (stx-transfer? (get staked-collateral position-data) CONTRACT-OWNER tx-sender))
;; Remove the liquidated position
(map-delete collateralized-positions position-owner)
;; Remove tokens from circulation
(map-set user-token-holdings position-owner u0)
(match (secure-subtract (var-get global-token-supply)
(get issued-synthetic-tokens position-data))
updated-supply
(begin
(var-set global-token-supply updated-supply)
(ok true))
error ERROR-CALCULATION-OVERFLOW))
)