You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: pages/lessons/projects/3.mdx
+33-34Lines changed: 33 additions & 34 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -44,6 +44,7 @@ In the previous lesson, we talked about NFTs and their use cases. Unlike traditi
44
44
<Questionquestion="lesson-2/1-intro/Q5" />
45
45
</SideDrawer>
46
46
<br/>
47
+
47
48
**Now that we have set the stage, it's time to dive into the exciting world of tiered NFTs and uncover the unique superpowers they possess. By the end of this tutorial, you will have gained a wealth of knowledge and accomplished the following steps**:
48
49
49
50
- Setting up the development environment
@@ -68,16 +69,15 @@ We will guide you through each step, ensuring a fun and comprehensive learning e
68
69
## First things first 👷♂️
69
70
{/* PART 2 ASSERTIONS AND DATA TYPES e.g. MAPPINGS */}
70
71
71
-
Before we start coding, we need to create our project template. We are going to follow
72
-
the same steps as in previous lessons. Using `npm` as our package manager, we'll create
72
+
Before we start coding, we need to create our project template by following
73
+
the same steps as in the previous *Build a Basic NFT* lesson. Make a note of
74
+
these steps and what they do, for you will use them a lot in
75
+
the future. Using `npm` as our package manager, we'll create
73
76
a Hardhat project and remove the default files we don't need.
74
77
75
-
If you’ve done our previous lesson, it’s the exact same process. Make a note of
76
-
remembering these steps and what they do, for we will use them a lot in
77
-
the future.
78
78
79
79
Let’s first open a console and `cd` into our `d_d_academy` folder, or create it
80
-
first if you don't have it. Then let's create a folder for our NFT project and make sure to `cd` into it too:
80
+
first if you haven't already. Then create a folder for our TierNFT project and make sure to `cd` into it too:
81
81
82
82
```bash
83
83
## (OPTIONAL) create a folder for our D_D Academy projects
In a Hardhat project, the default folders are supposed to be for:
135
+
In a Hardhat project, some of the default folders are:
136
136
137
-
- `contracts/` is where the source files for your contracts should be.
138
-
- `scripts/` is where simple automation scripts go.
139
-
- `test/` is where your tests should go.
137
+
- `contracts/` where the source files for your contracts should be.
138
+
- `scripts/` where simple automation scripts go.
139
+
- `test/` where your tests should go.
140
140
141
-
We want to delete some of the default files so we start fresh, e.g. we will create our own .sol file for our contract, etc:
141
+
We want to delete the default files inside the folders so we start afresh, i.e. we will create our own .sol file for our own contract, etc:
142
142
143
143
```bash
144
144
rm contracts/*.sol
@@ -178,15 +178,15 @@ contract TierNFT {
178
178
```
179
179
180
180
Now that we have our license, Solidity version and the
181
-
contract defined, we can add the logic and the variables we need to store.
182
-
183
-
## What do we need?
184
-
### we sort of need this 'intro' at the start of the lesson......
181
+
contract defined, we can add the logic and the variables we need to store. As we are creating tiers for the categories of our NFTs, we need to also store information about tiers in our contracts. We'll write our smart contract step by step in five stages:
185
182
186
-
As we are creating tiers for the categories of our NFTs, we need to also store
187
-
information about tiers in our contracts. We'll write our smart contract step by step in four stages.
183
+
-add mint function
184
+
-add tiers to utilise in mint function
185
+
- create basic TokenURI function
186
+
- enhance TokenURI function with SVG file
187
+
-add withdraw function
188
188
189
-
### Inheriting OpenZeppelin ERC721 and addinga Mint Function
189
+
### Adda Mint Function
190
190
191
191
Let’s get started by inheriting OpenZeppelin's ERC721.sol like we did last time. We add a constructor to our contract, which will mirror the one from ERC721.sol.
192
192
@@ -229,9 +229,9 @@ contract TierNFT is ERC721 {
229
229
230
230
```
231
231
232
-
### Adding Tiers and Using Them in the Mint Function
232
+
### Add Tiers
233
233
234
-
Next, to make our code neat and easily readable, just before the contract declaration add the tier Name and Value state variables, and assign their values, where each one represents a service subscription. Note that we assign the `constant` keyword, which is what it sounds like, meaning the values won't change, which also cuts down a lot on gas costs. Always good to know, but we'll go into 'gas optimisation' for you in a future lesson.
234
+
Next, to make our code neat and easily readable, just before the contract declaration add the tier Name and Value state variables, and assign their values, where each one represents a service subscription. Note that we assign the `constant` keyword, which is what it sounds like, meaning the values won't change, which also cuts down a lot on gas costs. Always good to know, but we'll go into **gas optimisation** for you in a future lesson.
235
235
236
236
```solidity
237
237
// SPDX-License-Identifier: MIT
@@ -264,9 +264,9 @@ contract TierNFT is ERC721 {
264
264
}
265
265
````
266
266
267
-
We have added `Basic`, `Medium` and `Premium` as tiers and assigned their values. We store the tier each NFT holds in `mapping(uint256 => uint256) public tokenTier;`. Mappings are widely used in Solidity, having many advantages. They are a great way to organise and access data efficiently, and therefore cheaply through 'key: value' pairs e.g. an address to a balance. We can also use nested mappings to allow for more complex data structures.
267
+
We have added `Basic`, `Medium` and `Premium` as tiers and assigned their values. We store the tier each NFT holds in `mapping(uint256 => uint256) public tokenTier;`. Mappings are widely used in Solidity, having many advantages. They are a great way to organise and access data efficiently, and therefore cheaply through **key: value** pairs e.g. a balance **value** maps to an address **key**. We can also use nested mappings to allow for more complex data structures.
268
268
269
-
Now we need to modify the mint function with logic that can access the three NFT tiers separately. We use a 'conditional' `if/else if` statement to achieve this. If you've done any coding before now, you'll probably know `if`, and if so, you'll definitely know `if else`!
269
+
Now we need to modify the mint function with logic that can access the three NFT tiers separately. We use a **conditional** `if/else if` statement to achieve this. If you've done any coding before now, you'll probably know `if`, and if so, you'll definitely know `if else`!
270
270
271
271
```solidity
272
272
// state variables and contract definition...
@@ -297,9 +297,10 @@ Now we need to modify the mint function with logic that can access the three NFT
297
297
298
298
The mint function selects tiers based on the amount of native token it receives stored in `msg.value`.
299
299
300
-
The `require` statement is a simple and powerful built-in function of Solidity you'll be using a lot in the future. It checks if the 1st parameter is true or false. On true, it does nothing, allowing execution to continue normally, but on false it throws an exception that reverts everything we modified in the transaction. In our case, if we send the function zero token value, it will 'revert' with a "Not enough value for the minimum Tier" message, and stop executing. Otherwise we can select the tier we want..... as long as we can afford it!
300
+
The `require` statement is a simple and powerful built-in function of Solidity you'll be using a lot in the future. It checks if the 1st parameter is true or false. On true, it does nothing, allowing execution to continue normally, but on false it throws an exception that reverts everything we modified in the transaction. In our case, if we send the function zero token value, it will **revert** with a "Not enough value for the minimum Tier" message, and stop executing. Otherwise we can select the tier we want..... as long as we can afford it!
301
301
302
-
We already have two `uint256` variables declared. You might wonder which one is which inside the `tokenTier` mapping? See if you can track through the code and find out - DEFO NEED A QUESTION OR TWO ON THIS - TO GET THAT ANSWER! AND ALSO TO CHECK ON STATE AND LOCAL VARIABLES e.g. `tierId` is declared with `0`.
302
+
We already have two `uint256` variables declared. You might wonder which one is which inside the `tokenTier` mapping? See if you can track through the code and find out.
303
+
{/* DEFO NEED A QUESTION OR TWO ON THIS - TO GET THAT ANSWER! AND ALSO TO CHECK ON STATE AND LOCAL VARIABLES e.g. `tierId` is declared with `0`. */}
303
304
304
305
<br/>
305
306
<details>
@@ -346,7 +347,6 @@ contract TierNFT is ERC721 {
346
347
</details>
347
348
<br/>
348
349
349
-
CHECKPOINT QUESTIONS ⁉️ <br />
350
350
<SideDrawer buttonText="Checkpoint Questions" title="Creating a Robust Development Environment">
351
351
<Question question="lesson-3/<# of section block+section name/Q1" />
When we inherited Open Zeppelin's ERC721, it gave us a function for `tokenURI` where we can store an image, a video, or much more. With the help of this ERC721 contract we have the ability to define **a base path** for creating a
364
364
unique URI which adds the token ID to the end of it.
@@ -373,7 +373,7 @@ Next, we import `Base64.sol` which encodes the tokenURI so it can return a JSON
373
373
374
374
Remember how we talked about this token ID at the end of the URI? `Strings.sol` will write it as a string inside the JSON file. Go ahead and import the magic of these two files to your contract.
375
375
376
-
For this lesson we won’t be creating a separate JSON file. We will actually code it into the contract.
376
+
For this lesson we won’t be creating a separate JSON file. We will actually code it into the contract. Nifty, eh?
377
377
378
378
```solidity
379
379
// mint function part of the code...
@@ -416,9 +416,9 @@ Let’s stop to break it down and examine it a little.
416
416
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.
417
417
- We also added `require(_exists(tokenId). "Nonexistent token");` . According to ERC721 specification, it is required to throw an error if the NFT doesn't exist.
418
418
-`imageSVG` is a placeholder for our image, and we will deal with it a bit later.
419
-
-`Base64.encode` is for encoding the JSON into Base64 so browsers can translate
419
+
-`Base64.encode` is for encoding the JSON into Base64, so browsers can translate
420
420
it into a file much in the same way as a file attached to an email.
421
-
-`string( abi.encodePacked () )` concatenates the string in a similar way to our previous lessons.
421
+
-`string( abi.encodePacked () )` concatenates (joins together) the string in a similar way to in our *Getting Started...* lesson.
422
422
423
423
This is the JSON format of our metadata:
424
424
@@ -515,9 +515,9 @@ uint256) public tokenTier;
515
515
</details>
516
516
<br/>
517
517
518
-
### Complete TokenURI function with our SVG
518
+
### Complete TokenURI function with SVG
519
519
520
-
Okay. We've done a bunch of things with our contract and now we're going to do some scalable vector graphic magic!
520
+
Okay. We've done a bunch of things with our contract, and now we're going to do some scalable vector graphic magic!
521
521
522
522
Add these lines right above the other constants defined for the tiers:
Here, we prepared the start and end of our SVG. We can test this out by joining
531
-
the start and end of the SVG into this [online svg editor](https://editsvgcode.com/).
530
+
Here, we prepared the start and end of our SVG. We can test this out by replacing the code in [online svg editor](https://editsvgcode.com/) with the start and end values we have provided above.
532
531
533
532
And now some more modifications. Inside the tokenURI function, right below `require(…)`, add these lines:
534
533
@@ -654,7 +653,7 @@ contract TierNFT is ERC721 {
654
653
</details>
655
654
<br/>
656
655
657
-
### Where are all our funds??? We need a withdraw Function!
656
+
### Where are all our funds? Add withdraw Function
658
657
659
658
We need to find a way to actually withdraw any funds our contract generates, otherwise they'll get stuck **in the contract** .... that we created!
0 commit comments