Artists and content material creators have a novel potential to monetize their work because of blockchain know-how, particularly NFTs.
Artists are now not reliant on galleries or public sale homes to promote their artwork. As an alternative, they’ll promote it on to the patron 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 sensible contract, enabling us so as to add, take away, validate, and confirm if a person is a part of a challenge’s whitelist.
Conditions
Be sure that to have Node.js or npm put in in your laptop. In case you do not, click on here.
Challenge Setup and Set up
Let’s create a brand new folder/listing for our challenge, 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 challenge by working the command under:
npx hardhat
We’ll go together with the next choices:
- A pattern challenge.
- Settle for all different requests.
Having hardhat-waffle
and hardhat-ethers
put in is required for the pattern challenge.
Simply in case it did not set up routinely, we are going to 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 thing is working, run the next code:
npx hardhat take a look at
If every thing is working because it ought to, you will see a handed take a look at lead to 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 listen! We’ll begin with essentially the most fundamental construction of any contract.
pragma solidity ^0.8.0;
import "hardhat/console.sol";
contract Whitelist {
constructor() {
console.log("Good day! from Whitelist Contract");
}
}
To construct and deploy our sensible 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.handle);
};
const runMain = async () => {
attempt {
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 sensible contract we wrote earlier.
Let’s run it with the next command:
npx hardhat run scripts/run.js
You need to see one thing much like this:
Now, we now have a working sensible 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 under:
const foremost = async () => {
const [deployer] = await hre.ethers.getSigners();
const accountBalance = await deployer.getBalance();
console.log("Deploying contracts with account: ", deployer.handle);
console.log("Account steadiness: ", accountBalance.toString());
const Token = await hre.ethers.getContractFactory("Whitelist");
const portal = await Token.deploy();
await portal.deployed();
console.log("Whitelist handle: ", portal.handle);
};
const runMain = async () => {
attempt {
await foremost();
course of.exit(0);
} catch (error) {
console.error(error);
course of.exit(1);
}
};
runMain();
Earlier than deploying, let’s be certain that our native blockchain node is working in a separate terminal with the next command:
npx hardhat node
Subsequent, we’ll deploy our sensible 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 sensible 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;
handle proprietor;
mapping(handle => bool) whitelistedAddresses;
constructor(uint256 _maxWhitelistedAddresses) {
proprietor = msg.sender;
maxNumberOfWhitelistedAddresses = _maxWhitelistedAddresses;
}
modifier onlyOwner() {
require(msg.sender == proprietor, "Error: Caller shouldn't be the proprietor");
_;
}
perform addUserAddressToWhitelist(handle _addressToWhitelist)
public
onlyOwner
{
require(
!whitelistedAddresses[_addressToWhitelist],
"Error: Sender already been whitelisted"
);
require(
numberOfAddressesWhitelisted < maxNumberOfWhitelistedAddresses,
"Error: Whitelist Restrict exceeded"
);
whitelistedAddresses[_addressToWhitelist] = true;
numberOfAddressesWhitelisted += 1;
}
perform verifyUserAddress(handle _whitelistedAddress)
public
view
returns (bool)
{
bool userIsWhitelisted = whitelistedAddresses[_whitelistedAddress];
return userIsWhitelisted;
}
perform isWhitelisted(handle _whitelistedAddress)
public
view
returns (bool)
{
return whitelistedAddresses[_whitelistedAddress];
}
perform removeUserAddressFromWhitelist(handle _addressToRemove)
public
onlyOwner
{
require(
whitelistedAddresses[_addressToRemove],
"Error: Sender shouldn't be whitelisted"
);
whitelistedAddresses[_addressToRemove] = false;
numberOfAddressesWhitelisted -= 1;
}
perform getNumberOfWhitelistedAddresses() public view returns (uint256) {
return numberOfAddressesWhitelisted;
}
perform getMaxNumberOfWhitelistedAddresses()
public
view
returns (uint256)
{
return maxNumberOfWhitelistedAddresses;
}
perform getOwner() public view returns (handle) {
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 handle: ", portal.handle);
};
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.
Sensible Contract Unit Testing
On this part, we’ll write a fundamental take a look at to check out essentially the most important features 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.handle).to.be.a("string");
count on(whitelistContract.handle).to.not.be.null;
});
it("ought to permit handle 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("mustn't permit handle 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 permit handle 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("mustn't permit handle 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 much like the picture under:
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 must create an Alchemy account.
We’ll publish our contract creation transaction with Alchemy. The transaction can be mined and added to the blockchain as a sound transaction.
After you enroll, we’ll create an app just like the one under. Bear in mind to change the community to Mumbai, the place we’ll be deploying.
We’ll must seize our keys, as proven under, 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 challenge listing:
require("@nomiclabs/hardhat-waffle");
require("dotenv").config();
job("accounts", "Prints the listing of accounts", async (taskArgs, hre) => {
const accounts = await hre.ethers.getSigners();
for (const account of accounts) {
console.log(account.handle);
}
});
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 have been learn from the .env
file, in addition to the import
on the prime of require("dotenv").config()
. This means that we have to set up the dotenv
bundle and in addition create a .env
file utilizing the command under:
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. Thankfully, getting our non-public key is not that arduous. Try this post.
Sensible Contract Deployment to Polygon Community
It is time to deploy our software on the Polygon community.
Let’s run the command under to deploy our contract to a blockchain community:
npx hardhat run scripts/deploy.js --community mumbai
We must always have one thing much like this:
We are able to confirm our contract deployment on Polygon Mumbai Network.
Here is the hyperlink to the repository with the intention to test the code or in case you missed something:
Conclusion
We constructed a whitelist sensible contract on this article and deployed it to the Polygon Testnet.
This text is part of the Hashnode Web3 blog, the place a staff of curated writers brings out new sources that will help you uncover the universe of web3. Test us out for extra on NFTs, DAOs, blockchains, and the decentralized future.