Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 113 additions & 0 deletions contracts/time-auction.clar
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
(define-constant ERR_ALREADY_SETTLED (err u6007))
(define-constant ERR_RESERVE_NOT_MET (err u6008))
(define-constant ERR_INVALID_DURATION (err u6009))
(define-constant ERR_NO_BID_TO_WITHDRAW (err u6010))
(define-constant ERR_NOT_HIGHEST_BIDDER (err u6011))

;; Minimum auction duration: 1 hour
(define-constant MIN_DURATION u3600)
Expand Down Expand Up @@ -316,6 +318,71 @@
)
)

;; Withdraw bid (only if not the highest bidder)
(define-public (withdraw-non-winning-bid (auction-id uint))
(let
(
(auction (unwrap! (map-get? auctions { auction-id: auction-id }) ERR_AUCTION_NOT_FOUND))
(user tx-sender)
)
;; Auction must still be active
(asserts! (is-auction-active auction-id) ERR_AUCTION_ENDED)

;; Cannot withdraw if you're the highest bidder
(match (get highest-bidder auction)
highest-bidder (asserts! (not (is-eq user highest-bidder)) ERR_NOT_HIGHEST_BIDDER)
true
)

;; Find and refund user's last bid
(let
(
(user-last-bid (find-user-last-bid auction-id user))
)
(asserts! (is-some user-last-bid) ERR_NO_BID_TO_WITHDRAW)
(let
(
(bid-amount (get amount user-last-bid))
)
(begin
;; Refund the bid amount
(try! (stx-transfer? bid-amount tx-sender user))

;; Update user stats
(update-user-stats-after-withdrawal user)

;; Log event
(log-bid-withdrawn auction-id user bid-amount)

(ok true)
)
)
)
)
)


;; Check if user can withdraw their bid from an auction
(define-read-only (can-withdraw-bid (auction-id uint) (user principal))
(match (map-get? auctions { auction-id: auction-id })
auction
(ok (and
(is-auction-active auction-id)
(not (is-eq user (default-to user (get highest-bidder auction))))
(is-some (find-user-last-bid auction-id user))
))
false
)
)

;; Get user's last bid amount in an auction
(define-read-only (get-user-last-bid (auction-id uint) (user principal))
(match (find-user-last-bid auction-id user)
bid (ok (get amount bid))
none (ok u0)
)
)

;; Settle auction after it ends
(define-public (settle-auction (auction-id uint))
(let
Expand Down Expand Up @@ -414,3 +481,49 @@
(ok true)
)
)

(define-private (find-user-last-bid (auction-id uint) (user principal))
(let
(
(auction (unwrap! (map-get? auctions { auction-id: auction-id }) ERR_AUCTION_NOT_FOUND))
(bid-count (get bid-count auction))
)
(find-user-last-bid-helper auction-id user (- bid-count u1))
)
)

(define-private (find-user-last-bid-helper (auction-id uint) (user principal) (index uint))
(if (>= index u0)
(match (map-get? bid-history { auction-id: auction-id, bid-index: index })
bid (if (is-eq (get bidder bid) user)
(some bid)
(find-user-last-bid-helper auction-id user (- index u1)))
(find-user-last-bid-helper auction-id user (- index u1))
)
none
)
)

;; Helper to update user bid stats when withdrawing
(define-private (update-user-stats-after-withdrawal (user principal))
(let
(
(user-stat (default-to { active-bids: u0, total-bids: u0, wins: u0 }
(map-get? user-bids { user: user })))
)
(if (> (get active-bids user-stat) u0)
(map-set user-bids
{ user: user }
(merge user-stat {
active-bids: (- (get active-bids user-stat) u1)
})
)
true
)
)
)

;; Add logging event for bid withdrawal
(define-private (log-bid-withdrawn (auction-id uint) (bidder principal) (amount uint))
(print { event: "bid-withdrawn", auction-id: auction-id, bidder: bidder, amount: amount, timestamp: stacks-block-time })
)