Source Code

;; Auction Smart Contract

;; title: stx-auction
;; version:
;; summary:
;; description:
;; Error codes
(define-constant ERR-NOT-AUTHORIZED (err u100))
(define-constant ERR-AUCTION-ALREADY-STARTED (err u101))
(define-constant ERR-AUCTION-NOT-STARTED (err u102))
(define-constant ERR-AUCTION-ENDED (err u103))
(define-constant ERR-BID-TOO-LOW (err u104))
(define-constant ERR-TRANSFER-FAILED (err u105))
(define-constant ERR-AUCTION-NOT-ENDED (err u106))
(define-constant ERR-NO-BIDS (err u107))
(define-constant ERR-INVALID-DURATION (err u108))
(define-constant ERR-RESERVE-NOT-MET (err u109))
(define-constant ERR-AUCTION-IN-PROGRESS (err u110))
(define-constant ERR-INVALID-NAME-LENGTH (err u111))
(define-constant ERR-INVALID-RESERVE-PRICE (err u112))

;; traits
;;
;; Define the data for the auction
(define-data-var top-bid uint u0)
(define-data-var top-bidder (optional principal) none)
(define-data-var auction-start-block uint u0)
(define-data-var auction-end-block uint u0)
(define-data-var owner principal tx-sender)
(define-data-var item-name (string-ascii 50) "")
(define-data-var reserve-price uint u0)

;; Map to track escrowed bids
(define-map escrowed-bids principal uint)

;; token definitions
;;
;; Define a constant for minimum bid increment
(define-constant BID-STEP u1000000) ;; 1 STX

;; constants
;;
;; Function to start the auction
(define-public (initialize-auction (duration uint) (name (string-ascii 50)) (min-price uint))
  (begin
    ;; Check that the sender is authorized
    (asserts! (is-eq tx-sender (var-get owner)) ERR-NOT-AUTHORIZED)
    ;; Check that the auction hasn't started yet
    (asserts! (is-eq (var-get auction-start-block) u0) ERR-AUCTION-ALREADY-STARTED)
    ;; Check that the duration is valid
    (asserts! (> duration u0) ERR-INVALID-DURATION)
    ;; Check that the item name is not empty and is within the 50-character limit
    (asserts! (> (len name) u0) ERR-INVALID-NAME-LENGTH)
    (asserts! (<= (len name) u50) ERR-INVALID-NAME-LENGTH)
    ;; Check that the minimum price is positive
    (asserts! (> min-price u0) ERR-INVALID-RESERVE-PRICE)
    ;; Initialize auction variables
    (var-set auction-start-block stacks-block-time)
    (var-set auction-end-block (+ stacks-block-time duration))
    (var-set item-name name)
    (var-set reserve-price min-price)
    (ok true)))

;; data vars
;;
;; Function to place a bid
(define-public (submit-bid (offer uint))
  (let (
    (current-offer (var-get top-bid))
    (min-valid-bid (if (> current-offer (var-get reserve-price))
                       (+ current-offer BID-STEP)
                       (var-get reserve-price))))
    ;; Ensure auction has started
    (asserts! (>= stacks-block-time (var-get auction-start-block)) ERR-AUCTION-NOT-STARTED)
    ;; Ensure auction has been initialized
    (asserts! (> (var-get auction-start-block) u0) ERR-AUCTION-NOT-STARTED)
    ;; Ensure auction hasn't ended
    (asserts! (< stacks-block-time (var-get auction-end-block)) ERR-AUCTION-ENDED)
    ;; Ensure bid is valid
    (asserts! (>= offer min-valid-bid) ERR-BID-TOO-LOW)
    ;; Transfer the new bid to contract owner (acts as escrow)
    (try! (stx-transfer? offer tx-sender (var-get owner)))
    ;; Refund previous bidder if exists
    (match (var-get top-bidder)
      previous-leader
        (begin
          ;; Owner refunds the previous bid
          (try! (stx-transfer? current-offer (var-get owner) previous-leader))
          (map-delete escrowed-bids previous-leader)
          (map-set escrowed-bids tx-sender offer)
          (var-set top-bid offer)
          (var-set top-bidder (some tx-sender))
          (ok true))
      (begin
        ;; First bid - just record it
        (map-set escrowed-bids tx-sender offer)
        (var-set top-bid offer)
        (var-set top-bidder (some tx-sender))
        (ok true)))))

;; data maps
;;
;; Function to end the auction and finalize the winner
(define-public (conclude-auction)
  (begin
    ;; Ensure auction has ended
    (asserts! (>= stacks-block-time (var-get auction-end-block)) ERR-AUCTION-NOT-ENDED)
    ;; Ensure there's a valid bid
    (asserts! (is-some (var-get top-bidder)) ERR-NO-BIDS)
    ;; Ensure reserve price is met
    (asserts! (>= (var-get top-bid) (var-get reserve-price)) ERR-RESERVE-NOT-MET)
    ;; Owner already has the winning bid from submit-bid
    ;; Clear the escrowed bid entry for the winner
    (match (var-get top-bidder)
      auction-winner
        (begin
          (map-delete escrowed-bids auction-winner)
          (ok true))
      ERR-NO-BIDS)))

;; public functions
;;
;; Function to cancel the auction (only by owner, only if no bids)
(define-public (cancel-auction)
  (begin
    ;; Check if sender is owner
    (asserts! (is-eq tx-sender (var-get owner)) ERR-NOT-AUTHORIZED)
    ;; Check that no bids have been placed
    (asserts! (is-none (var-get top-bidder)) ERR-AUCTION-IN-PROGRESS)
    ;; Reset auction data
    (var-set auction-start-block u0)
    (var-set auction-end-block u0)
    (var-set top-bid u0)
    (var-set top-bidder none)
    (ok true)))

;; read only functions
;;
;; Read-only functions
(define-read-only (query-top-bid)
  (ok (var-get top-bid)))

;; private functions
;;
(define-read-only (query-top-bidder)
  (ok (var-get top-bidder)))

(define-read-only (query-auction-end)
  (ok (var-get auction-end-block)))

(define-read-only (query-item-name)
  (ok (var-get item-name)))

(define-read-only (query-reserve-price)
  (ok (var-get reserve-price)))

(define-read-only (query-auction-status)
  (if (< stacks-block-time (var-get auction-start-block))
      (ok "Not started")
      (if (< stacks-block-time (var-get auction-end-block))
          (ok "In progress")
          (ok "Ended"))))

Functions (10)

FunctionAccessArgs
initialize-auctionpublicduration: uint, name: (string-ascii 50
submit-bidpublicoffer: uint
conclude-auctionpublic
cancel-auctionpublic
query-top-bidread-only
query-top-bidderread-only
query-auction-endread-only
query-item-nameread-only
query-reserve-priceread-only
query-auction-statusread-only