Source Code

;; Faktory Fun
;; Buy with memecoins approved via Velar

(use-trait faktory-dex 'SP3XXMS38VTAWTVPE5682XSBFXPTH7XCPEBTX8AN2.faktory-dex-trait-v1.dex-trait) 
(use-trait faktory-token 'SP3XXMS38VTAWTVPE5682XSBFXPTH7XCPEBTX8AN2.faktory-trait-v1.sip-010-trait) 
(use-trait ft-trait 'SP2AKWJYC7BNY18W1XXKPGP0YVEK63QJG4793Z2D4.sip-010-trait-ft-standard.sip-010-trait)

;; Constants
(define-constant ERR-NOT-OWNER (err u401))
(define-constant ERR-ALREADY-ADDED (err u402))
(define-constant ERR-INSUFFICIENT-STX-OUT (err u403))
(define-constant ERR-INVALID-DEX (err u404))
(define-constant ERR-INVALID-TOKEN (err u405))
(define-constant ERR-NOT-FOUND (err u406))
(define-constant ERR-PATH-ALREADY-EXISTS (err u407))
(define-constant ERR-NO-PATH-FOR-TOKEN (err u408))

(define-data-var contract-owner principal tx-sender)
(define-private (check-owner)
  (ok (asserts! (is-eq contract-caller (var-get contract-owner)) ERR-NOT-OWNER)))

(define-public (set-owner (new-owner principal))
  (begin
    (try! (check-owner))
    (ok (var-set contract-owner new-owner))))

(define-read-only (get-owner)
  (var-get contract-owner))

(define-public (add-token (token principal))
  (begin
    (try! (check-owner))
    (asserts! (not (is-valid-token token)) ERR-ALREADY-ADDED)
    (ok (map-set valid-tokens token true))))

(define-public (remove-token (token principal))
  (begin
    (try! (check-owner))
    (asserts! (is-valid-token token) ERR-NOT-FOUND)
    (ok (map-delete valid-tokens token))))

(define-public (add-dex (dex principal))
  (begin
    (try! (check-owner))
    (asserts! (not (is-valid-dex dex)) ERR-ALREADY-ADDED)
    (ok (map-set valid-dexes dex true))))

(define-public (remove-dex (dex principal))
  (begin
    (try! (check-owner))
    (asserts! (is-valid-dex dex) ERR-NOT-FOUND)
    (ok (map-delete valid-dexes dex))))

;; Define allowed DEXes and tokens
(define-constant BATCH-1-DEXES
  (list 
    'SPV9K21TBFAK4KNRJXF5DFP8N7W46G4V9RCJDC22.bushcoin-faktory-dex 
  ))

(define-constant BATCH-1-TOKENS
  (list 
    'SPV9K21TBFAK4KNRJXF5DFP8N7W46G4V9RCJDC22.bushcoin-faktory 
  ))

;; Buy with memecoins approved
;; Token Constants
(define-constant LEO-TOKEN 'SP1AY6K3PQV5MRT6R4S671NWW2FRVPKM0BR162CT6.leo-token)
(define-constant PEPE-TOKEN 'SP1Z92MPDQEWZXW36VX71Q25HKF5K2EPCJ304F275.tokensoft-token-v4k68639zxz)
(define-constant ROO-TOKEN 'SP2C1WREHGM75C7TGFAEJPFKTFTEGZKF6DFT6E2GE.kangaroo)
(define-constant WELSH-TOKEN 'SP3NE50GEXFG9SZGTT51P40X2CKYSZ5CC4ZTZ7A2G.welshcorgicoin-token)
(define-constant WSTX-TOKEN 'SP1Y5YSTAHZ88XYK1VPDH24GY0HPX5J4JECTMY4A1.wstx)
(define-constant SHARE-FEE-TO 'SP1Y5YSTAHZ88XYK1VPDH24GY0HPX5J4JECTMY4A1.univ2-share-fee-to) 

(define-map token-paths 
  principal 
  {
    pool: principal,
    pool-id: uint
  }
)

(map-set token-paths LEO-TOKEN 
  {
    pool: 'SP1Y5YSTAHZ88XYK1VPDH24GY0HPX5J4JECTMY4A1.wstx-leo,
    pool-id: u28,
  })

(map-set token-paths PEPE-TOKEN 
  {
    pool: 'SP1Y5YSTAHZ88XYK1VPDH24GY0HPX5J4JECTMY4A1.wstx-pepe,
    pool-id: u11,
  })

(map-set token-paths ROO-TOKEN 
  {
    pool: 'SP1Y5YSTAHZ88XYK1VPDH24GY0HPX5J4JECTMY4A1.wstx-roo,
    pool-id: u15,
  })

(map-set token-paths WELSH-TOKEN 
  {
    pool: 'SP1Y5YSTAHZ88XYK1VPDH24GY0HPX5J4JECTMY4A1.wstx-welsh,
    pool-id: u27,
  })

;; Path management functions
(define-public (add-token-path 
    (token principal)
    (pool principal)
    (pool-id uint))
  (begin
    (try! (check-owner))
    (asserts! (is-none (map-get? token-paths token)) ERR-PATH-ALREADY-EXISTS)
    (ok (map-set token-paths token {
        pool: pool,
        pool-id: pool-id
    }))))

(define-public (remove-token-path (token principal))
  (begin
    (try! (check-owner))
    (ok (map-delete token-paths token))))

;; Read functions
(define-read-only (get-token-path (token principal))
  (map-get? token-paths token))

;; Helper to get path for token
(define-private (get-path (token principal))
  (match (map-get? token-paths token)
    path-data (ok (list 
      {   
        a: "u",  
        b: (get pool path-data),
        c: (get pool-id path-data),
        d: WSTX-TOKEN,
        e: token,
        f: false
      }))
    ERR-NO-PATH-FOR-TOKEN))

;; Maps for validation
(define-map valid-dexes principal bool)
(define-map valid-tokens principal bool)

;; Helper functions to initialize maps
(define-private (add-valid-dex (dex principal))
  (map-set valid-dexes dex true))

(define-private (add-valid-token (token principal))
  (map-set valid-tokens token true))

;; Validation functions
(define-read-only (is-valid-dex (dex principal))
  (default-to false (map-get? valid-dexes dex)))

(define-read-only (is-valid-token (token principal))
  (default-to false (map-get? valid-tokens token)))

(define-public (buy
    (token-amount uint)
    (token <ft-trait>) 
    (min-stx-out uint)
    (dex <faktory-dex>)
    (ft <faktory-token>))
        (let ((path (try! (get-path (contract-of token))))) 

        ;; Validate DEX and token
        (asserts! (is-valid-dex (contract-of dex)) ERR-INVALID-DEX)
        (asserts! (is-valid-token (contract-of ft)) ERR-INVALID-TOKEN)
        
        ;; Execute Velar swap
        (let ((swap-result 
            (try! (contract-call? 
                'SP20X3DC5R091J8B6YPQT638J8NR1W83KN6TN5BJY.path-apply_staging 
                apply
                path
                token-amount
                (some token)  
                (some WSTX-TOKEN)  ;; token2
                none none none
                (some SHARE-FEE-TO)
                none none none none ;; univ2v2-pools 1-4
                none none none none ;; univ2v2-fees 1-4
                none none none none ;; curve-pools 1-4
                none none none none ;; curve-fees 1-4
                none none none none ;; ststx-pools 1-4
                none none none none ;; ststx-proxies 1-4
            ))))
            
            (let ((stx-amount (get amt-out (get swap4 swap-result))))
                (asserts! (>= stx-amount min-stx-out) ERR-INSUFFICIENT-STX-OUT)
                
                ;; Use STX to buy from the provided DEX
                (try! (contract-call? 
                    dex
                    buy
                    ft
                    stx-amount))
                    
                (ok {
                    token-in: token-amount,
                    stx-amount: stx-amount
                })))))

;; Initialize maps
(begin
    (map add-valid-dex BATCH-1-DEXES)
    (map add-valid-token BATCH-1-TOKENS)
    (print "Generic DEX Proxy Contract initialized"))

Functions (16)

FunctionAccessArgs
add-dexpublicdex: principal
check-ownerprivate
set-ownerpublicnew-owner: principal
get-ownerread-only
add-tokenpublictoken: principal
remove-tokenpublictoken: principal
remove-dexpublicdex: principal
add-token-pathpublictoken: principal, pool: principal, pool-id: uint
remove-token-pathpublictoken: principal
get-token-pathread-onlytoken: principal
get-pathprivatetoken: principal
add-valid-dexprivatedex: principal
add-valid-tokenprivatetoken: principal
is-valid-dexread-onlydex: principal
is-valid-tokenread-onlytoken: principal
buypublictoken-amount: uint, token: <ft-trait>, min-stx-out: uint, dex: <faktory-dex>, ft: <faktory-token>