Source Code


;; nova-swap-engine.clar
;; A basic AMM-like swap contract for STX and a Nova Fungible Token.
;; CLARITY VERSION: 2

(use-trait nova-trait-fungible .nova-trait-fungible.nova-trait-fungible)

(define-constant ERR-NOT-AUTHORIZED (err u100))
(define-constant ERR-INVALID-LIQUIDITY (err u101))
(define-constant ERR-SLIPPAGE-EXCEEDED (err u102))

(define-data-var liquidity-stx uint u0)
(define-data-var liquidity-token uint u0)
(define-data-var fee-basis-points uint u30) ;; 0.3% fee

;; Provide initial liquidity
(define-public (provide-liquidity (stx-amount uint) (token-amount uint) (token-trait <nova-trait-fungible>))
    (let (
        (sender tx-sender)
    )
    (try! (stx-transfer? stx-amount sender (as-contract tx-sender)))
    (try! (contract-call? token-trait transfer token-amount sender (as-contract tx-sender) none))
    
    (var-set liquidity-stx (+ (var-get liquidity-stx) stx-amount))
    (var-set liquidity-token (+ (var-get liquidity-token) token-amount))
    (ok true))
)

;; Swap STX for Token
(define-public (swap-stx-for-token (stx-amount uint) (min-token-out uint) (token-trait <nova-trait-fungible>))
    (let (
        (stx-in-with-fee (* stx-amount (- u10000 (var-get fee-basis-points))))
        (stx-reserve (var-get liquidity-stx))
        (token-reserve (var-get liquidity-token))
        (numerator (* stx-in-with-fee token-reserve))
        (denominator (+ (* stx-reserve u10000) stx-in-with-fee))
        (token-out (/ numerator denominator))
        (sender tx-sender)
    )
    (asserts! (>= token-out min-token-out) ERR-SLIPPAGE-EXCEEDED)
    (asserts! (> token-out u0) ERR-INVALID-LIQUIDITY)

    (try! (stx-transfer? stx-amount sender (as-contract tx-sender)))
    (try! (as-contract (contract-call? token-trait transfer token-out tx-sender sender none)))

    (var-set liquidity-stx (+ stx-reserve stx-amount))
    (var-set liquidity-token (- token-reserve token-out))
    (ok token-out))
)

;; Swap Token for STX
(define-public (swap-token-for-stx (token-amount uint) (min-stx-out uint) (token-trait <nova-trait-fungible>))
    (let (
        (token-in-with-fee (* token-amount (- u10000 (var-get fee-basis-points))))
        (stx-reserve (var-get liquidity-stx))
        (token-reserve (var-get liquidity-token))
        (numerator (* token-in-with-fee stx-reserve))
        (denominator (+ (* token-reserve u10000) token-in-with-fee))
        (stx-out (/ numerator denominator))
        (sender tx-sender)
    )
    (asserts! (>= stx-out min-stx-out) ERR-SLIPPAGE-EXCEEDED)
    (asserts! (> stx-out u0) ERR-INVALID-LIQUIDITY)

    (try! (contract-call? token-trait transfer token-amount sender (as-contract tx-sender) none))
    (try! (as-contract (stx-transfer? stx-out tx-sender sender)))

    (var-set liquidity-token (+ token-reserve token-amount))
    (var-set liquidity-stx (- stx-reserve stx-out))
    (ok stx-out))
)

(define-read-only (get-liquidity)
    (ok {
        stx: (var-get liquidity-stx),
        token: (var-get liquidity-token)
    })
)

Functions (4)

FunctionAccessArgs
provide-liquiditypublicstx-amount: uint, token-amount: uint, token-trait: <nova-trait-fungible>
swap-stx-for-tokenpublicstx-amount: uint, min-token-out: uint, token-trait: <nova-trait-fungible>
swap-token-for-stxpublictoken-amount: uint, min-stx-out: uint, token-trait: <nova-trait-fungible>
get-liquidityread-only