Source Code

;; title: wrapped-token-manager
;; version: 1.0.0
;; summary: Wrapped token management
;; description: Manage wrapped assets (wBTC, wETH, etc) - Clarity 4

;; Constants
(define-constant CONTRACT-OWNER tx-sender)
(define-constant ERR-UNAUTHORIZED (err u6400))
(define-constant ERR-INSUFFICIENT-BALANCE (err u6401))

;; Data Variables
(define-data-var total-wrapped uint u0)
(define-data-var total-unwrapped uint u0)

;; Data Maps - Using stacks-block-time for Clarity 4
(define-map wrapped-balances { user: principal, token: principal } {
  balance: uint,
  last-updated: uint  ;; Clarity 4: Unix timestamp
})

(define-map wrap-history uint {
  user: principal,
  token: principal,
  amount: uint,
  action: (string-ascii 10),  ;; "wrap" or "unwrap"
  timestamp: uint  ;; Clarity 4: Unix timestamp
})

(define-map supported-tokens principal {
  is-supported: bool,
  wrap-fee: uint,  ;; Basis points
  unwrap-fee: uint,
  total-wrapped: uint
})

(define-data-var next-wrap-id uint u1)

;; Public Functions

(define-public (wrap-token (token principal) (amount uint))
  (let (
    (wrap-id (var-get next-wrap-id))
    (token-data (unwrap! (map-get? supported-tokens token) (err u404)))
    (current-balance (default-to
      { balance: u0, last-updated: u0 }
      (map-get? wrapped-balances { user: tx-sender, token: token })))
  )
    (asserts! (get is-supported token-data) (err u400))

    (map-set wrapped-balances { user: tx-sender, token: token } {
      balance: (+ (get balance current-balance) amount),
      last-updated: stacks-block-time
    })

    (map-set wrap-history wrap-id {
      user: tx-sender,
      token: token,
      amount: amount,
      action: "wrap",
      timestamp: stacks-block-time
    })

    (var-set next-wrap-id (+ wrap-id u1))
    (var-set total-wrapped (+ (var-get total-wrapped) amount))

    (print {
      event: "token-wrapped",
      wrap-id: wrap-id,
      token: token,
      amount: amount,
      timestamp: stacks-block-time
    })

    (ok wrap-id)
  )
)

(define-public (unwrap-token (token principal) (amount uint))
  (let (
    (wrap-id (var-get next-wrap-id))
    (current-balance (unwrap! (map-get? wrapped-balances { user: tx-sender, token: token }) ERR-INSUFFICIENT-BALANCE))
  )
    (asserts! (>= (get balance current-balance) amount) ERR-INSUFFICIENT-BALANCE)

    (map-set wrapped-balances { user: tx-sender, token: token } {
      balance: (- (get balance current-balance) amount),
      last-updated: stacks-block-time
    })

    (map-set wrap-history wrap-id {
      user: tx-sender,
      token: token,
      amount: amount,
      action: "unwrap",
      timestamp: stacks-block-time
    })

    (var-set next-wrap-id (+ wrap-id u1))
    (var-set total-unwrapped (+ (var-get total-unwrapped) amount))

    (ok wrap-id)
  )
)

(define-public (add-supported-token
  (token principal)
  (wrap-fee uint)
  (unwrap-fee uint))
  (begin
    (asserts! (is-eq tx-sender CONTRACT-OWNER) ERR-UNAUTHORIZED)

    (map-set supported-tokens token {
      is-supported: true,
      wrap-fee: wrap-fee,
      unwrap-fee: unwrap-fee,
      total-wrapped: u0
    })

    (ok true)
  )
)

;; Read-Only Functions

(define-read-only (get-wrapped-balance (user principal) (token principal))
  (map-get? wrapped-balances { user: user, token: token })
)

(define-read-only (get-wrap-history (wrap-id uint))
  (map-get? wrap-history wrap-id)
)

(define-read-only (is-token-supported (token principal))
  (match (map-get? supported-tokens token)
    data (get is-supported data)
    false
  )
)

Functions (6)

FunctionAccessArgs
wrap-tokenpublictoken: principal, amount: uint
unwrap-tokenpublictoken: principal, amount: uint
add-supported-tokenpublictoken: principal, wrap-fee: uint, unwrap-fee: uint
get-wrapped-balanceread-onlyuser: principal, token: principal
get-wrap-historyread-onlywrap-id: uint
is-token-supportedread-onlytoken: principal