ERGO
Ergo-Native Features
Advanced
1-2 weeks

On-Chain Auction Pattern (English Auction on eUTXO)

Time-bounded auctions with bids as boxes, automatic winner settlement

GitHub

問題

You want to sell an asset to the highest bidder without trusting a centralized auction house.

解決方案

English auction on eUTXO: the auction box holds the asset, bids are separate boxes. Highest bid at deadline wins. Outbid bidders can reclaim their funds. Winner receives asset, seller receives payment.

運作方式

  1. 1Seller creates auction box with asset, minimum bid, and deadline
  2. 2Bidders create bid boxes with their offer amount
  3. 3Each new highest bid must exceed previous by minimum increment
  4. 4Previous highest bidder can reclaim their bid
  5. 5At deadline: highest bidder wins
  6. 6Winner claims asset, seller claims winning bid
  7. 7Unsettled bids can be reclaimed after deadline

程式碼範例

{
  // Auction box holding the asset
  // R4: Minimum bid (nanoERG)
  // R5: Minimum increment
  // R6: Deadline (block height)
  // R7: Seller address
  // R8: Current highest bid amount
  // R9: Current highest bidder address
  
  val auctionNFT = SELF.tokens(0)._1  // Auction identifier
  val assetToken = SELF.tokens(1)     // Asset being auctioned
  
  val minBid = SELF.R4[Long].get
  val minIncrement = SELF.R5[Long].get
  val deadline = SELF.R6[Int].get
  val seller = SELF.R7[Coll[Byte]].get
  val currentBid = SELF.R8[Long].get
  val currentBidder = SELF.R9[Coll[Byte]].get
  
  val auctionActive = HEIGHT <= deadline
  val auctionEnded = HEIGHT > deadline
  
  // Place new bid (must be higher than current)
  val placeBid = {
    auctionActive &&
    
    val newAuction = OUTPUTS(0)
    val newBidAmount = newAuction.R8[Long].get
    val newBidder = newAuction.R9[Coll[Byte]].get
    
    // New bid must exceed current by minimum increment
    val validBidAmount = newBidAmount >= currentBid + minIncrement
    
    // Auction continues with updated bid
    val auctionContinues = 
      newAuction.tokens(0)._1 == auctionNFT &&
      newAuction.tokens(1) == assetToken &&
      newAuction.R4[Long].get == minBid &&
      newAuction.R5[Long].get == minIncrement &&
      newAuction.R6[Int].get == deadline &&
      newAuction.R7[Coll[Byte]].get == seller
    
    // Previous bidder gets refund (if there was one)
    val previousBidderRefunded = currentBid == 0 || OUTPUTS.exists(o =>
      o.propositionBytes == currentBidder &&
      o.value >= currentBid
    )
    
    validBidAmount && auctionContinues && previousBidderRefunded
  }
  
  // Settle auction (after deadline)
  val settleAuction = {
    auctionEnded && currentBid > 0 &&
    
    // Winner receives asset
    val winnerReceivesAsset = OUTPUTS.exists(o =>
      o.propositionBytes == currentBidder &&
      o.tokens.exists(t => t._1 == assetToken._1)
    )
    
    // Seller receives payment
    val sellerReceivesPayment = OUTPUTS.exists(o =>
      o.propositionBytes == seller &&
      o.value >= currentBid
    )
    
    winnerReceivesAsset && sellerReceivesPayment
  }
  
  // Cancel auction (seller, if no bids)
  val cancelAuction = {
    currentBid == 0 &&
    OUTPUTS.exists(o =>
      o.propositionBytes == seller &&
      o.tokens.exists(t => t._1 == assetToken._1)
    )
  }
  
  placeBid || settleAuction || cancelAuction
}

Full English auction contract. Handles bidding, automatic refunds to outbid bidders, and final settlement.

使用案例

  • NFT auctions
  • Token sales
  • Domain name auctions
  • Rare item sales
  • Liquidation auctions

安全注意事項

  • !Ensure automatic refunds for outbid bidders
  • !Set reasonable minimum increments
  • !Consider sniping protection (extend deadline on late bids)
  • !Audit settlement logic thoroughly
  • !Handle edge cases (no bids, single bid)

實際應用案例

ErgoAuctions

NFT auction house

SkyHarbor

NFT marketplace with auctions

資源

手續費注意事項

Each bid requires transaction. Settlement requires transaction. Budget accordingly.

提升您的 ErgoScript 技能

獲取新模式、教學和開發者資源的通知。

Follow for daily updates