{"id":21936061,"url":"https://github.com/learnweb3dao/whitelist-dapp","last_synced_at":"2025-04-22T11:52:16.925Z","repository":{"id":40305368,"uuid":"441251094","full_name":"LearnWeb3DAO/Whitelist-Dapp","owner":"LearnWeb3DAO","description":null,"archived":false,"fork":false,"pushed_at":"2022-11-27T10:50:53.000Z","size":325,"stargazers_count":54,"open_issues_count":9,"forks_count":91,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-29T14:51:11.377Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LearnWeb3DAO.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-12-23T17:26:43.000Z","updated_at":"2025-02-05T04:09:54.000Z","dependencies_parsed_at":"2023-01-21T05:47:11.283Z","dependency_job_id":null,"html_url":"https://github.com/LearnWeb3DAO/Whitelist-Dapp","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LearnWeb3DAO%2FWhitelist-Dapp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LearnWeb3DAO%2FWhitelist-Dapp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LearnWeb3DAO%2FWhitelist-Dapp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LearnWeb3DAO%2FWhitelist-Dapp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LearnWeb3DAO","download_url":"https://codeload.github.com/LearnWeb3DAO/Whitelist-Dapp/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250237798,"owners_count":21397399,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-29T01:13:01.664Z","updated_at":"2025-04-22T11:52:16.900Z","avatar_url":"https://github.com/LearnWeb3DAO.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Whitelist-Dapp\n\nYou are launching your NFT collection named `Crypto Devs`. You want to give your early supporters access to a whitelist for your collection, so here you are creating a whitelist dapp for `Crypto Devs`\n\n![](https://i.imgur.com/zgY0TGo.png)\n\n## Requirements\n\n- Whitelist access should be given to the first `10` users for free who want to get in.\n- There should be a website where people can go and enter into the whitelist.\n\nLets start building 🚀\n\n---\n\n## Prerequisites\n\n- You can write code in JavaScript (Beginner Track - [Level-0](https://github.com/LearnWeb3DAO/Basic-Programming))\n- Have set up a Metamask Wallet (Beginner Track - [Level-4](https://github.com/LearnWeb3DAO/Crypto-Wallets))\n- Your computer has Node.js installed. If not download from [here](https://nodejs.org/en/download/)\n\n---\n## Prefer a Video?\nIf you would rather learn from a video, we have a recording available of this tutorial on our YouTube. Watch the video by clicking on the screenshot below, or go ahead and read the tutorial!\n[![Whitelist dApp Part-1](https://i.imgur.com/QsVxGLq.png)](https://www.youtube.com/watch?v=eSS0vZ7rqpU\u0026t=4757s \"Whitelist dApp Tutorial\")\n[![Whitelist dApp Part-2](https://i.imgur.com/084i0Sp.png)](https://www.youtube.com/watch?v=iMOAUkL09pU \"Whitelist dApp Tutorial\")\n## Build\n\n### Smart Contract\n\nTo build the smart contract we will be using [Hardhat](https://hardhat.org/).\nHardhat is an Ethereum development environment and framework designed for full stack development in Solidity. In simple words you can write your smart contract, deploy them, run tests, and debug your code.\n\n\n\n - First, you need to create a Whitelist-Daap folder where the Hardhat project and your Next.js app will later go\n - Open up a terminal and execute these commands\n  ```bash\n  mkdir Whitelist-Dapp\n  cd Whitelist-Dapp\n  ```\n - Then, in Whitelist-Daap folder, you will set up Hardhat project \n  ```bash\n  mkdir hardhat-tutorial\n  cd hardhat-tutorial\n  npm init --yes\n  npm install --save-dev hardhat\n  ```\n\n- In the same directory where you installed Hardhat run:\n\n  ```bash\n  npx hardhat\n  ```\n\n  - Select `Create a Javascript project`\n  - Press enter for the already specified `Hardhat Project root`\n  - Press enter for the question on if you want to add a `.gitignore`\n  - Press enter for `Do you want to install this sample project's dependencies with npm (@nomicfoundation/hardhat-toolbox)?`\n\nNow you have a hardhat project ready to go!\n\nIf you are not on mac, please do this extra step and install these libraries as well :)\n\n```bash\nnpm install --save-dev @nomicfoundation/hardhat-toolbox\n```\n\n- Start by creating a new file inside the `contracts` directory called `Whitelist.sol`.\n\n  ```go\n  //SPDX-License-Identifier: Unlicense\n  pragma solidity ^0.8.0;\n\n\n  contract Whitelist {\n\n      // Max number of whitelisted addresses allowed\n      uint8 public maxWhitelistedAddresses;\n\n      // Create a mapping of whitelistedAddresses\n      // if an address is whitelisted, we would set it to true, it is false by default for all other addresses.\n      mapping(address =\u003e bool) public whitelistedAddresses;\n\n      // numAddressesWhitelisted would be used to keep track of how many addresses have been whitelisted\n      // NOTE: Don't change this variable name, as it will be part of verification\n      uint8 public numAddressesWhitelisted;\n\n      // Setting the Max number of whitelisted addresses\n      // User will put the value at the time of deployment\n      constructor(uint8 _maxWhitelistedAddresses) {\n          maxWhitelistedAddresses =  _maxWhitelistedAddresses;\n      }\n\n      /**\n          addAddressToWhitelist - This function adds the address of the sender to the\n          whitelist\n       */\n      function addAddressToWhitelist() public {\n          // check if the user has already been whitelisted\n          require(!whitelistedAddresses[msg.sender], \"Sender has already been whitelisted\");\n          // check if the numAddressesWhitelisted \u003c maxWhitelistedAddresses, if not then throw an error.\n          require(numAddressesWhitelisted \u003c maxWhitelistedAddresses, \"More addresses cant be added, limit reached\");\n          // Add the address which called the function to the whitelistedAddress array\n          whitelistedAddresses[msg.sender] = true;\n          // Increase the number of whitelisted addresses\n          numAddressesWhitelisted += 1;\n      }\n\n  }\n  ```\n\n- Lets deploy the contract to `rinkeby` network. Create a new file, or replace the default file named `deploy.js` under the `scripts` folder\n\n- Now we will write some code to deploy the contract in `deploy.js` file.\n\n  ```js\n  const { ethers } = require(\"hardhat\");\n\n  async function main() {\n    /*\n    A ContractFactory in ethers.js is an abstraction used to deploy new smart contracts,\n    so whitelistContract here is a factory for instances of our Whitelist contract.\n    */\n    const whitelistContract = await ethers.getContractFactory(\"Whitelist\");\n\n    // here we deploy the contract\n    const deployedWhitelistContract = await whitelistContract.deploy(10);\n    // 10 is the Maximum number of whitelisted addresses allowed\n    \n    // Wait for it to finish deploying\n    await deployedWhitelistContract.deployed();\n\n    // print the address of the deployed contract\n    console.log(\n      \"Whitelist Contract Address:\",\n      deployedWhitelistContract.address\n    );\n  }\n\n  // Call the main function and catch if there is any error\n  main()\n    .then(() =\u003e process.exit(0))\n    .catch((error) =\u003e {\n      console.error(error);\n      process.exit(1);\n    });\n  ```\n\n- Now create a `.env` file in the `hardhat-tutorial` folder and add the following lines, use the instructions in the comments to get your Alchemy API Key URL and RINKEBY Private Key. Make sure that the account from which you get your rinkeby private key is funded with Rinkeby Ether.\n\n  ```\n\n  // Go to https://www.alchemyapi.io, sign up, create\n  // a new App in its dashboard and select the network as Rinkeby, and replace \"add-the-alchemy-key-url-here\" with its key url\n  ALCHEMY_API_KEY_URL=\"add-the-alchemy-key-url-here\"\n\n  // Replace this private key with your RINKEBY account private key\n  // To export your private key from Metamask, open Metamask and\n  // go to Account Details \u003e Export Private Key\n  // Be aware of NEVER putting real Ether into testing accounts\n  RINKEBY_PRIVATE_KEY=\"add-the-rinkeby-private-key-here\"\n\n  ```\n\n- Now we will install `dotenv` package to be able to import the env file and use it in our config. Open up a terminal pointing at`hardhat-tutorial` directory and execute this command\n  ```bash\n  npm install dotenv\n  ```\n- Now open the hardhat.config.js file, we would add the `rinkeby` network here so that we can deploy our contract to rinkeby. Replace all the lines in the `hardhar.config.js` file with the given below lines\n\n  ```js\n  require(\"@nomicfoundation/hardhat-toolbox\");\n  require(\"dotenv\").config({ path: \".env\" });\n\n  const ALCHEMY_API_KEY_URL = process.env.ALCHEMY_API_KEY_URL;\n\n  const RINKEBY_PRIVATE_KEY = process.env.RINKEBY_PRIVATE_KEY;\n\n  module.exports = {\n    solidity: \"0.8.9\",\n    networks: {\n      rinkeby: {\n        url: ALCHEMY_API_KEY_URL,\n        accounts: [RINKEBY_PRIVATE_KEY],\n      },\n    },\n  };\n  ```\n\n- Compile the contract, open up a terminal pointing at`hardhat-tutorial` directory and execute this command\n\n  ```bash\n     npx hardhat compile\n  ```\n  \n- To deploy, open up a terminal pointing at`hardhat-tutorial` directory and execute this command\n  ```bash\n  npx hardhat run scripts/deploy.js --network rinkeby\n  ```\n- Save the Whitelist Contract Address that was printed on your terminal in your notepad, you would need it futher down in the tutorial.\n\n### Website\n\n- To develop the website we will use [React](https://reactjs.org/) and [Next Js](https://nextjs.org/). React is a javascript framework used to make websites and Next.js is a React framework that also allows writing backend APIs code along with the frontend, so you don't need two separate frontend and backend services.\n- First, You will need to create a new `next` app.\n\n- To create this `next-app`, in the terminal point to Whitelist-Dapp folder and type\n\n  ```bash\n  npx create-next-app@latest\n  ```\n\n  and press `enter` for all the questions\n\n- Your folder structure should look something like\n\n  ```\n  - Whitelist-Dapp\n      - hardhat-tutorial\n      - my-app\n  ```\n\n- Now to run the app, execute these commands in the terminal\n\n  ```\n  cd my-app\n  npm run dev\n  ```\n\n- Now go to `http://localhost:3000`, your app should be running 🤘\n\n- Now lets install [Web3Modal library](https://github.com/Web3Modal/web3modal). Web3Modal is an easy to use library to help developers easily allow their users to connect to your dApps with all sorts of different wallets. By default Web3Modal Library supports injected providers like (Metamask, Dapper, Gnosis Safe, Frame, Web3 Browsers, etc) and WalletConnect, You can also easily configure the library to support Portis, Fortmatic, Squarelink, Torus, Authereum, D'CENT Wallet and Arkane.\n(Here's a live example on [Codesandbox.io](https://codesandbox.io/s/j43b10))\n\n- Open up a terminal pointing at`my-app` directory and execute this command\n\n  ```bash\n  npm install web3modal\n  ```\n\n- In the same terminal also install `ethers.js`\n\n  ```bash\n  npm install ethers\n  ```\n\n- In your my-app/public folder, download [this image](https://github.com/LearnWeb3DAO/Whitelist-Dapp/blob/main/my-app/public/crypto-devs.svg) and rename it to `crypto-devs.svg`\n- Now go to styles folder and replace all the contents of `Home.modules.css` file with the following code, this would add some styling to your dapp:\n\n  ```css\n  .main {\n    min-height: 90vh;\n    display: flex;\n    flex-direction: row;\n    justify-content: center;\n    align-items: center;\n    font-family: \"Courier New\", Courier, monospace;\n  }\n\n  .footer {\n    display: flex;\n    padding: 2rem 0;\n    border-top: 1px solid #eaeaea;\n    justify-content: center;\n    align-items: center;\n  }\n\n  .image {\n    width: 70%;\n    height: 50%;\n    margin-left: 20%;\n  }\n\n  .title {\n    font-size: 2rem;\n    margin: 2rem 0;\n  }\n\n  .description {\n    line-height: 1;\n    margin: 2rem 0;\n    font-size: 1.2rem;\n  }\n\n  .button {\n    border-radius: 4px;\n    background-color: blue;\n    border: none;\n    color: #ffffff;\n    font-size: 15px;\n    padding: 20px;\n    width: 200px;\n    cursor: pointer;\n    margin-bottom: 2%;\n  }\n  @media (max-width: 1000px) {\n    .main {\n      width: 100%;\n      flex-direction: column;\n      justify-content: center;\n      align-items: center;\n    }\n  }\n  ```\n\n- Open your index.js file under the pages folder and paste the following code, explanation of the code can be found in the comments. Make sure you read about React and [React Hooks](https://reactjs.org/docs/hooks-overview.html), [React Hooks Tutorial](https://www.w3schools.com/react/react_hooks.asp) if you are not familiar with them.\n\n  ```js\n  import Head from \"next/head\";\n  import styles from \"../styles/Home.module.css\";\n  import Web3Modal from \"web3modal\";\n  import { providers, Contract } from \"ethers\";\n  import { useEffect, useRef, useState } from \"react\";\n  import { WHITELIST_CONTRACT_ADDRESS, abi } from \"../constants\";\n\n  export default function Home() {\n    // walletConnected keep track of whether the user's wallet is connected or not\n    const [walletConnected, setWalletConnected] = useState(false);\n    // joinedWhitelist keeps track of whether the current metamask address has joined the Whitelist or not\n    const [joinedWhitelist, setJoinedWhitelist] = useState(false);\n    // loading is set to true when we are waiting for a transaction to get mined\n    const [loading, setLoading] = useState(false);\n    // numberOfWhitelisted tracks the number of addresses's whitelisted\n    const [numberOfWhitelisted, setNumberOfWhitelisted] = useState(0);\n    // Create a reference to the Web3 Modal (used for connecting to Metamask) which persists as long as the page is open\n    const web3ModalRef = useRef();\n\n    /**\n     * Returns a Provider or Signer object representing the Ethereum RPC with or without the\n     * signing capabilities of metamask attached\n     *\n     * A `Provider` is needed to interact with the blockchain - reading transactions, reading balances, reading state, etc.\n     *\n     * A `Signer` is a special type of Provider used in case a `write` transaction needs to be made to the blockchain, which involves the connected account\n     * needing to make a digital signature to authorize the transaction being sent. Metamask exposes a Signer API to allow your website to\n     * request signatures from the user using Signer functions.\n     *\n     * @param {*} needSigner - True if you need the signer, default false otherwise\n     */\n    const getProviderOrSigner = async (needSigner = false) =\u003e {\n      // Connect to Metamask\n      // Since we store `web3Modal` as a reference, we need to access the `current` value to get access to the underlying object\n      const provider = await web3ModalRef.current.connect();\n      const web3Provider = new providers.Web3Provider(provider);\n\n      // If user is not connected to the Rinkeby network, let them know and throw an error\n      const { chainId } = await web3Provider.getNetwork();\n      if (chainId !== 4) {\n        window.alert(\"Change the network to Rinkeby\");\n        throw new Error(\"Change network to Rinkeby\");\n      }\n\n      if (needSigner) {\n        const signer = web3Provider.getSigner();\n        return signer;\n      }\n      return web3Provider;\n    };\n\n    /**\n     * addAddressToWhitelist: Adds the current connected address to the whitelist\n     */\n    const addAddressToWhitelist = async () =\u003e {\n      try {\n        // We need a Signer here since this is a 'write' transaction.\n        const signer = await getProviderOrSigner(true);\n        // Create a new instance of the Contract with a Signer, which allows\n        // update methods\n        const whitelistContract = new Contract(\n          WHITELIST_CONTRACT_ADDRESS,\n          abi,\n          signer\n        );\n        // call the addAddressToWhitelist from the contract\n        const tx = await whitelistContract.addAddressToWhitelist();\n        setLoading(true);\n        // wait for the transaction to get mined\n        await tx.wait();\n        setLoading(false);\n        // get the updated number of addresses in the whitelist\n        await getNumberOfWhitelisted();\n        setJoinedWhitelist(true);\n      } catch (err) {\n        console.error(err);\n      }\n    };\n\n    /**\n     * getNumberOfWhitelisted:  gets the number of whitelisted addresses\n     */\n    const getNumberOfWhitelisted = async () =\u003e {\n      try {\n        // Get the provider from web3Modal, which in our case is MetaMask\n        // No need for the Signer here, as we are only reading state from the blockchain\n        const provider = await getProviderOrSigner();\n        // We connect to the Contract using a Provider, so we will only\n        // have read-only access to the Contract\n        const whitelistContract = new Contract(\n          WHITELIST_CONTRACT_ADDRESS,\n          abi,\n          provider\n        );\n        // call the numAddressesWhitelisted from the contract\n        const _numberOfWhitelisted = await whitelistContract.numAddressesWhitelisted();\n        setNumberOfWhitelisted(_numberOfWhitelisted);\n      } catch (err) {\n        console.error(err);\n      }\n    };\n\n    /**\n     * checkIfAddressInWhitelist: Checks if the address is in whitelist\n     */\n    const checkIfAddressInWhitelist = async () =\u003e {\n      try {\n        // We will need the signer later to get the user's address\n        // Even though it is a read transaction, since Signers are just special kinds of Providers,\n        // We can use it in it's place\n        const signer = await getProviderOrSigner(true);\n        const whitelistContract = new Contract(\n          WHITELIST_CONTRACT_ADDRESS,\n          abi,\n          signer\n        );\n        // Get the address associated to the signer which is connected to  MetaMask\n        const address = await signer.getAddress();\n        // call the whitelistedAddresses from the contract\n        const _joinedWhitelist = await whitelistContract.whitelistedAddresses(\n          address\n        );\n        setJoinedWhitelist(_joinedWhitelist);\n      } catch (err) {\n        console.error(err);\n      }\n    };\n\n    /*\n      connectWallet: Connects the MetaMask wallet\n    */\n    const connectWallet = async () =\u003e {\n      try {\n        // Get the provider from web3Modal, which in our case is MetaMask\n        // When used for the first time, it prompts the user to connect their wallet\n        await getProviderOrSigner();\n        setWalletConnected(true);\n\n        checkIfAddressInWhitelist();\n        getNumberOfWhitelisted();\n      } catch (err) {\n        console.error(err);\n      }\n    };\n\n    /*\n      renderButton: Returns a button based on the state of the dapp\n    */\n    const renderButton = () =\u003e {\n      if (walletConnected) {\n        if (joinedWhitelist) {\n          return (\n            \u003cdiv className={styles.description}\u003e\n              Thanks for joining the Whitelist!\n            \u003c/div\u003e\n          );\n        } else if (loading) {\n          return \u003cbutton className={styles.button}\u003eLoading...\u003c/button\u003e;\n        } else {\n          return (\n            \u003cbutton onClick={addAddressToWhitelist} className={styles.button}\u003e\n              Join the Whitelist\n            \u003c/button\u003e\n          );\n        }\n      } else {\n        return (\n          \u003cbutton onClick={connectWallet} className={styles.button}\u003e\n            Connect your wallet\n          \u003c/button\u003e\n        );\n      }\n    };\n\n    // useEffects are used to react to changes in state of the website\n    // The array at the end of function call represents what state changes will trigger this effect\n    // In this case, whenever the value of `walletConnected` changes - this effect will be called\n    useEffect(() =\u003e {\n      // if wallet is not connected, create a new instance of Web3Modal and connect the MetaMask wallet\n      if (!walletConnected) {\n        // Assign the Web3Modal class to the reference object by setting it's `current` value\n        // The `current` value is persisted throughout as long as this page is open\n        web3ModalRef.current = new Web3Modal({\n          network: \"rinkeby\",\n          providerOptions: {},\n          disableInjectedProvider: false,\n        });\n        connectWallet();\n      }\n    }, [walletConnected]);\n\n    return (\n      \u003cdiv\u003e\n        \u003cHead\u003e\n          \u003ctitle\u003eWhitelist Dapp\u003c/title\u003e\n          \u003cmeta name=\"description\" content=\"Whitelist-Dapp\" /\u003e\n          \u003clink rel=\"icon\" href=\"/favicon.ico\" /\u003e\n        \u003c/Head\u003e\n        \u003cdiv className={styles.main}\u003e\n          \u003cdiv\u003e\n            \u003ch1 className={styles.title}\u003eWelcome to Crypto Devs!\u003c/h1\u003e\n            \u003cdiv className={styles.description}\u003e\n              Its an NFT collection for developers in Crypto.\n            \u003c/div\u003e\n            \u003cdiv className={styles.description}\u003e\n              {numberOfWhitelisted} have already joined the Whitelist\n            \u003c/div\u003e\n            {renderButton()}\n          \u003c/div\u003e\n          \u003cdiv\u003e\n            \u003cimg className={styles.image} src=\"./crypto-devs.svg\" /\u003e\n          \u003c/div\u003e\n        \u003c/div\u003e\n\n        \u003cfooter className={styles.footer}\u003e\n          Made with \u0026#10084; by Crypto Devs\n        \u003c/footer\u003e\n      \u003c/div\u003e\n    );\n  }\n  ```\n\n- Now create a new folder under the my-app folder and name it `constants`.\n- In the constants folder create a file, `index.js` and paste the following code.\n\n  ```js\n  export const WHITELIST_CONTRACT_ADDRESS = \"YOUR_WHITELIST_CONTRACT_ADDRESS\";\n  export const abi = YOUR_ABI;\n  ```\n  \n- Replace `\"YOUR_WHITELIST_CONTRACT_ADDRESS\"` with the address of the whitelist contract that you deployed.\n- Replace `\"YOUR_ABI\"` with the ABI of your Whitelist Contract. To get the ABI for your contract, go to your `hardhat-tutorial/artifacts/contracts/Whitelist.sol` folder and from your `Whitelist.json` file get the array marked under the `\"abi\"` key (it will be. a huge array, close to 100 lines if not more).\n\n\n- Now in your terminal which is pointing to `my-app` folder, execute\n\n  ```bash\n  npm run dev\n  ```\n\nYour whitelist dapp should now work without errors 🚀\n\n### Push to github\n\nMake sure before proceeding you have [pushed all your code to github](https://medium.com/hackernoon/a-gentle-introduction-to-git-and-github-the-eli5-way-43f0aa64f2e4) :)\n\n---\n\n## Deploying your dApp\n\nWe will now deploy your dApp, so that everyone can see your website and you can share it with all of your LearnWeb3 DAO friends.\n\n- Go to [Vercel](https://vercel.com/) and sign in with your GitHub\n- Then click on `New Project` button and then select your Whitelist dApp repo\n- ![](https://i.imgur.com/ZRjfkCE.png)\n- When configuring your new project, Vercel will allow you to customize your `Root Directory`\n- Click `Edit` next to `Root Directory` and set it to `my-app`\n- Select the Framework as `Next.js`\n- Click `Deploy`\n- Now you can see your deployed website by going to your dashboard, selecting your project, and copying the URL from there!\n\nShare your website in Discord :D\n\n## Verification\n\nTo verify this level, make sure you have whitelisted some addresses in your contract. Input your contract address into the Smart Contract Verification box, and select the test network you deployed on.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flearnweb3dao%2Fwhitelist-dapp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flearnweb3dao%2Fwhitelist-dapp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flearnweb3dao%2Fwhitelist-dapp/lists"}