You can run a trustless auction for your NFTs on Bitcoin.

Write an Auction smart contract

It turns out that writing the Auction smart contract is very simple. Here is a basic contract to provide decentralized auction on Bitcoin Virtual Machine.

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

import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "./ERC721NFT.sol";

interface IERC721Mint {
    function transferFrom(address _from, address _to, uint _nftId) external;
    function safeMint(address to, string memory uri) external;

contract DutchAuction {
    uint private constant DURATION = 7 days;

    IERC721 public immutable nft;
    uint public immutable nftId;

    address payable public immutable seller;
    uint public immutable startingPrice;
    uint public immutable startAt;
    uint public immutable expiresAt;
    uint public immutable discountRate;

    constructor(uint _startingPrice, uint _discountRate, address _nft, uint _nftId) {
        seller = payable(msg.sender);
        startingPrice = _startingPrice;
        startAt = block.timestamp;
        expiresAt = block.timestamp + DURATION;
        discountRate = _discountRate;

        require(_startingPrice >= _discountRate * DURATION, "starting price < min");

        nft = IERC721(_nft);
        nftId = _nftId;

    function getPrice() public view returns (uint) {
        uint timeElapsed = block.timestamp - startAt;
        uint discount = discountRate * timeElapsed;
        return startingPrice - discount;

    function buy() external payable {
        require(block.timestamp < expiresAt, "auction expired");

        uint price = getPrice();
        require(msg.value >= price, "ETH < price");

        nft.transferFrom(address(this), msg.sender, nftId);
        uint refund = msg.value - price;
        if (refund > 0) {

    function onERC721Received(address, address, uint256, bytes calldata) external pure returns (bytes4) {
        return IERC721Receiver.onERC721Received.selector;

Dutch auction for NFT.

  1. Seller of NFT deploys this contract setting a starting price for the NFT.

  2. Auction lasts for 7 days.

  3. Price of NFT decreases over time.

  4. Participants can buy by depositing ETH greater than the current price computed by the smart contract.

  5. Auction ends when a buyer buys the NFT.

Clone the smart contract examples

We've prepared a few different examples for you to get started.

git clone

Compile the contracts

To compile your contracts, use the built-in hardhat compile task.

cd smart-contract-examples
npm install
npx hardhat compile

Deploy the contracts

Review config file hardhat.config.ts. The network configs should look like this.

  networks: {
    mynw: {
      url: "http://localhost:10002",
      accounts: {
        mnemonic: "<your mnemonic with funds>"
      timeout: 100_000,
    blockscoutVerify: {
      blockscoutURL: "http://localhost:4000", // your explorer URL

Run the deploy scripts using hardhat-deploy.

npx hardhat deploy --tags DutchAuction

Make sure the accounts in hardhat.config.ts have some TC.

Interact with the contracts

Once the contracts are deployed, you can interact with them. We've prepared a few hardhat tasks to make it easy for you to interact with the contracts.

npx hardhat getPrice
npx hardhat buy --amount 1

Last updated