Ergo-Native Features
Advanced
1-2 weeksШаблон аукциона в цепи (Russian аукцион в eUTXO)
Time-bounded auctions with bids as boxes, automatic winner settlement
Problem
You want to sell an asset to the highest bidder without trusting a centralized auction house.
Solution
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.
How It Works
- 1Seller creates auction box with asset, minimum bid, and deadline
- 2Bidders create bid boxes with their offer amount
- 3Each new highest bid must exceed previous by minimum increment
- 4Previous highest bidder can reclaim their bid
- 5At deadline: highest bidder wins
- 6Winner claims asset, seller claims winning bid
- 7Unsettled bids can be reclaimed after deadline
Code Examples
{
// 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.
Use Cases
- →NFT auctions
- →Token sales
- →Domain name auctions
- →Rare item sales
- →Liquidation auctions
Security Considerations
- !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)
Resources
Fee Considerations
Each bid requires transaction. Settlement requires transaction. Budget accordingly.