ThirteenYearAuction Contract#
Overview#
The ThirteenYearAuction is an innovative long-term NFT auction system that creates scarcity through time-based bidding cycles. The contract manages periodic auctions with rest intervals, encouraging strategic bidding and long-term engagement with the Eden platform.
Key Features#
- Long-Term Auctions: 13-year total duration (configurable)
- Periodic Cycles: Active auction periods with rest intervals
- Reserve Pricing: Minimum bid requirements
- Automatic Settlement: Self-executing auction resolution
- Revenue Distribution: Automated payout to designated address
- Emergency Controls: Pause/resume functionality for safety
- Gas Efficient: Optimized for minimal transaction costs
Architecture#
graph TB
subgraph "ThirteenYearAuction System"
A[Auction Start] --> B[Accept Bids]
B --> C{Auction Period Over?}
C -->|No| B
C -->|Yes| D[Auction Settlement]
D --> E[NFT Transfer]
E --> F[Payment Transfer]
F --> G[Rest Period]
G --> H{Max Auctions Reached?}
H -->|No| I[Start Next Auction]
H -->|Yes| J[Contract Complete]
I --> A
end
subgraph "External Systems"
K[NFT Minting]
L[Payment Processing]
M[Frontend Interface]
end
A --> K
F --> L
B --> M
D --> M
Auction Mechanics#
Timing Structure#
- Auction Duration: 1 hour (3600 seconds) - configurable
- Rest Duration: 30 minutes (1800 seconds) - configurable
- Rest Interval: Every 3 auctions - configurable
- Total Auctions: 10 maximum - configurable
- Time Span: 13+ years at full schedule
Bidding Rules#
- Minimum Bid: Must meet reserve price
- Outbid Amount: Must exceed previous bid by minimum increment
- Last Minute Extension: Bidding extends auction if within time limit
- Automatic Refunds: Previous bidders automatically refunded
Contract Functions#
Auction Management#
startAuction(string metadataURI)
#
- Purpose: Begin a new auction period
- Access: Owner only
- Parameters:
metadataURI
: IPFS metadata for auction NFT - Requirements: Must not be in active auction or rest period
- Events: Emits
AuctionStarted(auctionId, metadataURI, endTime)
bid()
#
- Purpose: Place bid on active auction
- Access: Public (payable)
- Requirements:
- Auction must be active
- Bid must exceed current highest bid
- Bid must meet minimum increment
- Events: Emits
BidPlaced(auctionId, bidder, amount)
settleAuction()
#
- Purpose: Finalize completed auction
- Access: Public (anyone can settle)
- Requirements: Auction period must be ended
- Actions:
- Mints NFT to winning bidder
- Transfers payment to payout address
- Initiates rest period if needed
- Events: Emits
AuctionSettled(auctionId, winner, amount)
Administrative Functions#
pauseAuctions()
#
- Purpose: Emergency pause all auction activity
- Access: Owner only
- Effect: Prevents new auctions and bid placement
resumeAuctions()
#
- Purpose: Resume auction activity after pause
- Access: Owner only
- Effect: Allows normal auction operations
updatePayoutAddress(address newPayout)
#
- Purpose: Change recipient of auction proceeds
- Access: Owner only
- Parameters:
newPayout
: New address to receive payments
View Functions#
getCurrentAuction()
#
- Purpose: Get details of active auction
- Returns: Auction struct with all details
- Access: Public view
getAuctionHistory(uint256 auctionId)
#
- Purpose: Get historical auction data
- Parameters:
auctionId
: ID of past auction - Returns: Complete auction information
isAuctionActive()
#
- Purpose: Check if auction is currently accepting bids
- Returns: Boolean indicating auction status
timeUntilNextAuction()
#
- Purpose: Calculate time remaining until next auction
- Returns: Seconds until next auction can start
Events#
event AuctionStarted(
uint256 indexed auctionId,
string metadataURI,
uint256 endTime
);
event BidPlaced(
uint256 indexed auctionId,
address indexed bidder,
uint256 amount
);
event AuctionSettled(
uint256 indexed auctionId,
address indexed winner,
uint256 amount
);
event RestPeriodStarted(uint256 indexed auctionId, uint256 restEndTime);
event PayoutAddressUpdated(address indexed newPayout);
event AuctionsPaused();
event AuctionsResumed();
Auction Lifecycle#
sequenceDiagram
participant Owner as Contract Owner
participant AC as AuctionContract
participant Bidder1 as Bidder 1
participant Bidder2 as Bidder 2
participant Winner as Winning Bidder
Owner->>AC: startAuction(metadataURI)
AC->>AC: Create auction, set end time
AC-->>Bidder1: AuctionStarted event
Bidder1->>AC: bid() + 0.1 ETH
AC->>AC: Record bid, refund none
AC-->>Bidder1: BidPlaced event
Bidder2->>AC: bid() + 0.2 ETH
AC->>AC: Record new highest bid
AC->>Bidder1: Refund 0.1 ETH
AC-->>Bidder2: BidPlaced event
Note over AC: Auction period ends
Winner->>AC: settleAuction()
AC->>AC: Mint NFT to Bidder2
AC->>Owner: Transfer 0.2 ETH to payout
AC-->>Winner: AuctionSettled event
alt Rest Period Needed
AC->>AC: Start rest period
AC-->>Owner: RestPeriodStarted event
end
Economic Model#
Revenue Distribution#
// Example auction economics
const auctionProceeds = winningBid; // e.g., 0.5 ETH
const platformFee = auctionProceeds * 0.025; // 2.5%
const artistPayout = auctionProceeds - platformFee;
// Automated distribution on settlement
contract.transfer(payoutAddress, artistPayout);
Bidding Strategy#
The long-term nature encourages strategic approaches:
- Early Bidding: Secure position early in cycle
- Sniping: Last-minute bidding for advantage
- Rest Period Planning: Prepare for upcoming auctions
- Long-term Commitment: Engagement over years
Security Features#
- Reentrancy Protection: All payable functions protected
- Overflow Protection: Safe math for all calculations
- Access Control: Owner-only administrative functions
- Emergency Pause: Immediate auction halt capability
- Refund Safety: Automatic and secure bid refunds
- Time Validation: Strict timing enforcement
Gas Optimization#
- Efficient Storage: Packed auction data structures
- Minimal State Changes: Optimized state updates
- Batch Settlement: Single transaction settlement
- Event-Based Indexing: Off-chain data access
Configuration#
The contract supports flexible configuration:
struct AuctionConfig {
uint256 auctionDuration; // 3600 seconds (1 hour)
uint256 restDuration; // 1800 seconds (30 min)
uint256 restInterval; // Every 3 auctions
uint256 maxAuctions; // 10 total auctions
uint256 reservePrice; // Minimum bid
uint256 minBidIncrement; // Minimum overbid amount
}
Usage Examples#
Starting an Auction#
import { ethers } from 'ethers';
import ThirteenYearAuctionABI from './ThirteenYearAuction.json';
const auctionContract = new ethers.Contract(
CONTRACT_ADDRESS,
ThirteenYearAuctionABI,
ownerSigner
);
// Start new auction
const tx = await auctionContract.startAuction(
"ipfs://QmYourAuctionMetadata"
);
await tx.wait();
console.log("Auction started!");
Placing Bids#
// Get current auction info
const currentAuction = await auctionContract.getCurrentAuction();
console.log("Current highest bid:", ethers.formatEther(currentAuction.highestBid));
// Place bid (must exceed current highest)
const bidAmount = ethers.parseEther("0.1");
const tx = await auctionContract
.connect(bidderSigner)
.bid({ value: bidAmount });
await tx.wait();
console.log("Bid placed successfully!");
Monitoring Auctions#
// Check auction status
const isActive = await auctionContract.isAuctionActive();
if (isActive) {
const timeLeft = await auctionContract.timeUntilNextAuction();
console.log("Auction ends in:", timeLeft, "seconds");
} else {
const timeToNext = await auctionContract.timeUntilNextAuction();
console.log("Next auction in:", timeToNext, "seconds");
}
// Listen for auction events
auctionContract.on("BidPlaced", (auctionId, bidder, amount) => {
console.log(`New bid: ${ethers.formatEther(amount)} ETH from ${bidder}`);
});
auctionContract.on("AuctionSettled", (auctionId, winner, amount) => {
console.log(`Auction ${auctionId} won by ${winner} for ${ethers.formatEther(amount)} ETH`);
});
Settlement#
// Anyone can settle completed auctions
const currentAuction = await auctionContract.getCurrentAuction();
const now = Math.floor(Date.now() / 1000);
if (now > currentAuction.endTime && currentAuction.settled === false) {
const tx = await auctionContract.settleAuction();
await tx.wait();
console.log("Auction settled!");
}
Testing#
Comprehensive test suite covers:
describe("ThirteenYearAuction", function() {
it("Should accept valid bids during auction", async function() {
await auction.startAuction("ipfs://test");
const bidAmount = ethers.parseEther("0.1");
await expect(
auction.connect(bidder).bid({ value: bidAmount })
).to.emit(auction, "BidPlaced");
});
it("Should automatically refund outbid bidders", async function() {
await auction.startAuction("ipfs://test");
const bid1 = ethers.parseEther("0.1");
const bid2 = ethers.parseEther("0.2");
await auction.connect(bidder1).bid({ value: bid1 });
const balanceBefore = await bidder1.getBalance();
await auction.connect(bidder2).bid({ value: bid2 });
const balanceAfter = await bidder1.getBalance();
expect(balanceAfter - balanceBefore).to.equal(bid1);
});
});
Related Contracts#
- AbrahamEarlyWorks: NFT minting integration
- FixedPriceSale: Alternative sales mechanism
- AgentRegistry: Agent-based auctions
Contract Status: Production Ready
Last Updated: September 1, 2025