Contract · NFT
Auction
English auction with minimum bid increments, automatic refunds and settlement.
NFT
~1.6M gas
Ethereum
Post-deploy checklist
- Confirm NFT contract + tokenId exist and are owned by the seller
- Approve the auction contract to transfer the NFT
- Verify start price and min increment (wei, not ETH UI units)
- After end, settle so winner receives the NFT and seller receives ETH
Configure & deploy
ERC721 contract that holds the asset being auctioned.
The specific NFT id. Must be owned by the account that will transfer/approve the auction.
Opening bid in wei (1e17 = 0.1 ETH). Use the Unit Converter tool for ETH → wei.
Auction length from deploy/start. 86400 = 24 hours.
Minimum amount a new bid must exceed the current bid by.
Use cases
- Art auctions
- 1-of-1 NFT sales
- Charity bidding
EnglishAuction.solsolidity
// SPDX-License-Identifier: MIT
// Compatible with OpenZeppelin Contracts ^5.0 (Wizard / Contracts MCP patterns)
// Compiled with Solidity ^0.8.24 — Ethereum Toolset browser solc
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
contract EnglishAuction is ReentrancyGuard {
IERC721 public immutable nft;
uint256 public immutable tokenId;
address public immutable seller;
uint64 public immutable endsAt;
uint256 public immutable minIncrement;
address public highestBidder;
uint256 public highestBid;
bool public settled;
mapping(address => uint256) public refunds;
constructor(IERC721 _nft, uint256 _tokenId, uint256 _start, uint64 _duration, uint256 _minIncrement) {
nft = _nft; tokenId = _tokenId; seller = msg.sender;
highestBid = _start; endsAt = uint64(block.timestamp) + _duration; minIncrement = _minIncrement;
}
function bid() external payable {
require(block.timestamp < endsAt, "ended");
require(msg.value >= highestBid + minIncrement, "bid too low");
if (highestBidder != address(0)) refunds[highestBidder] += highestBid;
highestBidder = msg.sender;
highestBid = msg.value;
}
function withdraw() external nonReentrant {
uint256 amt = refunds[msg.sender];
refunds[msg.sender] = 0;
payable(msg.sender).transfer(amt);
}
function settle() external nonReentrant {
require(block.timestamp >= endsAt && !settled, "not ready");
settled = true;
if (highestBidder == address(0)) {
nft.safeTransferFrom(address(this), seller, tokenId);
} else {
payable(seller).transfer(highestBid);
nft.safeTransferFrom(address(this), highestBidder, tokenId);
}
}
}
