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
60 changes: 34 additions & 26 deletions src/pages/lessons/projects/2.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ and copy this code inside:

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.12;
pragma solidity 0.8.20;

contract ProjectNFT {
}
Expand Down Expand Up @@ -358,7 +358,7 @@ This is what we need in our code:

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.12;
pragma solidity 0.8.20;

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

Expand Down Expand Up @@ -395,7 +395,7 @@ which we can use as our ID for each new token created:

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.12;
pragma solidity 0.8.20;

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

Expand Down Expand Up @@ -437,7 +437,7 @@ NFT:

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.12;
pragma solidity 0.8.20;

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

Expand Down Expand Up @@ -500,7 +500,7 @@ Here's the modifications we will add and I'll explain them below:

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.12;
pragma solidity 0.8.20;

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

Expand Down Expand Up @@ -793,7 +793,7 @@ deployed contract to the console.
Before we run our script, we need to tell Hardhat what Solidity version our
contracts are using. For that, we need to go into the `hardhat.config.js` file
in our project's root folder. Find the line that says `solidity: '0.8.xx',` and
replace the `0.8.xx` for the pragma used in our contract: `0.8.12`.
replace the `0.8.xx` for the pragma used in our contract: `0.8.20`.

We could have used a range of Solidity versions e.g. `^0.8.0` in our contract,
but we like to promote best practices by choosing a fixed Solidity version and
Expand Down Expand Up @@ -872,17 +872,16 @@ going to run the deploy again, but this time to a testnet.
What is a testnet? It is a basically a whole running blockchain, but it runs
only so people can try stuff out. On it, you have ETH, NFTs, or other tokens but
they have no monetary value. This way, you can develop and test your contracts
without fear of losing anything valuable. Ethereum has many testnets, and you
might notice that we used _Goerli_ testnet. But we suggest that you use
without fear of losing anything valuable. Ethereum has many testnets, and we suggest that you use
_Sepolia_ testnet, now that it has compatible NFT hosting support, and longevity
for app development that _Goerli_ won't outlast.
for app development.

Before we go any further, let's take an extra step for precaution. In the next
project we'll learn how to use collaborative tools to store our projects, but
for now, let's open our root directory's `.gitignore` file and add this line:

```bash
hardhat.config.js
.env
```

In order to deploy to a real testnet we'll need:
Expand All @@ -895,7 +894,7 @@ In order to deploy to a real testnet we'll need:
[#3](https://faucet.quicknode.com/ethereum/sepolia)
- An API Key from an Ethereum RPC Node Provider
([Alchemy](https://www.alchemy.com/), [Infura](https://infura.io/),
[Ankr](https://rpc.ankr.com/eth_goerli))
[Ankr](https://rpc.ankr.com/eth_sepolia))
- A minor change in the Hardhat configuration file

First and foremost, **security**. We are exploring new grounds, experimenting,
Expand Down Expand Up @@ -936,27 +935,36 @@ We are going to replace our file with this:

```jsx
require("@nomicfoundation/hardhat-toolbox");

const WALLET_PRIVATE_KEY = "YOUR-PRIVATE-KEY-DONT-SHARE";

const RPC_API_KEY = "YOUR-API-KEY-FROM-INFURA-OR-ALCHEMY";
require("dotenv").config();

/**
* @type import('hardhat/config').HardhatUserConfig
*/
module.exports = {
solidity: "0.8.12",
solidity: "0.8.20",
networks: {
goerli: {
url: RPC_API_KEY,
accounts: [WALLET_PRIVATE_KEY],
sepolia: {
url: process.env.RPC_URL,
accounts: [process.env.PRIVATE_KEY],
},
},
};
```

And you'll need to set the two global variables using the `const` keyword with
your own values for Hardhat to communicate correctly to the network.
We strongly recommend using a `.env` file to store your sensitive information. This is a common practice among professional developers to keep secrets out of their source code.

First, install the `dotenv` package:

```bash
npm install dotenv
```

Then, create a `.env` file in your project root and add your keys:

```bash
RPC_URL=YOUR-API-KEY-FROM-INFURA-OR-ALCHEMY
PRIVATE_KEY=YOUR-PRIVATE-KEY-DONT-SHARE
```

We have already gone through how to get your API KEY.

Expand All @@ -965,11 +973,11 @@ to open Metamask, click on the three dots next to your _Account Name_, and then
on _Account Details_, then click on _Export Private Key_. It will ask for your
Metamask password - the one you use to open it, NOT your seed phrase. It also
issues a warning to 'Never disclose this key'. Confirm and you'll be able to
copy your private key. Paste it in to our `hardhat.config.js`
copy your private key. Paste it into your `.env` file.

Please, if you are already a developer, and you plan to use Git to store your
project, don't store your `hardhat.config.js` on it, because you will have your
private key there.
project, don't store your `.env` file on it, because you will have your
private key there. That's why we added it to our `.gitignore` file earlier.

<SideDrawer
buttonText="Checkpoint Questions"
Expand Down Expand Up @@ -1006,7 +1014,7 @@ Remember we are deploying to the actual blockchain, a testnet, but a blockchain
nonetheless.

Now that we have run the deploy script, **delete the private key and the RPC API
key from `hardhat.config.js`** to minimize the handling of the wallet. In the
key from your `.env` file** to minimize the handling of the wallet. In the
next project we will learn about tools to collaborate and store your projects
online.

Expand All @@ -1016,7 +1024,7 @@ Just go to [Sepolia Etherscan](https://sepolia.etherscan.io/) (or
deployed contract.

You can view my links as an example on
[Etherscan](https://goerli.etherscan.io/address/0x166A82F7cD8F7BA9D8C10b2cc792C1A20084564d)
[Etherscan](https://sepolia.etherscan.io/)
and [Opensea](https://testnets.opensea.io/collection/d-d-academy)

![opensea.png](/assets/lessons/2/img_20.png)
Expand Down
56 changes: 28 additions & 28 deletions src/pages/lessons/projects/3.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ the same name:

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.12;
pragma solidity 0.8.20;

contract TierNFT {
}
Expand All @@ -251,7 +251,7 @@ We add a constructor to our contract, which will mirror the one from `ERC721.sol

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.12;
pragma solidity 0.8.20;

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

Expand All @@ -269,7 +269,7 @@ remember what `++` does to our total supply?

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.12;
pragma solidity 0.8.20;

import '@openzeppelin/contracts/token/ERC721/ERC721.sol';

Expand Down Expand Up @@ -300,7 +300,7 @@ go into **gas optimisation** for you in a future lesson.

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.12;
pragma solidity 0.8.20;

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

Expand Down Expand Up @@ -350,7 +350,7 @@ so, you'll definitely know `if else`!

// constructor...

function mint() public payable {
function mint() public payable {
require(
msg.value >= TIER_VALUE_0,
"Not enough value for the minimum Tier"
Expand All @@ -365,7 +365,7 @@ so, you'll definitely know `if else`!
tokenTier[totalSupply] = tierId;
}

// We will add more code here
// We will add more code here
}
```

Expand All @@ -390,7 +390,7 @@ through the code and find out.
<summary>**View full code here**</summary>
```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.12;
pragma solidity 0.8.20;

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

Expand Down Expand Up @@ -469,7 +469,7 @@ it into the contract! Nifty, eh?
override
returns (string memory)
{
require(_exists(tokenId), "Nonexistent token");
_requireOwned(tokenId);

string memory imageSVG = "PLACEHOLDER FOR SVG IMAGE";

Expand All @@ -489,7 +489,7 @@ it into the contract! Nifty, eh?
return string(abi.encodePacked("data:application/json;base64,", json));
}

// We will add more code here
// We will add more code here
}
```

Expand All @@ -498,7 +498,7 @@ Let’s stop to break it down and examine it a little.
- Within the `tokenURI` function, you'll notice `override`, an `ERC721` function
we'll use, since we are not creating a separate JSON file to store images or
other services, but creating it right here in the contract.
- We also added `require(_exists(tokenId). "Nonexistent token");`. According to
- We also added `_requireOwned(tokenId);`. According to
the ERC-721 specification, it is required to throw an error if the NFT doesn't
exist.
- `imageSVG` is a placeholder for our image, and we will deal with it a bit
Expand All @@ -523,9 +523,9 @@ TokenID were `3`, our JSON would end up look something like this:

```solidity
{
"name": "TierNFT #3",
"description": "TierNFTs collection",'
"image": "data:image/svg+xml;base64,A_BUNCH_OF_BASE64_LETTERS_AND_NUMBERS_HERE"
"name": "TierNFT #3",
"description": "TierNFTs collection",'
"image": "data:image/svg+xml;base64,A_BUNCH_OF_BASE64_LETTERS_AND_NUMBERS_HERE"
}
```

Expand All @@ -534,7 +534,7 @@ TokenID were `3`, our JSON would end up look something like this:
<summary>**here’s the updated code**</summary>
```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.12;
pragma solidity 0.8.20;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/utils/Base64.sol";
Expand Down Expand Up @@ -574,7 +574,7 @@ uint256) public tokenTier;
override
returns (string memory)
{
require(_exists(tokenId), "Nonexistent token");
_requireOwned(tokenId);

string memory imageSVG = "PLACEHOLDER FOR SVG IMAGE";

Expand Down Expand Up @@ -666,7 +666,7 @@ Standard.
<summary>**View updated code**</summary>
```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.12;
pragma solidity 0.8.20;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/utils/Base64.sol";
Expand Down Expand Up @@ -712,7 +712,7 @@ contract TierNFT is ERC721 {
override
returns (string memory)
{
require(_exists(tokenId), "Nonexistent token");
_requireOwned(tokenId);

string memory tierName = tokenTier[tokenId] == 2
? TIER_NAME_2
Expand Down Expand Up @@ -763,7 +763,7 @@ And inherit `Ownable` from the OpenZeppelin contract into our own.

contract TierNFT is ERC721, Ownable {

// Our whole contract code here
// Our whole contract code here

}
```
Expand All @@ -774,7 +774,7 @@ all of it! Let’s get this withdraw function coded in here!
```solidity
// tokenURI function part of the code...

// Function to withdraw funds from contract
// Function to withdraw funds from contract
function withdraw() public onlyOwner {
// Check that we have funds to withdraw
uint256 balance = address(this).balance;
Expand All @@ -785,7 +785,7 @@ all of it! Let’s get this withdraw function coded in here!
require(success, "Withdraw failed");
}

// 'withdraw' will be our last function at the end of the contract
// 'withdraw' will be our last function at the end of the contract

}
```
Expand Down Expand Up @@ -815,7 +815,7 @@ all of it! Let’s get this withdraw function coded in here!
<summary>**View the Full Contract Here**</summary>
```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.12;
pragma solidity 0.8.20;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
Expand All @@ -835,7 +835,7 @@ contract TierNFT is ERC721, Ownable { uint256 public totalSupply;
mapping(uint256 => uint256) public tokenTier;

constructor(string memory _name, string memory _symbol)
ERC721(_name, _symbol) {}
ERC721(_name, _symbol) Ownable(msg.sender) {}

function mint() public payable {
require(
Expand All @@ -860,7 +860,7 @@ mapping(uint256 => uint256) public tokenTier;
override
returns (string memory)
{
require(_exists(tokenId), "Nonexistent token");
_requireOwned(tokenId);

string memory tierName = tokenTier[tokenId] == 2
? TIER_NAME_2
Expand Down Expand Up @@ -987,10 +987,10 @@ require("dotenv").config();

/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
solidity: "0.8.12",
solidity: "0.8.20",
networks: {
mumbai: {
url: "https://rpc-mumbai.maticvigil.com",
amoy: {
url: "https://rpc-amoy.polygon.technology",
accounts: [process.env.PRIVATE_KEY],
},
},
Expand Down Expand Up @@ -1078,7 +1078,7 @@ to keep your wallet safe and **unwanted guests out**.
We will deploy our smart contract by using this command:

```bash
npx hardhat run scripts/deploy.js --network mumbai
npx hardhat run scripts/deploy.js --network amoy
```

We specify the network where we want the contract to be deployed using the
Expand Down Expand Up @@ -1179,7 +1179,7 @@ main().catch((error) => {
To mint our tier NFTs we will run the following command.

```bash
npx hardhat run scripts/mint.js --network mumbai
npx hardhat run scripts/mint.js --network amoy
```

If we look at our terminal we will see something like this.
Expand Down
Loading