Artists and content material creators have a singular potential to monetize their work as a consequence of blockchain know-how, particularly NFTs.
Artists are not reliant on galleries or public sale homes to promote their artwork. As a substitute, 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 undertaking’s whitelist.
Stipulations
Be certain to have Node.js or npm put in in your pc. When you do not, click on here.
Venture Setup and Set up
Let’s create a brand new folder/listing for our undertaking, 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 undertaking by working the command under:
npx hardhat
We’ll go along with the next choices:
- A pattern undertaking.
- Settle for all different requests.
Having hardhat-waffle
and hardhat-ethers
put in is required for the pattern undertaking.
Simply in case it did not set up robotically, 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 the whole lot is working, run the next code:
npx hardhat check
If the whole lot is working because it ought to, you will see a handed check lead to your console:
Now, delete sample-test.js
from the check 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 format is essential, so listen! 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("Hi there! 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 important = async () => {
const whitelistContractFactory = await hre.ethers.getContractFactory(
"Whitelist"
);
const whitelistContract = await whitelistContractFactory.deploy();
await whitelistContract.deployed();
console.log("Whitelist Contract deployed to: ", whitelistContract.tackle);
};
const runMain = async () => {
strive {
await important();
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
It is best 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 important = async () => {
const [deployer] = await hre.ethers.getSigners();
const accountBalance = await deployer.getBalance();
console.log("Deploying contracts with account: ", deployer.tackle);
console.log("Account steadiness: ", accountBalance.toString());
const Token = await hre.ethers.getContractFactory("Whitelist");
const portal = await Token.deploy();
await portal.deployed();
console.log("Whitelist tackle: ", portal.tackle);
};
const runMain = async () => {
strive {
await important();
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
information respectively.
Replace the Whitelist.sol
file with the next code snippet:
pragma solidity ^0.8.0;
contract Whitelist {
uint256 public maxNumberOfWhitelistedAddresses;
uint256 public numberOfAddressesWhitelisted;
tackle proprietor;
mapping(tackle => bool) whitelistedAddresses;
constructor(uint256 _maxWhitelistedAddresses) {
proprietor = msg.sender;
maxNumberOfWhitelistedAddresses = _maxWhitelistedAddresses;
}
modifier onlyOwner() {
require(msg.sender == proprietor, "Error: Caller will not be the proprietor");
_;
}
perform addUserAddressToWhitelist(tackle _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(tackle _whitelistedAddress)
public
view
returns (bool)
{
bool userIsWhitelisted = whitelistedAddresses[_whitelistedAddress];
return userIsWhitelisted;
}
perform isWhitelisted(tackle _whitelistedAddress)
public
view
returns (bool)
{
return whitelistedAddresses[_whitelistedAddress];
}
perform removeUserAddressFromWhitelist(tackle _addressToRemove)
public
onlyOwner
{
require(
whitelistedAddresses[_addressToRemove],
"Error: Sender will not 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 (tackle) {
return proprietor;
}
}
Replace the deploy.js
file within the script
listing with the next code snippet:
const important = async () => {
const portal = await Token.deploy(5);
await portal.deployed();
console.log("Whitelist tackle: ", portal.tackle);
};
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 primary check 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 check
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.tackle).to.be.a("string");
count on(whitelistContract.tackle).to.not.be.null;
});
it("ought to permit tackle 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 permit tackle 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 tackle 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 permit tackle 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 check with the next command:
npx hardhat check
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 have to create an Alchemy account.
We’ll publish our contract creation transaction with Alchemy. The transaction might be mined and added to the blockchain as a sound transaction.
After you join, we’ll create an app just like the one under. Keep in mind to change the community to Mumbai, the place we’ll be deploying.
We’ll have to seize our keys, as proven under, and retailer them for later use:
To make use of the Testnet, we’ll want some pretend MATIC tokens in our Testnet account, so we’ll request some from Polygon Mumbai utilizing a faucet.
This “pretend” 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 undertaking listing:
require("@nomiclabs/hardhat-waffle");
require("dotenv").config();
activity("accounts", "Prints the checklist of accounts", async (taskArgs, hre) => {
const accounts = await hre.ethers.getSigners();
for (const account of accounts) {
console.log(account.tackle);
}
});
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 likewise 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 personal key. Thankfully, getting our personal key is not that onerous. 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.
This is the hyperlink to the repository in an effort to examine 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 crew of curated writers brings out new sources that can assist you uncover the universe of web3. Test us out for extra on NFTs, DAOs, blockchains, and the decentralized future.