Source Code

(define-constant CONTRACT_OWNER tx-sender)
(define-constant ERR_NOT_AUTHORIZED (err u1400))
(define-constant ERR_NFT_NOT_FOUND (err u1401))
(define-constant ERR_INSUFFICIENT_FRACTIONAL (err u1402))

(define-non-fungible-token fractional-nft uint)
(define-fungible-token fractional-token)

(define-data-var next-nft-id uint u1)
(define-data-var reserve-ratio uint u100)

(define-map nft-metadata
  uint
  {
    owner: principal,
    total-fractional: uint,
    created-at: uint
  }
)

(define-map segregated-accounts
  principal
  {fractional-balance: uint, nft-held: (optional uint)}
)

(define-read-only (get-contract-hash)
  (contract-hash? .fractional-nft)
)

(define-read-only (get-nft-owner (nft-id uint))
  (ok (nft-get-owner? fractional-nft nft-id))
)

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

(define-read-only (balance-of-fractional (account principal))
  (let
    (
      (account-data (default-to {fractional-balance: u0, nft-held: none} (map-get? segregated-accounts account)))
    )
    (ok (get fractional-balance account-data))
  )
)

(define-public (mint-nft (to principal))
  (let
    (
      (nft-id (var-get next-nft-id))
    )
    (try! (nft-mint? fractional-nft nft-id to))
    (map-set nft-metadata nft-id {
      owner: to,
      total-fractional: u0,
      created-at: stacks-block-time
    })
    (var-set next-nft-id (+ nft-id u1))
    (ok nft-id)
  )
)

(define-public (fractional-reserve-mint (amount uint) (recipient principal))
  (begin
    (asserts! (is-eq tx-sender CONTRACT_OWNER) ERR_NOT_AUTHORIZED)
    (try! (ft-mint? fractional-token amount recipient))
    (let
      (
        (account-data (default-to {fractional-balance: u0, nft-held: none} (map-get? segregated-accounts recipient)))
      )
      (map-set segregated-accounts recipient (merge account-data {
        fractional-balance: (+ (get fractional-balance account-data) amount)
      }))
    )
    (ok true)
  )
)

(define-public (fractional-reserve-burn (amount uint))
  (let
    (
      (account-data (default-to {fractional-balance: u0, nft-held: none} (map-get? segregated-accounts tx-sender)))
    )
    (asserts! (>= (get fractional-balance account-data) amount) ERR_INSUFFICIENT_FRACTIONAL)
    (try! (ft-burn? fractional-token amount tx-sender))
    (map-set segregated-accounts tx-sender (merge account-data {
      fractional-balance: (- (get fractional-balance account-data) amount)
    }))
    (ok true)
  )
)

(define-public (deposit-nft-for-fractional (nft-id uint) (fractional-amount uint))
  (let
    (
      (nft-data (unwrap! (map-get? nft-metadata nft-id) ERR_NFT_NOT_FOUND))
      (account-data (default-to {fractional-balance: u0, nft-held: none} (map-get? segregated-accounts tx-sender)))
    )
    (asserts! (is-eq (get owner nft-data) tx-sender) ERR_NOT_AUTHORIZED)
    (try! (nft-transfer? fractional-nft nft-id tx-sender CONTRACT_OWNER))
    (try! (ft-mint? fractional-token fractional-amount tx-sender))
    (map-set segregated-accounts tx-sender (merge account-data {
      fractional-balance: (+ (get fractional-balance account-data) fractional-amount),
      nft-held: (some nft-id)
    }))
    (ok true)
  )
)

(define-public (withdraw-nft-for-fractional (nft-id uint) (fractional-amount uint))
  (let
    (
      (account-data (unwrap! (map-get? segregated-accounts tx-sender) ERR_NOT_AUTHORIZED))
    )
    (asserts! (is-eq (get nft-held account-data) (some nft-id)) ERR_NOT_AUTHORIZED)
    (asserts! (>= (get fractional-balance account-data) fractional-amount) ERR_INSUFFICIENT_FRACTIONAL)
    (try! (ft-burn? fractional-token fractional-amount tx-sender))
    (try! (nft-transfer? fractional-nft nft-id CONTRACT_OWNER tx-sender))
    (map-set segregated-accounts tx-sender (merge account-data {
      fractional-balance: (- (get fractional-balance account-data) fractional-amount),
      nft-held: none
    }))
    (ok true)
  )
)

(define-read-only (verify-r1-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-time
)

(define-read-only (check-asset-restrictions)
  (ok (is-ok (contract-hash? .fractional-nft)))
)

Functions (12)

FunctionAccessArgs
get-contract-hashread-only
get-nft-ownerread-onlynft-id: uint
get-fractional-balanceread-onlyaccount: principal
balance-of-fractionalread-onlyaccount: principal
mint-nftpublicto: principal
fractional-reserve-mintpublicamount: uint, recipient: principal
fractional-reserve-burnpublicamount: uint
deposit-nft-for-fractionalpublicnft-id: uint, fractional-amount: uint
withdraw-nft-for-fractionalpublicnft-id: uint, fractional-amount: uint
verify-r1-signatureread-onlymessage: (buff 32
get-timestampread-only
check-asset-restrictionsread-only