> ## Documentation Index
> Fetch the complete documentation index at: https://chainstack-docs-polygon-flatcalltracer-getproof.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Cronos: Dutch auction smart contract with Hardhat

> Deploy a Dutch auction NFT contract on Cronos Mainnet using Hardhat where the price decreases over time until a buyer mints at an acceptable price.

**TLDR:**

* This tutorial shows how to create and deploy a Dutch auction NFT contract on Cronos Mainnet using Hardhat.
* The price starts high and lowers at fixed intervals; buyers can mint an NFT once the price is acceptable.
* You’ll set up Hardhat, code and compile the contract, then verify and interact with it using the Cronos Explorer.
* Because this deploys to Cronos Mainnet, deployment and minting spend real CRO — fund your wallet with a small amount to start.

## Main article

A Dutch auction is a type of an auction in which the initial price of an NFT starts at its ceiling and lowers by a small amount at set intervals. Buyers make bids at reduced prices until the end of an auction. A Dutch auction continues until either all assets are sold out or the auction time ends.

The objective of this tutorial is to familiarize you with the Cronos network, Hardhat, and Dutch auction smart contracts. In the end of the tutorial, you will be able to create a simple Dutch auction smart contract to help you sell your NFTs to the highest bidder.

Specifically, in this tutorial, you will:

* Create a Dutch auction smart contract.
* Deploy and verify the contract on Cronos Mainnet through a node deployed with Chainstack.
* Interact with the deployed contract.

## Prerequisites

* [Chainstack account](https://console.chainstack.com/) to deploy a [reliable Cronos RPC endpoint](https://chainstack.com/build-better-with-cronos/).
* [Hardhat](https://hardhat.org/docs) to compile and deploy the contract.
* [MetaMask](https://docs.metamask.io/guide/) to interact with the contract through your Chainstack node.

## Overview

To get from zero to deploying your own Dutch auction smart contract on Cronos Mainnet, do the following:

1. With Chainstack, create a <Tooltip tip="A public chain project- a project to join public networks">public chain project</Tooltip>.

2. With Chainstack, join Cronos Mainnet.

3. With Chainstack, access your Cronos node endpoint.

4. With Hardhat, set up your development environment.

5. With Hardhat, create and compile your Dutch auction contract.

6. With MetaMask, fund your wallet with CRO to cover deployment and minting gas.

7. With Hardhat, deploy your Dutch auction contract.

8. With the [Cronos Explorer](https://explorer.cronos.com/), interact with your Dutch auction contract.

## Step-by-step

### Create a public chain project

See [Create a project](/docs/manage-your-project#create-a-project).

### Join Cronos Mainnet

See [Join a public network](/docs/manage-your-networks).

### Get your Cronos node endpoint

See [View node access and credentials](/docs/manage-your-node#view-node-access-and-credentials).

### Install Hardhat

See [Hardhat documentation](https://hardhat.org/hardhat-runner/docs/getting-started#installation).

### Initialize a Hardhat project

In your project directory, run `npx hardhat`. Select **Create a JavaScript project** and agree to install the sample project's dependencies. This will create a sample project directory with a smart contract draft.

### Install additional dependencies

To complete the project, we need to install several additional dependencies.

The [OpenZeppelin Contract library](https://docs.openzeppelin.com/) allows you to inherit smart contracts. To install it, run:

<CodeGroup>
  ```bash Shell theme={"system"}
  npm i @openzeppelin/contracts
  ```
</CodeGroup>

The [dotenv library](https://github.com/motdotla/dotenv) allows you to export and keep sensitive data securely. To install it, run:

<CodeGroup>
  ```bash Shell theme={"system"}
  npm i dotenv
  ```
</CodeGroup>

Contract verification uses [`@nomicfoundation/hardhat-verify`](https://hardhat.org/hardhat-runner/plugins/nomicfoundation-hardhat-verify), which is already bundled in the `@nomicfoundation/hardhat-toolbox` the sample project installed — no separate verification plugin is needed. You point it at the Cronos Explorer in the Hardhat config below.

You need to create an environment file to store your sensitive data with the project. To create it, in your project directory, run:

<CodeGroup>
  ```bash Shell theme={"system"}
  touch .env
  ```
</CodeGroup>

### Create and compile the contract

1. Navigate to your previously created project directory and go to the `contracts` directory. In the directory, create your Dutch auction smart contract: `DutchAuction.sol`.

   <CodeGroup>
     ```solidity solidity theme={"system"}
     // SPDX-License-Identifier: MIT
     pragma solidity ^0.8.0;

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

     contract MyToken is ERC721, Ownable {
         using Counters for Counters.Counter;

         Counters.Counter private _tokenIdCounter;

         uint256 public immutable startPrice = 10 ether;
         uint256 public immutable startAt;
         uint256 public immutable endsAt;
         uint256 public immutable endPrice = 5 ether;
         uint256 public immutable discountRate = 0.01 ether;
         uint256 public duration = 500 minutes;
         uint256 public immutable MAX_SUPPLY = 100;

          mapping (address => bool) public onlyOne;

         constructor() ERC721("CronosNFT", "CroNFT") {
             startAt = block.timestamp;
             endsAt = block.timestamp + duration;
         }

         function price() public view returns (uint256) {
             if (block.timestamp > endsAt ) {
                 return endPrice;
             }

             uint256 minutesElapsed = (block.timestamp - startAt) / 60;

             return startPrice - (minutesElapsed * discountRate);
         }

         function safeMint(address to) public payable {
             require(msg.value >= price(), "Not enough ether sent");
             require(!onlyOne[msg.sender], "Sorry, Address already has 1 NFT!");
             uint256 tokenId = _tokenIdCounter.current();
             require(tokenId < MAX_SUPPLY, "No more items left.");
             _safeMint(to, tokenId + 1);
             _tokenIdCounter.increment();
             onlyOne[msg.sender]=true;

         }

         function withdraw() public onlyOwner {
             payable(owner()).transfer(address(this).balance);
         }
     }
     ```
   </CodeGroup>

   The contract implementation is the following:

   * The price of an NFT starts at 10 ether and decreases to 5 ether over 500 minutes. A maximum of 100 NFTs can be minted.
   * The contract uses the `onlyOne` mapping to ensure that each address can only own one NFT from your collection.
   * The contract sets the values of the start and end price, which cannot be changed later on.
   * The function `price()` uses `block.timestamp` to calculate the price of an NFT each time the `safeMint` function is called.
   * If all the required conditions are satisfied, the wallet address gets an NFT minted.

2. To compile the contract, in your project directory, run:

   <CodeGroup>
     ```bash Shell theme={"system"}
     npx hardhat compile
     ```
   </CodeGroup>

### Fund your account

To deploy your smart contract on Cronos Mainnet, the deploying wallet needs CRO to cover gas. Fund it with a small amount of CRO from an exchange or an existing wallet.

### Set up the environment and configuration files

1. In your project directory, navigate to a previously created environment file and edit it to add the following data:

   * `RPC_URL` — your Cronos node HTTPS endpoint deployed with Chainstack. See also [View node access and credentials](/docs/manage-your-node#view-node-access-and-credentials).
   * `PRIVATE_KEY` — the private key of your MetaMask wallet, funded with enough CRO to cover deployment gas.
   * `API_KEY` — a Cronos Explorer API key used to verify the deployed contract. Create one in the [Cronos Explorer](https://explorer.cronos.com/) (see [Block explorer and API keys](https://docs.cronos.com/block-explorers/block-explorer-and-api-keys)).

   Example of the environment file data:

   <CodeGroup>
     ```env env theme={"system"}
     RPC_URL=YOUR_CHAINSTACK_ENDPOINT
     PRIVATE_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXu7
     API_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXG5
     ```
   </CodeGroup>

2. In your project directory, navigate to the Hardhat configuration file and replace the current data with the following data:

   <CodeGroup>
     ```js JavaScript theme={"system"}
     require("@nomicfoundation/hardhat-toolbox");
     require('dotenv').config();

     module.exports = {
       solidity: "0.8.10",
       networks: {
         cronos: {
           url: `${process.env.RPC_URL}`,
           chainId: 25,
           accounts: [process.env.PRIVATE_KEY]
         },
       },
       etherscan: {
         apiKey: {
           cronos: `${process.env.API_KEY}`
         },
         customChains: [
           {
             network: "cronos",
             chainId: 25,
             urls: {
               apiURL: `https://explorer-api.cronos.org/mainnet/api/v1/hardhat/contract?apikey=${process.env.API_KEY}`,
               browserURL: "https://explorer.cronos.com"
             }
           }
         ]
       }
     };
     ```
   </CodeGroup>

   where

   * `dotenv` — library to import your sensitive data from the environment file securely
   * `cronos` — the Cronos Mainnet network to deploy the contract to
   * `url` — your Cronos node HTTPS endpoint imported from the environment file
   * `accounts` — your MetaMask wallet private key imported from the environment file
   * `etherscan` — Cronos Explorer verification settings: your API key plus the `customChains` entry that points `hardhat-verify` at the Cronos Explorer

### Deploy the Dutch auction contract

1. In your project directory, navigate to the scripts directory and create the `DeployDutch.js` file.

2. Edit the `DeployDutch.js` file to add the basic deployment script of Hardhat:

   <CodeGroup>
     ```js JavaScript theme={"system"}
     const hre = require("hardhat");

     async function main() {
       const CronosToken = await hre.ethers.getContractFactory("MyToken");
       console.log("Deploying your contract, please Wait.....");
       const cronosToken = await CronosToken.deploy();
       await cronosToken.deployed();

       console.log("CronosToken deployed to:", cronosToken.address);
     }

     main()
       .then(() => process.exit(0))
       .catch((error) => {
         console.error(error);
         process.exit(1);
       });
     ```
   </CodeGroup>

3. In your project directory, run the following script:

   <CodeGroup>
     ```bash Shell theme={"system"}
     npx hardhat run scripts/DeployDutch.js --network cronos
     ```
   </CodeGroup>

   The contract will deploy and the terminal will return the contract address. Use this address to verify and interact with your contract.

### Verify your contract on Cronos Mainnet

Once your contract is deployed, verify it on Cronos Mainnet. In your terminal, run:

<CodeGroup>
  ```bash Shell theme={"system"}
  npx hardhat verify --network cronos CONTRACT_ADDRESS
  ```
</CodeGroup>

where CONTRACT\_ADDRESS your contract address returned at the previous step

### Interact with the contract

Now that your contract is verified, the [Cronos Explorer](https://explorer.cronos.com/) is effectively a front-end instance for your contract.

## Conclusion

This tutorial guided you through the basics of using Hardhat to deploy a Dutch auction smart contract to Cronos Mainnet, and verify it against the Cronos Explorer with `hardhat-verify`.

Because this deploys to Cronos Mainnet, every deployment and mint spends real CRO — keep amounts small while you experiment.

### About the author

<CardGroup>
  <Card title="Priyank Gupta">
    <img src="https://mintcdn.com/chainstack-docs-polygon-flatcalltracer-getproof/VrnJIprlDDMrVpnP/images/docs/56264430/224220454-0df06476-4ea8-4f40-8255-88f1cb4ab89d.png?fit=max&auto=format&n=VrnJIprlDDMrVpnP&q=85&s=f5cf85ffb732941eeb6e9bc4b4d98069" alt="Priyank Gupta" style={{width: '80px', height: '80px', borderRadius: '50%', objectFit: 'cover', display: 'block', margin: '0 auto'}} noZoom width="444" height="444" data-path="images/docs/56264430/224220454-0df06476-4ea8-4f40-8255-88f1cb4ab89d.png" />

    <Icon icon="code" iconType="solid" /> Developer Advocate @ Chainstack
    <br /><Icon icon="screwdriver-wrench" iconType="solid" /> BUIDLs on Ethereum, zkEVMs, and The Graph protocol
    <br /><Icon icon="anchor" iconType="solid" /> Part-time Rust aficionado

    <div style={{display: "flex", justifyContent: "center", gap: "12px"}}>
      <a href="https://github.com/Genesis3800" style={{textDecoration: "none", borderBottom: "none"}}>
        <Icon icon="github" iconType="brands" />
      </a>

      <a href="https://twitter.com/PriyankGupta03" style={{textDecoration: "none", borderBottom: "none"}}>
        <Icon icon="twitter" iconType="brands" />
      </a>

      <a href="https://www.linkedin.com/in/priyank-gupta-0308/" style={{textDecoration: "none", borderBottom: "none"}}>
        <Icon icon="linkedin" iconType="brands" />
      </a>
    </div>
  </Card>
</CardGroup>
