Skip to content

Commit f8d0c9e

Browse files
restructure how to into get started
1 parent 4d3d49b commit f8d0c9e

File tree

5 files changed

+637
-1
lines changed

5 files changed

+637
-1
lines changed

docs/zkEVM/how-to/using-foundry.md

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
2+
Any smart contract deployable to the Ethereum network can be deployed easily to the Polygon zkEVM network. In this guide, we demonstrate how to deploy an ERC-721 token contract on the Polygon zkEVM network using Foundry.
3+
4+
We follow the Soulbound NFT tutorial from [this video](https://www.loom.com/share/41dcd20628774d3bbcce5edf2647312f).
5+
6+
## Set up the environment
7+
8+
Foundry is a smart contract development toolchain. It can be used to manage dependencies, compile a project, run tests and deploy smart contracts. It also lets one interact with the blockchain from the CLI or via Solidity scripts.
9+
10+
### Install Foundry
11+
12+
If you have not installed Foundry, Go to [book.getfoundry](https://book.getfoundry.sh) and select **Installation** from the side menu. Follow the instructions to download **Using Foundryup**.
13+
14+
Next, select **Creating a New Project** from the sidebar. Initialize and give your new project a name: ```forge init zkevm-sbt```
15+
16+
In case of a `library not loaded error`, you should run below command and then repeat the above process again:
17+
18+
```bash
19+
brew install libusb
20+
```
21+
22+
If you never installed Rust or need an update, visit the website [here](https://www.rust-lang.org/tools/install).
23+
24+
### Build a project and test
25+
26+
Run the command `forge build` to build the project. The output should look something like this:
27+
28+
![Successful forge build command](../../img/zkEVM/zkv-success-forge-build.png)
29+
30+
Now, test the build with `forge test`
31+
32+
![Testing Forge Build](../../img/zkEVM/zkv-test-forge-build.png)
33+
34+
You can check out the contents of the newly built project by switching to your IDE. In case of VSCode, just type: ```code .```
35+
36+
## Writing the smart contract
37+
38+
1. Find the [OpenZeppelin Wizard](https://wizard.openzeppelin.com) in your browser, and use the wizard to create an out-of-the-box NFT contract.
39+
40+
- Select the `ERC721` tab for an NFT smart contract.
41+
42+
- Name the NFT and give it an appropriate symbol. Example: Name `SoEarly` and Symbol `SOE`.
43+
44+
- Go ahead and select features for your token. Simply tick the relevant boxes.
45+
46+
- You can tick the **URI Storage** box if you wish to attach some image or special text to the token.
47+
48+
2. Open your CLI and install dependencies with this command:
49+
50+
```bash
51+
npm install @openzeppelin/contracts-upgradeable
52+
```
53+
54+
3. Remap dependencies to easy-to-read filenames with the command:
55+
56+
```bash
57+
forge remappings > remappings.txt
58+
```
59+
60+
4. Inside the new `remapping.txt` file, rename the referencing `openzeppelin-contracts` to `openzeppelin`, which is the name used when importing. That is, change `openzeppelin-contracts/=lib/openzeppelin-contracts` → `openzeppelin/=lib/openzeppelin-contracts`.
61+
62+
5. Copy the smart contract code in OpenZeppelin: **Copy to Clipboard**
63+
64+
6. In the IDE, open a new `.sol` file, name it and paste the copied code to this file. This is in fact the actual smart contract for the NFT.
65+
66+
## Add control on token transfers
67+
68+
The aim here is to put rules in place stipulating that the token cannot be transferred without burning it.
69+
70+
- Go to the [OpenZeppelin documentation](https://docs.openzeppelin.com/).
71+
72+
- Look up the signature by searching for `_beforetokentransfererc721`.
73+
74+
- Scroll down to `ERC 721` and copy the corresponding text on the right side:
75+
76+
```c
77+
_beforeTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal
78+
```
79+
80+
- Create a new function in the code for the smart contract token called `_beforeTokenTransfer`
81+
82+
```c
83+
function _beforeTokenTransfer (address from, address to, uint256 firstTokenId, uint256 batchSize) internal override {
84+
require(from==address(0) || to==address(0), "Soulbound: cannot transfer");
85+
super._beforeTokenTransfer(from, to, firstTokenId, batchSize);
86+
}
87+
```
88+
89+
## Set a token URI (optional)
90+
91+
A token URI is a function that returns the address where the metadata of a specific token is stored. The metadata is a `. json` file where all the data associated with the NFT is stored. Our aim here is to attach some image to the created token.
92+
93+
The stored data typically consists of the name of the token, brief description and URL where the image is stored.
94+
95+
- Choose an image and give it a name relatable to the token
96+
97+
- Find some free of charge IPFS storage for the image, like [NFT.STORAGE](https://nft.storage)
98+
99+
- Upload the image to the storage using your GitHub account
100+
101+
## Add URI json file
102+
103+
This is the file that contains the metadata for the token which includes the image address (i.e., the IPFS address of the image).
104+
105+
- In the IDE, create a new `.json` file which you can call `tokenuri.json`
106+
107+
- Populate the `tokenuri.json` file with the token-name, description and URL where the image is stored:
108+
109+
```json
110+
{
111+
"title": "So Early",
112+
"description": "I was super duper early to the Polygon zkEVM",
113+
"image": "<IPFS address>" /* remove the forward-slash at the end of the URL, if any */
114+
}
115+
```
116+
117+
- Upload the `tokenuri.json` file to the same storage where the image was uploaded
118+
119+
- Copy the address to the `Sbt.sol` inside the `safeMint` function
120+
121+
- Remove the `uri` parameter so as to hardcode it. This results in all minted tokens sharing the same uri image, but each token's `tokenId` differs from the previous one by 1.
122+
123+
## Populate the `.env` file
124+
125+
In order to deploy on the zkEVM Testnet, populate the `.env` file in the usual way. That is,
126+
127+
- Create a `.env.sample` file within the `src` folder
128+
129+
- Populate `.env.sample` file with your `ACCOUNT_PRIVATE_KEY` and the zkEVM Testnet's `RPC URL` found [here](../get-started/quick-start.md). So the `.env.sample` file looks like this:
130+
131+
```json
132+
RPC_URL="https://rpc.public.zkevm-test.net"
133+
PVTKEY="<insert private key here>"
134+
```
135+
136+
- Copy the contents of the `.env.sample` file to the `.env` file,
137+
138+
```bash
139+
cp .env.sample .env
140+
```
141+
142+
!!!warning
143+
144+
Make sure `.env` is in the `.gitignore` file to avoid uploading your `ACCOUNT_PRIVATE_KEY`.
145+
146+
## Deploy your contract
147+
148+
1. In the CLI, use the following command to ensure grabbing variables from `.env`:
149+
150+
```bash
151+
source .env
152+
```
153+
154+
2. Check if the correct `RPC URL` is read from the `.env` file:
155+
156+
```bash
157+
echo $RPC_URL
158+
```
159+
160+
3. You can now use the next command:
161+
162+
```bash
163+
forge create --rpc-url $RPC_URL --private-key $PRIVATE_KEY src/{ContractFile.sol}:{ContractName} --legacy
164+
```
165+
166+
which executes the following:
167+
168+
- Does a `forge create`.
169+
- Passes the `RPC_URL` and `PVTKEY`.
170+
- References the actual smart contract.
171+
172+
For example, when deploying the `Sbt.sol` contract, the command looks like this:
173+
174+
```bash
175+
forge create --rpc-url $RPC_URL --private-key $PRIVATE_KEY src/Sbt.sol:SoEarly --legacy
176+
```
177+
178+
The above command compiles and deploys the contract to the zkEVM Testnet. The output on the CLI looks like this one below.
179+
180+
![Successful Deploy Sbt.sol](../../img/zkEVM/zkv-success-deploy-sbtdotsol.png)
181+
182+
## Check deployed contract in explorer
183+
184+
- Copy the address of your newly deployed contract (i.e. the `Deployed to:` address as in the above example output).
185+
186+
- Go to the [zkEVM Testnet Explorer](https://cardona-zkevm.polygonscan.com/), and paste the address in the `Search by address` field.
187+
188+
- Check `Transaction Details` reflecting the `From` address, which is the owner's address and the `To` address, which is the same `Deployed to:` address seen in the CLI.

0 commit comments

Comments
 (0)