Saniul Ahsan

#javascript, #python, #microservices, #automations, #blockchains, #devops

NFT Auction With Solidity

In this example, we’ll create a basic NFT auction contract where users can bid on an NFT, and the highest bidder wins the NFT after a certain duration.

Please note that this example is simplified and doesn’t cover all possible edge cases. Also, make sure to test thoroughly and consider security best practices before deploying any smart contract to the Ethereum network.

Here’s a basic outline of the NFT auction contract:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract NFTAuction is Ownable {
    using Counters for Counters.Counter;
    Counters.Counter private auctionIds;

    struct Auction {
        uint256 id;
        address payable seller;
        IERC721 nftContract;
        uint256 tokenId;
        uint256 startPrice;
        uint256 endBlock;
        address highestBidder;
        uint256 highestBid;
    }

    mapping(uint256 => Auction) public auctions;

    event AuctionCreated(uint256 auctionId, address seller, uint256 tokenId, uint256 startPrice, uint256 endBlock);
    event BidPlaced(uint256 auctionId, address bidder, uint256 amount);
    event AuctionEnded(uint256 auctionId, address winner, uint256 amount);

    constructor() {}

    function createAuction(
        address _nftContract,
        uint256 _tokenId,
        uint256 _startPrice,
        uint256 _durationBlocks
    ) external {
        require(_startPrice > 0, "Start price must be greater than 0");
        require(_durationBlocks > 0, "Duration must be greater than 0");

        auctionIds.increment();
        uint256 auctionId = auctionIds.current();

        Auction storage newAuction = auctions[auctionId];
        newAuction.id = auctionId;
        newAuction.seller = payable(msg.sender);
        newAuction.nftContract = IERC721(_nftContract);
        newAuction.tokenId = _tokenId;
        newAuction.startPrice = _startPrice;
        newAuction.endBlock = block.number + _durationBlocks;
        
        emit AuctionCreated(auctionId, msg.sender, _tokenId, _startPrice, newAuction.endBlock);
    }

    function placeBid(uint256 _auctionId) external payable {
        Auction storage auction = auctions[_auctionId];
        require(block.number < auction.endBlock, "Auction has ended");
        require(msg.value > auction.highestBid, "Bid must be higher than current highest bid");

        if (auction.highestBidder != address(0)) {
            // Refund the previous highest bidder
            address payable previousHighestBidder = payable(auction.highestBidder);
            previousHighestBidder.transfer(auction.highestBid);
        }

        auction.highestBidder = msg.sender;
        auction.highestBid = msg.value;
        emit BidPlaced(_auctionId, msg.sender, msg.value);
    }

    function endAuction(uint256 _auctionId) external {
        Auction storage auction = auctions[_auctionId];
        require(block.number >= auction.endBlock, "Auction has not ended yet");
        require(!auction.ended, "Auction already ended");

        auction.ended = true;
        if (auction.highestBidder != address(0)) {
            address payable winner = payable(auction.highestBidder);
            auction.nftContract.transferFrom(auction.seller, winner, auction.tokenId);
            auction.seller.transfer(auction.highestBid);
            emit AuctionEnded(_auctionId, winner, auction.highestBid);
        }
    }
}

In this example, the contract includes functions for creating an auction, placing bids, and ending auctions. It uses the OpenZeppelin library for ERC721 and utility functions. Before deploying any contract to the Ethereum network, it’s crucial to review, test, and consider security best practices to ensure the safety of the contract and users’ funds.