Playbook

BareNFTAuction: Claim, Refund, and Emergency Powers (Barenft Auction Claim Refund Emergency Powers)

English auction flows: bid, claim, cancel, below-reserve refunds, and owner emergency transferNft/transferFunds trade-offs.

Bare Crypto Solidity Marketplace Protocol

Part 4 of 5

BareNFT, reserve escrow, English auction, and NFT-gated BareToken emissions built in Remix IDE with OpenZeppelin v4.1 GitHub imports — no Hardhat/Foundry — covering ADRs, weak RNG, and emergency-power trade-offs.

Bare Crypto Solidity marketplace protocol diagram

The clock ends; ETH and NFT (Non-Fungible Token) must unwind together

BareNFTAuction is an owner-operated English auction: the NFT sits in escrow, each bid instantly refunds the previous maxBidder, and claimTokenFromAuctionByTokenId distributes NFT and ETH by reserve rules. cancelAuctionByTokenId refunds the max bid and returns the NFT to the seller. Emergency transferNft/transferFunds again sit with the owner — recovery and rug share one door.

Owner escrow NFT → createNewAuction(endBlock, reserve, id, start)
        |
   bid() > maxBid ── refund previous maxBidder
        |
   endBlock reached
        |
   claim: maxBid < reserve? refund + NFT→seller
          else ETH→seller, NFT→maxBidder
        |
   cancel / emergency transfer*

This part locks the auction lifecycle, claim/refund paths, and the ADR trade-off for emergency powers.

Concepts, defined where they first appear

📦 English auction
Open ascending bids; each new bid beats the leader and triggers a refund.

📦 Reserve price
If max bid is below reserve, no sale: NFT returns to seller, bid refunds.

📦 Claim settlement
After end, seller or maxBidder calls distribution of NFT/ETH.

📦 Push refund
Immediate ETH return to the previous maxBidder when a higher bid arrives.

Push refunds simplify UX but can stall the whole bid path on a failing receive; pull-payment is an alternate ADR.

ADR: owner-created English auction

Decision: only the owner creates auctions; endBlock must be after the current block; no new auction for a tokenId until the prior one finishes. Rationale: Bare Crypto schedules vitrine auctions on an operator calendar. Cost: no permissionless seller auctions; setTokenContract and setOwner are also owner-bound — the protocol surface hangs on the operator key.

Bid, claim, cancel flow

bid checks startingBid and maxBid, refunds the previous maxBidder via call{value}, then updates maxBid/maxBidder. claimTokenFromAuctionByTokenId: no maxBidder returns NFT to seller; maxBid below reserve refunds and returns NFT; otherwise pays seller and sends NFT to the winner. cancel refunds and returns NFT while open. Those three paths try to keep the escrow invariant that money and NFT unwind together.

bid → refund old leader → set new leader
claim:
  no bid → NFT seller
  below reserve → refund + NFT seller
  else → pay seller + NFT winner
cancel → refund leader + NFT seller

Failure: stuck refunds, griefing, emergency

If the previous bidder is a contract that reverts on receive, the new bid dies on require(success) — a griefing vector. On claim, a failed seller.call may still risk continuing into NFT transfer if success is not enforced on that branch. Emergency transferNft pulls the NFT without settling ETH; the maxBidder's funds can stay trapped. Performance: every bid pushes onto Bid[]; long histories bloat storage and view gas.

The mappings that get confused most often

❌ English auction means anyone can open an auction
✓ In this implementation createNewAuction is owner-only

❌ Bids below reserve are burned
✓ On the claim path the maxBidder is refunded and the NFT returns to the seller

❌ Emergency NFT pull also clears bids
✓ transferNft does not auto-refund ETH; funds can remain stuck in the contract

A checklist for auditing your own system

  1. Who may call claim — only maxBidder, or seller too?
  2. What happens to a new bid if the previous bidder reverts on receive?
  3. After a below-reserve claim, which state does the UI show?
  4. How do cancel and emergency transferNft differ for funds?
  5. How large can Bid[] grow, and is there a view limit?

What to take away from this part

  1. BareNFTAuction is an owner-operated English auction with explicit claim/refund paths.
  2. Push refund UX convenience arrives with griefing and stuck-bid risk.
  3. Emergency NFT pulls do not automatically settle the ETH side.

An end block is not enough; you need a claim path that closes ETH and NFT together.

FAQ

Frequently asked questions

What is English auction?

Open ascending bids; each new bid beats the leader and triggers a refund.

What is Reserve price?

If max bid is below reserve, no sale: NFT returns to seller, bid refunds.

Is it true that "English auction means anyone can open an auction"?

In this implementation createNewAuction is owner-only

What does this part lock in?

This part locks the auction lifecycle, claim/refund paths, and the ADR trade-off for emergency powers. BareNFTAuction is an owner-operated English auction: the NFT sits in escrow, each bid instantly refunds the previous maxBidder, and claimTokenFromAuctionByTokenId distributes NFT and ETH by reserve rules. cancelAuctionByTokenId refunds the max bid and returns the NFT to the seller. Emergency transferNft/transferFunds again sit with the owner — recovery and rug share one door.

Engineering Principles Learned

  • An auction ADR must write create authority, reserve rules, and refund model together.
  • If push refund is chosen, document griefing and the pull-payment alternative.
  • Emergency NFT/ETH exits must be designed without breaking the claim invariant.

Continue reading

Continue reading

Next in series

Next in series

Same series

Paylaş