Source Code

;; NFT Rental Contract
;; Rent out NFTs for a specified duration

(define-constant err-not-owner (err u100))
(define-constant err-not-available (err u101))
(define-constant err-rental-active (err u102))
(define-constant err-rental-expired (err u103))

(define-data-var rental-nonce uint u0)

(define-map rentals
    uint
    {
        nft-contract: principal,
        token-id: uint,
        owner: principal,
        renter: (optional principal),
        price-per-block: uint,
        min-duration: uint,
        max-duration: uint,
        rental-start: (optional uint),
        rental-end: (optional uint),
        active: bool
    }
)

(define-public (list-for-rent
    (nft-contract principal)
    (token-id uint)
    (price-per-block uint)
    (min-duration uint)
    (max-duration uint))
    (let ((rental-id (var-get rental-nonce)))
        (map-set rentals rental-id {
            nft-contract: nft-contract,
            token-id: token-id,
            owner: tx-sender,
            renter: none,
            price-per-block: price-per-block,
            min-duration: min-duration,
            max-duration: max-duration,
            rental-start: none,
            rental-end: none,
            active: true
        })
        (var-set rental-nonce (+ rental-id u1))
        (ok rental-id)
    )
)

(define-public (rent-nft (rental-id uint) (duration uint))
    (let
        (
            (rental (unwrap! (map-get? rentals rental-id) err-not-available))
            (rental-cost (* (get price-per-block rental) duration))
            (rental-end (+ block-height duration))
        )
        (asserts! (get active rental) err-not-available)
        (asserts! (is-none (get renter rental)) err-rental-active)
        (asserts! (>= duration (get min-duration rental)) err-not-available)
        (asserts! (<= duration (get max-duration rental)) err-not-available)
        
        (try! (stx-transfer? rental-cost tx-sender (get owner rental)))
        
        (map-set rentals rental-id (merge rental {
            renter: (some tx-sender),
            rental-start: (some block-height),
            rental-end: (some rental-end)
        }))
        (ok rental-end)
    )
)

(define-public (return-nft (rental-id uint))
    (let ((rental (unwrap! (map-get? rentals rental-id) err-not-available)))
        (asserts! (is-eq (some tx-sender) (get renter rental)) err-not-owner)
        (map-set rentals rental-id (merge rental {
            renter: none,
            rental-start: none,
            rental-end: none
        }))
        (ok true)
    )
)

(define-read-only (get-rental (rental-id uint))
    (map-get? rentals rental-id)
)

(define-read-only (is-rental-active (rental-id uint))
    (match (map-get? rentals rental-id)
        rental (match (get rental-end rental)
            end-block (> end-block block-height)
            false)
        false)
)

Functions (5)

FunctionAccessArgs
list-for-rentpublicnft-contract: principal, token-id: uint, price-per-block: uint, min-duration: uint, max-duration: uint
rent-nftpublicrental-id: uint, duration: uint
return-nftpublicrental-id: uint
get-rentalread-onlyrental-id: uint
is-rental-activeread-onlyrental-id: uint