bme032-0-scalar-strategy-hedge

SP3Y12HJYP2NMNAFHWBPM2CMYDHYXME1F45GASVBG

Source Code

;; Title: BME032 Strategy for scalar market hedging
;; Synopsis:
;; Provides a hook for scalar markets to run hedging function during cool down.
;; Description:
;; The idea is to create an algorithmic hedge fund - we assume the community 
;; surfaces the winning outcome and swap treasury tokens in response. The contractcalls the 
;; the treasury with the form/to token contracts and works out the direction bearish/bullish
;; of the signal together with the signal strength strong/medium/weak. 

(impl-trait 'SP22NW0RYCW4GFZRPE8VGJRCKGQMRMMX4903A2TRG.hedge-trait.hedge-trait)
(use-trait ft-velar-token 'SP2AKWJYC7BNY18W1XXKPGP0YVEK63QJG4793Z2D4.sip-010-trait-ft-standard.sip-010-trait)

(define-constant err-unauthorised (err u32000))
(define-constant err-already-hedged (err u32001))
(define-constant err-already-executed (err u32002))
(define-constant err-hedge-not-found (err u32003))
(define-constant err-token-incorrect (err u32004))
(define-constant err-pair-not-found (err u32005))
(define-constant err-cooldown (err u32006))
(define-constant err-amount-zero (err u32007))
(define-constant err-slippage (err u32008))
(define-constant err-invalid-amount (err u32009))

(define-data-var hedge-market-contract principal .bme024-0-market-predicting)
(define-data-var hedge-scalar-contract principal .bme024-0-market-scalar-pyth)
(define-data-var hedge-multipliers (list 6 uint) (list u750 u500 u250 u250 u500 u750))
(define-data-var max-hedge-bips uint u1000)      ;; hard cap per trade = 10% of balance
(define-data-var max-hedge-abs  uint u0)         ;; optional absolute cap (0 = disabled)
(define-data-var min-trade      uint u0)         ;; optional minimum trade size (0 = disabled)
(define-data-var per-market-cooldown uint u144)  ;; ~1 day (tune as needed)
(define-data-var per-trade-slippage uint u300)   ;; 3% default for hedges (stricter than treasury 5%)

(define-map last-hedge-height {market-id:uint} uint)  ;; anti-replay

(define-map swap-token-pairs (buff 32) {token-in: principal, token-out: principal, token0: principal, token1: principal})
(define-map hedges
  uint
  {executed: bool, feed-id: (buff 32)}
)

(define-public (is-dao-or-extension)
	(ok (asserts! (or (is-eq tx-sender .bigmarket-dao) (contract-call? .bigmarket-dao is-extension contract-caller)) err-unauthorised)))

(define-public (set-hedge-multipliers (multipliers (list 6 uint)))
  (begin
    (try! (is-dao-or-extension))
    (var-set hedge-multipliers multipliers)
    (print {event: "hedge-multipliers", multipliers: multipliers})
    (ok true)
  )
)

(define-public (set-hedge-market-contract (market-contract principal))
  (begin
    (try! (is-dao-or-extension))
    (var-set hedge-market-contract market-contract)
    (print {event: "hedge-market-contract", market-contract: market-contract})
    (ok true)
  )
)

(define-public (set-hedge-scalar-contract (market-contract principal))
  (begin
    (try! (is-dao-or-extension))
    (var-set hedge-scalar-contract market-contract)
    (print {event: "hedge-scalar-contract", market-contract: market-contract})
    (ok true)
  )
)

(define-public (set-hedge-caps (bips uint) (abs uint))
  (begin (try! (is-dao-or-extension))
         (asserts! (<= bips u5000) err-invalid-amount) ;; <=50%
         (var-set max-hedge-bips bips)
         (var-set max-hedge-abs  abs)
         (ok true)))

(define-public (set-hedge-min-trade (min uint))
  (begin (try! (is-dao-or-extension)) (var-set min-trade min) (ok true)))

(define-public (set-hedge-cooldown (blocks uint))
  (begin (try! (is-dao-or-extension)) (var-set per-market-cooldown blocks) (ok true)))

(define-public (set-hedge-slippage (bips uint))
  (begin (try! (is-dao-or-extension))
         (asserts! (and (>= bips u1) (<= bips u3000)) err-invalid-amount)
         (var-set per-trade-slippage bips) (ok true)))

(define-public (set-swap-token-pair
  (feed-id (buff 32))
  (token-a principal)
  (token-b principal)
  (token-in principal)
  (token-out principal))
  (begin
    (try! (is-dao-or-extension))
    ;; Check token-in is one of token-a or token-b
    (asserts! (or (is-eq token-in token-a) (is-eq token-in token-b)) err-token-incorrect)
    ;; Check token-out is the other one
    (asserts! (or (is-eq token-out token-a) (is-eq token-out token-b)) err-token-incorrect)
    (asserts! (not (is-eq token-in token-out)) err-token-incorrect)

    ;; Lexicographic ordering
    (let (
      (buff-a (unwrap! (to-consensus-buff? token-a) err-token-incorrect))
      (buff-b (unwrap! (to-consensus-buff? token-b) err-token-incorrect))
      (token0 (if (< buff-a buff-b) token-a token-b))
      (token1 (if (< buff-a buff-b) token-b token-a))

    )
      (map-set swap-token-pairs
        feed-id
        {
          token-in: token-in,
          token-out: token-out,
          token0: token0,
          token1: token1
        })
      (print {event: "swap-token-pair", feed-id: feed-id, token-in: token-in, token-out: token-out, token0: token0, token1: token1})
      (ok true)
    )
  )
)

(define-read-only (get-swap-token-pair (feed-id (buff 32)))
	(map-get? swap-token-pairs feed-id)
)

(define-public (perform-swap-hedge
  (market-id uint) (predicted-index uint) (feed-id (buff 32))
  (token0 <ft-velar-token>) (token1 <ft-velar-token>)
  (token-in <ft-velar-token>) (token-out <ft-velar-token>)
)
  (let (
    (pair (unwrap! (map-get? swap-token-pairs feed-id) err-pair-not-found))
    (is-bearish (< predicted-index u3))
    (expected-in  (if is-bearish (get token-in pair)  (get token-out pair)))
    (expected-out (if is-bearish (get token-out pair) (get token-in pair)))
    (lh (default-to u0 (map-get? last-hedge-height {market-id: market-id})))
    (cool (var-get per-market-cooldown))
  )
    ;; auth + source contract check
    (try! (is-dao-or-extension))
    (asserts! (is-eq contract-caller (var-get hedge-scalar-contract)) err-unauthorised)

    ;; one-shot safety: refuse if this market was already hedged here
    (asserts! (is-none (map-get? hedges market-id)) err-already-executed)

    ;; cooldown even if another component tries to hedge repeatedly
    (if (> lh u0)
      (asserts! (> stacks-block-height (+ lh cool)) err-cooldown)
      true
    )

    ;; pair validation: enforce tokens match configured direction
    (asserts! (is-eq (contract-of token-in)  expected-in)  err-token-incorrect)
    (asserts! (is-eq (contract-of token-out) expected-out) err-token-incorrect)

    ;; compute bounded amount
    (let (
      (balance (unwrap! (contract-call? token-in get-balance .bme006-0-treasury) err-unauthorised))
      (bips-mult (unwrap! (element-at? (var-get hedge-multipliers) predicted-index) err-token-incorrect)) ;; e.g., 750 = 7.5%
      (cap-bips (var-get max-hedge-bips))
      (bips (if (> bips-mult cap-bips) cap-bips bips-mult))
      (raw (/ (* balance bips) u10000))
      (abs-cap (var-get max-hedge-abs))
      (amt (if (and (> abs-cap u0) (> raw abs-cap)) abs-cap raw))
      (min-size (var-get min-trade))
    )
      (asserts! (> amt u0) err-amount-zero)
      (if (> min-size u0) (asserts! (>= amt min-size) err-amount-zero) true)

      ;; do the swap with stricter slippage than treasury default
      (let ((slip (var-get per-trade-slippage)))
        (asserts! (and (>= slip u1) (<= slip u3000)) err-slippage)
        (try! (contract-call? .bme006-0-treasury swap-tokens-with-slippage
              token0 token1 token-in token-out amt slip))
      )

      ;; record hedge + height
      (map-set hedges market-id {executed: true, feed-id: feed-id})
      (map-set last-hedge-height {market-id: market-id} stacks-block-height)
      (print {event:"perform-swap-hedge", market-id: market-id, predicted: predicted-index, feed-id: feed-id, amount: amt})
      (ok true)
    )
  )
)

;; can be implemented in later contract
(define-public (perform-custom-hedge (market-id uint) (predicted-index uint))
  (begin 
    ;; caller must be both an ACTIVE extension and sepecifically the scalar prediction market
    (try! (is-dao-or-extension))
    (asserts! (is-eq contract-caller (var-get hedge-market-contract)) err-unauthorised)
    (print {event: "perform-custom-hedge", market-id: market-id, predicted: predicted-index})
    (ok true)
  )
)

(define-private (compute-swap-amount (token <ft-velar-token>) (index uint))
  (let (
      (balance (unwrap! (contract-call? token get-balance .bme006-0-treasury) err-unauthorised))
      (bips (unwrap! (element-at? (var-get hedge-multipliers) index) err-token-incorrect))
      (amt (/ (* balance bips) u10000))
    )
    (ok amt)
  )
)

Functions (13)

FunctionAccessArgs
is-dao-or-extensionpublic
set-hedge-multiplierspublicmultipliers: (list 6 uint
set-hedge-market-contractpublicmarket-contract: principal
set-hedge-scalar-contractpublicmarket-contract: principal
set-hedge-capspublicbips: uint, abs: uint
set-hedge-min-tradepublicmin: uint
set-hedge-cooldownpublicblocks: uint
set-hedge-slippagepublicbips: uint
set-swap-token-pairpublicfeed-id: (buff 32
get-swap-token-pairread-onlyfeed-id: (buff 32
perform-swap-hedgepublicmarket-id: uint, predicted-index: uint, feed-id: (buff 32
perform-custom-hedgepublicmarket-id: uint, predicted-index: uint
compute-swap-amountprivatetoken: <ft-velar-token>, index: uint