Artists and content material creators have a novel potential to monetize their work because of blockchain know-how, particularly NFTs.
Artists are not reliant on galleries or public sale homes to promote their artwork. As a substitute, they will promote it on to the buyer as an NFT, permitting them to maintain a extra significant slice of the revenue.
This text will information us by means of constructing and deploying an NFT whitelist good contract, enabling us so as to add, take away, validate, and confirm if a consumer is a part of a mission’s whitelist.
Conditions
Make certain to have Node.js or npm put in in your laptop. For those who do not, click on here.
Venture Setup and Set up
Let’s create a brand new folder/listing for our mission, whitelist-project
within the terminal. We’ll work on this listing by means of the course of this tutorial. Within the listing we simply created, run the next instructions:
npm init -y
npm set up --save-dev hardhat
Let’s get a pattern mission by working the command beneath:
npx hardhat
We’ll go along with the next choices:
- A pattern mission.
- Settle for all different requests.
Having hardhat-waffle
and hardhat-ethers
put in is required for the pattern mission.
Simply in case it did not set up robotically, we’ll set up it manually with the next command:
npm set up --save-dev @nomiclabs/hardhat-waffle ethereum-waffle chai @nomiclabs/hardhat-ethers ethers
To verify every part is working, run the next code:
npx hardhat take a look at
If every part is working because it ought to, you may see a handed take a look at end in your console:
Now, delete sample-test.js
from the take a look at folder, sample-script.js
from the scripts
folder, and Greeter.sol
from the contracts
folder.
The folders themselves shouldn’t be deleted.
We’ll create a Whitelist.sol
file contained in the contracts
listing. When utilizing Hardhat, file structure is essential, so concentrate! We’ll begin with probably the most primary construction of any contract.
pragma solidity ^0.8.0;
import "hardhat/console.sol";
contract Whitelist {
constructor() {
console.log("Hey! from Whitelist Contract");
}
}
To construct and deploy our good contract, we’ll navigate to the scripts
folder, create a brand new run.js
file, and replace it with the next code snippet:
const foremost = async () => {
const whitelistContractFactory = await hre.ethers.getContractFactory(
"Whitelist"
);
const whitelistContract = await whitelistContractFactory.deploy();
await whitelistContract.deployed();
console.log("Whitelist Contract deployed to: ", whitelistContract.deal with);
};
const runMain = async () => {
strive {
await foremost();
course of.exit(0);
} catch (error) {
console.log(error);
course of.exit(1);
}
};
runMain();
Within the code snippet above, we have created a script
that lets us deploy the good contract we wrote earlier.
Let’s run it with the next command:
npx hardhat run scripts/run.js
It’s best to see one thing just like this:
Now, we now have a working good contract. Let’s deploy it to our native community.
Within the scripts
folder, let’s create a deploy.js
file and replica and paste the code beneath:
const foremost = async () => {
const [deployer] = await hre.ethers.getSigners();
const accountBalance = await deployer.getBalance();
console.log("Deploying contracts with account: ", deployer.deal with);
console.log("Account stability: ", accountBalance.toString());
const Token = await hre.ethers.getContractFactory("Whitelist");
const portal = await Token.deploy();
await portal.deployed();
console.log("Whitelist deal with: ", portal.deal with);
};
const runMain = async () => {
strive {
await foremost();
course of.exit(0);
} catch (error) {
console.error(error);
course of.exit(1);
}
};
runMain();
Earlier than deploying, let’s make sure that our native blockchain node is working in a separate terminal with the next command:
npx hardhat node
Subsequent, we’ll deploy our good contract:
npx hardhat run scripts/deploy.js --community localhost
We must always have one thing like this:
Constructing a Whitelist
On this part, we’ll replace the good contract Whitelist.sol
and deploy.js
recordsdata respectively.
Replace the Whitelist.sol
file with the next code snippet:
pragma solidity ^0.8.0;
contract Whitelist {
uint256 public maxNumberOfWhitelistedAddresses;
uint256 public numberOfAddressesWhitelisted;
deal with proprietor;
mapping(deal with => bool) whitelistedAddresses;
constructor(uint256 _maxWhitelistedAddresses) {
proprietor = msg.sender;
maxNumberOfWhitelistedAddresses = _maxWhitelistedAddresses;
}
modifier onlyOwner() {
require(msg.sender == proprietor, "Error: Caller isn't the proprietor");
_;
}
operate addUserAddressToWhitelist(deal with _addressToWhitelist)
public
onlyOwner
{
require(
!whitelistedAddresses[_addressToWhitelist],
"Error: Sender already been whitelisted"
);
require(
numberOfAddressesWhitelisted < maxNumberOfWhitelistedAddresses,
"Error: Whitelist Restrict exceeded"
);
whitelistedAddresses[_addressToWhitelist] = true;
numberOfAddressesWhitelisted += 1;
}
operate verifyUserAddress(deal with _whitelistedAddress)
public
view
returns (bool)
{
bool userIsWhitelisted = whitelistedAddresses[_whitelistedAddress];
return userIsWhitelisted;
}
operate isWhitelisted(deal with _whitelistedAddress)
public
view
returns (bool)
{
return whitelistedAddresses[_whitelistedAddress];
}
operate removeUserAddressFromWhitelist(deal with _addressToRemove)
public
onlyOwner
{
require(
whitelistedAddresses[_addressToRemove],
"Error: Sender isn't whitelisted"
);
whitelistedAddresses[_addressToRemove] = false;
numberOfAddressesWhitelisted -= 1;
}
operate getNumberOfWhitelistedAddresses() public view returns (uint256) {
return numberOfAddressesWhitelisted;
}
operate getMaxNumberOfWhitelistedAddresses()
public
view
returns (uint256)
{
return maxNumberOfWhitelistedAddresses;
}
operate getOwner() public view returns (deal with) {
return proprietor;
}
}
Replace the deploy.js
file within the script
listing with the next code snippet:
const foremost = async () => {
const portal = await Token.deploy(5);
await portal.deployed();
console.log("Whitelist deal with: ", portal.deal with);
};
Within the code snippet above, we up to date the deploy.js
script by specifying 5
within the constructor as the utmost variety of addresses to be whitelisted.
Good Contract Unit Testing
On this part, we’ll write a primary take a look at to check out probably the most crucial capabilities we’ll use.
To take action, we’ll create a whitelist-test.js
file contained in the take a look at
listing and write the next code:
const { count on, use } = require("chai");
const { ethers } = require("hardhat");
describe("Whitelist", async () => {
let whitelist;
let whitelistContract;
earlier than(async () => {
whitelist = await ethers.getContractFactory("Whitelist");
whitelistContract = await whitelist.deploy(5);
});
it("ought to deploy", async () => {
count on(whitelistContract.deal with).to.be.a("string");
count on(whitelistContract.deal with).to.not.be.null;
});
it("ought to enable deal with to be added to whitelist", async () => {
const whitelistAddress = "0x0000000000000000000000000000000000000000";
await whitelistContract.addUserAddressToWhitelist(whitelistAddress);
const isWhitelisted = await whitelistContract.isWhitelisted(
whitelistAddress
);
count on(isWhitelisted).to.be.true;
});
it("shouldn't enable deal with to be added to whitelist if already whitelisted", async () => {
const whitelistAddress = "0x0000000000000000000000000000000000000009";
await whitelistContract.addUserAddressToWhitelist(whitelistAddress);
const isWhitelisted = await whitelistContract.isWhitelisted(
whitelistAddress
);
count on(isWhitelisted).to.be.true;
});
it("ought to enable deal with to be faraway from whitelist if already whitelisted", async () => {
const whitelistAddress = "0x0000000000000000000000000000000000000009";
await whitelistContract.removeUserAddressFromWhitelist(whitelistAddress);
const isWhitelisted = await whitelistContract.isWhitelisted(
whitelistAddress
);
count on(isWhitelisted).to.be.false;
});
it("shouldn't enable deal with to be faraway from whitelist if not whitelisted", async () => {
const whitelistAddress = "0x0000000000000000000000000000000000000000";
await whitelistContract.removeUserAddressFromWhitelist(whitelistAddress);
const isWhitelisted = await whitelistContract.isWhitelisted(
whitelistAddress
);
count on(isWhitelisted).to.be.false;
});
it("ought to return variety of whitelisted addresses", async () => {
const whitelistAddress = "0x0000000000000000000000000000000000000000";
await whitelistContract.addUserAddressToWhitelist(whitelistAddress);
const numberOfWhitelistedAddresses =
await whitelistContract.getNumberOfWhitelistedAddresses();
count on(numberOfWhitelistedAddresses).to.equal(1);
});
it("ought to return the utmost variety of whitelisted addresses", async () => {
const maxNumberOfWhitelistedAddresses =
await whitelistContract.getMaxNumberOfWhitelistedAddresses();
count on(maxNumberOfWhitelistedAddresses).to.equal(5);
});
it("ought to return the proprietor of the contract", async () => {
const proprietor = await whitelistContract.getOwner();
count on(proprietor).to.be.a("string");
count on(proprietor).to.not.be.null;
});
});
Subsequent, let’s run the take a look at with the next command:
npx hardhat take a look at
We must always have one thing just like the picture beneath:
RPC(Distant Process Name) Setup
Let’s arrange an RPC and deploy the contract to the blockchain.
Earlier than deploying to the blockchain, we’ll have to create an Alchemy account.
We’ll publish our contract creation transaction with Alchemy. The transaction will probably be mined and added to the blockchain as a sound transaction.
After you join, we’ll create an app just like the one beneath. Bear in mind to change the community to Mumbai, the place we’ll be deploying.
We’ll have to seize our keys, as proven beneath, and retailer them for later use:
To make use of the Testnet, we’ll want some faux MATIC tokens in our Testnet account, so we’ll request some from Polygon Mumbai utilizing a faucet.
This “faux” MATIC can solely be used on the Testnet.
We are able to seize some MATIC tokens here.
Allow us to replace the hardhat.config.js
file within the root mission listing:
require("@nomiclabs/hardhat-waffle");
require("dotenv").config();
activity("accounts", "Prints the record of accounts", async (taskArgs, hre) => {
const accounts = await hre.ethers.getSigners();
for (const account of accounts) {
console.log(account.deal with);
}
});
module.exports = {
solidity: "0.8.4",
networks: {
mumbai: {
url: course of.env.STAGING_ALCHEMY_KEY,
accounts: [process.env.PRIVATE_KEY],
},
},
};
Within the code snippet above, some keys had been learn from the .env
file, in addition to the import
on the high of require("dotenv").config()
. This suggests that we have to set up the dotenv
package deal and in addition create a .env
file utilizing the command beneath:
npm set up -D dotenv
contact .env
Contained in the .env
file, let’s add the next keys:
STAGING_ALCHEMY_KEY=
PRIVATE_KEY=
Within the code above, we have to put our non-public key. Fortuitously, getting our non-public key is not that arduous. Take a look at this post.
Good Contract Deployment to Polygon Community
It is time to deploy our utility on the Polygon community.
Let’s run the command beneath to deploy our contract to a blockchain community:
npx hardhat run scripts/deploy.js --community mumbai
We must always have one thing just like this:
We are able to confirm our contract deployment on Polygon Mumbai Network.
Here is the hyperlink to the repository so that you could test the code or in case you missed something:
Conclusion
We constructed a whitelist good contract on this article and deployed it to the Polygon Testnet.
This text is part of the Hashnode Web3 blog, the place a workforce of curated writers brings out new sources that will help you uncover the universe of web3. Examine us out for extra on NFTs, DAOs, blockchains, and the decentralized future.