Source Code

(define-constant CONTRACT_OWNER tx-sender)
(define-constant ERR_NOT_AUTHORIZED (err u2000))
(define-constant ERR_INSUFFICIENT_RESERVE (err u2001))
(define-constant ERR_INVALID_TOKEN (err u2002))

(define-fungible-token basket-token)

(define-data-var total-reserve-value uint u0)
(define-data-var basket-count uint u0)

(define-map reserve-tokens
  uint
  {
    token-contract: principal,
    reserve-amount: uint,
    weight-percentage: uint
  }
)

(define-map user-deposits
  {user: principal, token-index: uint}
  uint
)

(define-read-only (get-contract-hash)
  (contract-hash? .basket-reserve-token)
)

(define-read-only (get-balance (account principal))
  (ok (ft-get-balance basket-token account))
)

(define-read-only (get-total-supply)
  (ok (ft-get-supply basket-token))
)

(define-read-only (get-reserve-token (index uint))
  (ok (map-get? reserve-tokens index))
)

(define-read-only (get-total-reserve-value)
  (ok (var-get total-reserve-value))
)

(define-public (add-reserve-token 
  (token-contract principal)
  (weight-percentage uint)
)
  (let
    (
      (index (var-get basket-count))
    )
    (asserts! (is-eq tx-sender CONTRACT_OWNER) ERR_NOT_AUTHORIZED)
    (map-set reserve-tokens index {
      token-contract: token-contract,
      reserve-amount: u0,
      weight-percentage: weight-percentage
    })
    (var-set basket-count (+ index u1))
    (ok index)
  )
)

(define-public (deposit-to-reserve (token-index uint) (amount uint))
  (let
    (
      (token-data (unwrap! (map-get? reserve-tokens token-index) ERR_INVALID_TOKEN))
      (current-deposit (default-to u0 (map-get? user-deposits {user: tx-sender, token-index: token-index})))
    )
    (map-set reserve-tokens token-index (merge token-data {
      reserve-amount: (+ (get reserve-amount token-data) amount)
    }))
    (map-set user-deposits 
      {user: tx-sender, token-index: token-index}
      (+ current-deposit amount)
    )
    (var-set total-reserve-value (+ (var-get total-reserve-value) amount))
    (ok true)
  )
)

(define-public (mint-basket-token (amount uint) (recipient principal))
  (let
    (
      (reserve-value (var-get total-reserve-value))
    )
    (asserts! (is-eq tx-sender CONTRACT_OWNER) ERR_NOT_AUTHORIZED)
    (asserts! (> reserve-value u0) ERR_INSUFFICIENT_RESERVE)
    (ft-mint? basket-token amount recipient)
  )
)

(define-public (redeem-for-reserves (amount uint))
  (let
    (
      (total-supply (ft-get-supply basket-token))
      (reserve-value (var-get total-reserve-value))
      (redemption-value (/ (* reserve-value amount) total-supply))
    )
    (asserts! (>= (ft-get-balance basket-token tx-sender) amount) ERR_INSUFFICIENT_RESERVE)
    (try! (ft-burn? basket-token amount tx-sender))
    (var-set total-reserve-value (- reserve-value redemption-value))
    (ok redemption-value)
  )
)

(define-public (rebalance-basket)
  (begin
    (asserts! (is-eq tx-sender CONTRACT_OWNER) ERR_NOT_AUTHORIZED)
    (ok true)
  )
)

(define-public (transfer (amount uint) (sender principal) (recipient principal))
  (begin
    (asserts! (is-eq tx-sender sender) ERR_NOT_AUTHORIZED)
    (ft-transfer? basket-token amount sender recipient)
  )
)

(define-read-only (calculate-redemption-value (amount uint))
  (let
    (
      (total-supply (ft-get-supply basket-token))
      (reserve-value (var-get total-reserve-value))
    )
    (if (> total-supply u0)
      (ok (/ (* reserve-value amount) total-supply))
      (ok u0)
    )
  )
)

(define-read-only (verify-signature (message (buff 32)) (signature (buff 64)) (public-key (buff 33)))
  (ok (secp256r1-verify message signature public-key))
)

(define-read-only (get-timestamp)
  stacks-block-height
)

(define-read-only (restrictions-check)
  (ok (is-ok (contract-hash? .basket-reserve-token)))
)

Functions (14)

FunctionAccessArgs
get-contract-hashread-only
get-balanceread-onlyaccount: principal
get-total-supplyread-only
get-reserve-tokenread-onlyindex: uint
get-total-reserve-valueread-only
deposit-to-reservepublictoken-index: uint, amount: uint
mint-basket-tokenpublicamount: uint, recipient: principal
redeem-for-reservespublicamount: uint
rebalance-basketpublic
transferpublicamount: uint, sender: principal, recipient: principal
calculate-redemption-valueread-onlyamount: uint
verify-signatureread-onlymessage: (buff 32
get-timestampread-only
restrictions-checkread-only