Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# 🧙‍♂️ What Are We Building Today?

gm everyone ☀️ We are super hyped to bring you this course where you'll build a Solidity project that takes your Web3 skills to the next level.

## So, what are we building? 🤔

We're crafting our very own **Hogwarts Sorting Hat dApp**! 🎩✨ Inspired by the legendary Harry Potter concept, this dApp will magically sort you (and your friends) into your respective Hogwarts houses.

This project is a fantastic way to sharpen your Solidity skills while having fun. By the end, you'll have built and deployed a functional dApp in the Web3 ecosystem!

Curious to see how it works? Try out the live version [here](https://jatin192-hogwarts-dapp-beta.vercel.app/). We'll be using the **Arbitrum Sepolia** testnet to power our dApp.

![Sorting Hat in Action](https://github.com/0xmetaschool/Learning-Projects/blob/main/assests_for_all/Build%20Hogwarts%20Sorting%20Cap%20dApp%20on%20the%20Polygon%20Mumbai/What%20Are%20We%20Building%20Today/Frame_3560365_(28).webp?raw=true)

## 🏆 Why Build This?

Unlock your **wizardry in Solidity** and become a Web3 spellcaster by mastering smart contract development. This interactive project makes learning Solidity engaging, ensuring that you not only understand the concepts but can also apply them in a fun way.

## 📖 Course Overview

In this course, you will:

1. **Set up a basic project** using Remix IDE⚡️
2. **Code the Hogwarts Sorting randomness** using Solidity 🎲
3. **Deploy smart contracts** on **Arbitrum Sepolia** 🌍
4. **Build a React frontend** and integrate it with the Solidity backend 🖥️
5. **Deploy the final dApp** and interact with it 🎉

🚀 **Keep the momentum going!** In lessons 3-11, we’ll dive into the most exciting parts of this course. I can’t wait to share them with you!



## 👩‍💻 Who Should Take This Course?

This course is for **intermediate Web3 developers** who want to level up their **dApp development** and **Solidity** expertise.

You should have a basic understanding of:
- Blockchain fundamentals 🏗️
- Solidity programming 📝
- Frontend technologies like React ⚛️

If you're new to Web3, don't worry! You can always reach out for help in our community. 🚀



## 🛠 Prerequisites

Before starting, make sure you have:

- The **MetaMask extension** installed in your browser ([Chrome extension link](https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn)) 🔑

> **New to MetaMask?** Check out [this guide](https://metaschool.so/courses/understand-and-setup-metamask-account) to set it up first.



## 🎖 Proof of Completion

Complete this course, and you'll earn a **special NFT** 🏅—a utility token unlocking more perks on the Metaschool platform.

Here’s what your NFT will look like:

![Completion NFT](https://github.com/0xmetaschool/Learning-Projects/blob/main/assests_for_all/Completion%20NFT.webp?raw=true)



## 📜 House Rules

Before we dive in, let’s set some ground rules:
1. **Do your assignments**—they’re designed to reinforce your learning.
2. **Join [our Discord](https://discord.gg/vbVMUwXWgc)** and ask questions.
3. **Support us by following on [X](https://bit.ly/hogwarts-dapp-twitter) & [LinkedIn](https://bit.ly/hogwarts-dapp-linkedin)** 🙌
4. **Stay positive & have fun!** 🚀

💡 **Bonus:** Complete the course within **3 days** to earn **double XP**! 🎯 Find the quest on the right side of your screen.

Alright, no more waiting—let’s dive into the magic! 🪄🙌
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# 🚀 Set Up Your Project

Ahoy, mateys! 🏴‍☠️ Ready to set sail on your Web3 adventure? Let's get your project up and running in no time. Grab your favorite snack, and let’s dive in!

## ⚙️ Prerequisites

Before we begin, make sure you have the following installed:

- [Visual Studio Code](https://code.visualstudio.com/download) - Your code’s best friend! 💻
- [Node.js](https://nodejs.org/en/download) - We’re using `v20.18.0`. Check yours with:
```sh
node --version
```
- [MetaMask](https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn) - Your gateway to the blockchain! 🦊

## 🌍 Setting Up the Testnet

We need to connect to the Arbitrum Sepolia testnet to deploy our smart contract. Follow these steps:

1. Go to [Chainlist](https://chainlist.org/chain/421614).
2. Click on **“Add to MetaMask”**.

![setup-metamask-1.png](https://github.com/0xmetaschool/Learning-Projects/blob/main/assests_for_all/one-piece-dapp/Set%20Up%20Your%20Project/setup-metamask-1.webp?raw=true)

3. Click **“Approve”** and then **“Switch network”**.

Boom! You’re now connected to Arbitrum Sepolia. 🎉 Check out the GIF below for reference:

![connect-metamask-2.gif](https://github.com/0xmetaschool/Learning-Projects/blob/main/assests_for_all/one-piece-dapp/Set%20Up%20Your%20Project/connect-metamask-2.webp?raw=true)

### Get Some Test ETH 💰

Now it’s time to fund your wallet with some test ETH! Just like Nami, we love stacking coins. 😉

1. Copy your MetaMask wallet address.
2. Go to [Chainlink Faucet](https://faucets.chain.link/arbitrum-sepolia).
3. Connect your Metamask wallet to chainlink website.
4. Paste your wallet address.
![](https://github.com/0xmetaschool/Learning-Projects/blob/main/assests_for_all/Build%20Hogwarts%20Sorting%20Cap%20dApp%20on%20the%20Polygon%20Mumbai/new_images/faucet.webp?raw=true)
5. Click **“Get Tokens”**.
6. Receive **0.5 ETH + 25 LINK** and flex on your friends! 💎

> **Troubleshooting:** If you don’t get ETH, sign up or log in to Alchemy and try again.

## 🛠️ Set Up the Remix Project

Now, let’s get our development environment ready with **Remix**, a browser-based IDE that makes smart contract development easy.

### Steps to Set Up Remix:

1. Open [Remix](https://remix.ethereum.org/) in your browser.
2. Click on **File Explorers** 📁 and create a new workspace.
3. Inside your workspace, create a new file, e.g., `OnePieceDapp.sol`.
4. Start writing your **Solidity** smart contract! 🚀


Just like **Sunny Go** is always ready to take our crew anywhere, our Remix setup is ready to launch us into Web3! 🌊

## 🎯 Wrap Up

In this lesson, we:

✅ Connected to the **Arbitrum Sepolia** testnet 🌐
✅ Got **free test ETH** 💸
✅ Set up **Remix** for writing and deploying smart contracts ✨

Next up, we’ll start coding our smart contract and take our Web3 journey to the next level! See you in the next lesson, future blockchain pirate! 🏴‍☠️
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# 🔗 Integrating Chainlink VRF on Arbitrum Sepolia

Welcome to this exciting lesson on integrating **Chainlink VRF (Verifiable Random Function)** into your smart contract on **Arbitrum Sepolia**. By the end of this module, you will have a fully functional randomness setup, crucial for fair draws, lotteries, and unpredictable outcomes in blockchain applications. Let's dive in!

## 🛠 Step 1: Connecting Your Wallet & Retrieving VRF Details

To get started, follow these steps:

1. Open [Chainlink VRF](https://vrf.chain.link/arbitrum-sepolia) in your browser.
2. Click **Connect Wallet** and authorize your **MetaMask** connection.
3. Locate and copy the VRF Coordinator Address. We'll use this in the upcoming lesson steps, so make sure to note it down.

![VRF Coordinator](https://github.com/0xmetaschool/Learning-Projects/blob/main/assests_for_all/one-piece-dapp/Secure%20Your%20Data/chainlink-1.webp?raw=true)

4. Similarly, copy the Key Hash and keep it handy. This will be required in the later steps of the lesson.

![Key Hash](https://github.com/0xmetaschool/Learning-Projects/blob/main/assests_for_all/one-piece-dapp/Secure%20Your%20Data/chainlink-2.webp?raw=true)

## 🔑 Step 2: Creating & Managing Your Subscription

Chainlink VRF requires a subscription to function. Let's create one!

1. Click **Create Subscription** and follow the prompts:
- Click **Create Subscription**.

![Create Subscription](https://github.com/0xmetaschool/Learning-Projects/blob/main/assests_for_all/one-piece-dapp/Secure%20Your%20Data/chainlink-3.webp?raw=true)

- Sign and confirm the transaction.

![Sign Transaction](https://github.com/0xmetaschool/Learning-Projects/blob/main/assests_for_all/one-piece-dapp/Secure%20Your%20Data/chainlink-3.webp?raw=true)

2. Navigate to **Home > My Subscriptions**. Find your newly created subscription and copy the **Subscription ID**.

![Subscription ID](https://github.com/0xmetaschool/Learning-Projects/blob/main/assests_for_all/one-piece-dapp/Secure%20Your%20Data/chainlink-4.webp?raw=true)

3. Update your `.env` file by replacing `<your-chainlink-vrf-subscription-id>` with the copied ID.

![Update .env](https://github.com/0xmetaschool/Learning-Projects/blob/main/assests_for_all/one-piece-dapp/Secure%20Your%20Data/chainlink-5.webp?raw=true)

## 💰 Step 3: Funding Your Subscription

Before making VRF requests, we need to **fund the subscription**. Here's how:

1. Click **Action > Fund Subscription**.

![Fund Subscription](https://github.com/0xmetaschool/Learning-Projects/blob/main/assests_for_all/one-piece-dapp/Secure%20Your%20Data/fund-subscription-1.webp?raw=true)

2. Click **Visit the Chainlink Arbitrum Sepolia Faucet** and request **25 test LINK**.

![Request LINK](https://github.com/0xmetaschool/Learning-Projects/blob/main/assests_for_all/one-piece-dapp/Secure%20Your%20Data/fund-subscription-3.webp?raw=true)

3. Return to **Subscription Page**, enter **15 LINK** in **Add Funds**, and click **Confirm**.

![Confirm Funds](https://github.com/0xmetaschool/Learning-Projects/blob/main/assests_for_all/one-piece-dapp/Secure%20Your%20Data/fund-subscription-4.webp?raw=true)

## 🎉 Wrap-up & Next Steps

Fantastic work! 🎉 You've successfully set up **Chainlink VRF** and funded your subscription. This ensures that your smart contract can now request **random numbers in a secure and verifiable way**.

In the next lesson, we'll **integrate Chainlink VRF into a Solidity smart contract** to generate truly random numbers on-chain. Get ready for some hands-on coding action!

🚀 **See you in the next lesson!**
Original file line number Diff line number Diff line change
@@ -1,18 +1,10 @@
# Create Hogwarts Contract
# 🏰 Create Hogwarts Contract

Welcome back! So we are done with setting up our project. Now it’s time to code!! Wohoo, so let’s start coding!

## Create a file
## ✨ Crafting the Hogwarts NFT

Navigate to `contracts` directory. Delete existing `Lock.sol` as we do not need it.

Create a new Solidity file called `HogwartsNFT.sol` in the `contracts` directory:

![Frame 3560364 (34).jpg](<https://github.com/0xmetaschool/Learning-Projects/blob/main/assests_for_all/Build%20Hogwarts%20Sorting%20Cap%20dApp%20on%20the%20Polygon%20Mumbai/Create%20Hogwarts%20Contract/Frame_3560364_(34).webp?raw=true>)

## Write code

We will write that does the following:
Our HogwartsNFT contract will

- Allows the owner to mint non-fungible tokens representing the four Hogwarts houses.
- Store NFTs on IPFS and associated them with a specific house.
Expand All @@ -22,7 +14,7 @@ So why wait, let’s go!

First are the license and import statements (ignore any red lines or warnings):

```
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;

Expand All @@ -37,15 +29,15 @@ import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
- `Ownable.sol` is a contract that provides a basic access control mechanism, allowing the contract owner to restrict certain functions to themselves.
- `ERC721.sol` is a contract that provides a basic implementation of ERC721 token.

```
```solidity
contract HogwartsNFT is ERC721URIStorage, Ownable {
```

- This line defines a new Solidity contract named `HogwartsNFT`.
- It inherits from two other contracts, `ERC721URIStorage` and `Ownable`.
- `ERC721URIStorage` is likely an ERC-721 token standard with URI storage for NFT metadata, and `Ownable` provides ownership functionality.

```
```solidity
mapping(uint256 => address) public s_requestIdToSender;
mapping(address => uint256) public s_addressToHouse;
mapping(address => bool) public hasMinted;
Expand All @@ -62,7 +54,7 @@ These lines declare several state variables:
- `s_addressToName`: A mapping to associate name with address.
- `s_tokenCounter`: A private variable to keep track of the number of NFTs minted.

```
```solidity
string[] internal houseTokenURIs = [
"ipfs://QmXja2QBKsNW9qnw9kKfcm25rJTomwAVJUrXekYFJnVwbg/Gryffindor.json",
"ipfs://QmXja2QBKsNW9qnw9kKfcm25rJTomwAVJUrXekYFJnVwbg/Hufflepuff.json",
Expand All @@ -74,22 +66,22 @@ string[] internal houseTokenURIs = [
- It declares an internal array called `houseTokenURIs`, which contains strings representing the URIs for the token metadata of the four Hogwarts houses (Gryffindor, Hufflepuff, Ravenclaw, Slytherin). These URIs likely point to JSON files on IPFS.
- You can even upload your own assets on IPFS using Pinata or NFTstorage and replace the IPFS links accordingly.

```
```solidity
event NftMinted(uint256 house, address minter, string name);
```

- This line defines an event called `NftMinted`, which will be called when an NFT is minted.
- It includes three parameters: the `house` (represented as a `uint256`), `minter` address, and the `name` the user will provide.

```
```solidity
constructor() ERC721("Hogwarts NFT", "HP") {
s_tokenCounter = 0;
}
```

- This is the constructor for the contract. It sets the initial state by initializing `s_tokenCounter` to 0 and also calls the constructor of the parent contract `ERC721` with the name "Hogwarts NFT" and symbol "HP."

```
```solidity
function hasMintedNFT(address _user) public view returns (bool) {
return hasMinted[_user];
}
Expand All @@ -99,7 +91,7 @@ function hasMintedNFT(address _user) public view returns (bool) {
- It allows anyone to check whether a specific address `_user` has already minted an NFT.
- It returns a boolean indicating whether the address has minted or not.

```
```solidity
function getHouseIndex(address _user) public view returns (uint256) {
return s_addressToHouse[_user];
}
Expand All @@ -108,7 +100,7 @@ function getHouseIndex(address _user) public view returns (uint256) {
- This is another public view function named `getHouseIndex`.
- It allows anyone to query the index of the Hogwarts house associated with a specific address `_user`. It returns a `uint256` representing the index.

```
```solidity

function mintNFT(address recipient, uint256 house, string memory name) external onlyOwner {
require(!hasMinted[recipient], "You have already minted your house NFT"); // Ensure the address has not minted before
Expand Down Expand Up @@ -139,7 +131,7 @@ This is a public function named `mintNFT`, which allows the contract owner (the
- `hasMinted[recipient] = true;`: This line marks the `recipient`'s address as having minted an NFT by setting the corresponding value in the `hasMinted` mapping to `true`.
- `emit NftMinted(house, recipient, name);`: Finally, this line emits the `NftMinted` event with information about the `house`, `recipient` address, and `name` of the minted NFT. This event allows external parties to listen for NFT minting events and react accordingly.

```
```solidity
function _beforeTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual override {
super._beforeTokenTransfer(from, to, firstTokenId, batchSize);

Expand All @@ -152,31 +144,33 @@ function _beforeTokenTransfer(address from, address to, uint256 firstTokenId, ui
- It enforces a custom transfer condition where transfers are only allowed from or to the zero address (`address(0)`), indicating that the tokens are **soulbound** within the Hogwarts context.
- If this condition is not met, it reverts the transaction.

## Complete code
## 🏆 Complete code

The complete code for the `HogwartsNFT.sol` is:

```
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts@4.8.0/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts@4.8.0/access/Ownable.sol";
import "@openzeppelin/contracts@4.8.0/token/ERC721/ERC721.sol";

contract HogwartsNFT is ERC721URIStorage, Ownable {
contract HogwartsNFT is ERC721URIStorage, Ownable
{
mapping(uint256 => address) public s_requestIdToSender;
mapping(address => uint256) public s_addressToHouse;
mapping(address => bool) public hasMinted;
mapping(address => string) public s_addressToName;

uint256 private s_tokenCounter;

string[] internal houseTokenURIs = [
"ipfs://QmXja2QBKsNW9qnw9kKfcm25rJTomwAVJUrXekYFJnVwbg/Gryffindor.json",
"ipfs://QmXja2QBKsNW9qnw9kKfcm25rJTomwAVJUrXekYFJnVwbg/Hufflepuff.json",
"ipfs://QmXja2QBKsNW9qnw9kKfcm25rJTomwAVJUrXekYFJnVwbg/Ravenclaw.json",
"ipfs://QmXja2QBKsNW9qnw9kKfcm25rJTomwAVJUrXekYFJnVwbg/Slytherin.json"
string[] internal houseTokenURIs =
[
"https://bronze-implicit-jellyfish-397.mypinata.cloud/ipfs/bafkreigsgls4v63azaqnc6u5bdbu6nmkgdd6mulhhslip2gzjebcor3ecm", // Gryffindor.json
"https://bronze-implicit-jellyfish-397.mypinata.cloud/ipfs/bafkreidxd3hry27eab2ye2viyufd5pdndxs436kv34wgw7wzf7yl2efjja", // Hufflepuff.json
"https://bronze-implicit-jellyfish-397.mypinata.cloud/ipfs/bafkreicforscvnzvi5ptisvtjkkttf63svwultolhgea6h6evvk2end4jq", // Ravenclaw.json
"https://bronze-implicit-jellyfish-397.mypinata.cloud/ipfs/bafkreiejzzco7wzehtkc6c5gvg3qxyfjhxwpbqwuon6hwfyaiaygbz3psq" // Slytherin.json
];

event NftMinted(uint256 house, address minter, string name);
Expand Down Expand Up @@ -222,7 +216,7 @@ contract HogwartsNFT is ERC721URIStorage, Ownable {
}
```

## Wrap up
## 🎉 Wrap up

In this lesson, we learned how to create a new Solidity contract, import existing Solidity smart contracts, and use OpenZeppelin and Chainlink libraries. We created a contract called `HogwartsNFT.sol` that allows the owner to mint non-fungible tokens representing the four Hogwarts houses. The NFTs are stored on IPFS and are associated with a specific house. The contract also enforces a custom transfer condition where transfers are only allowed from or to the zero address, indicating that the tokens are soulbound within the Hogwarts context.

Expand Down
Loading