Deploy a Testnet faucet on Polygon Network
In this demo, we will be exploring how to create a faucet for your token using solidity and deploy it to the Matic/Polygon live network. There are several reasons for a token to have a faucet. It can be a mainnet faucet used to distribute tokens to the community on the basis of some task completion, or a testnet faucet to support developers to build apps using the token, etc.,
This article will focus on explaining how to,
-
Create a Faucet Smart Contract.
-
Deploy it on Mumbai testnet.
Let’s get started
Navigate to the Remix IDE . Create a new file called Faucet.sol and add the following contents to the file.
// SPDX-License-Identifier: UNLISCENSED
pragma solidity ^0.8.4;
interface IERC20 {
/**
* @dev returns the tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev returns the decimal places of a token
*/
function decimals() external view returns (uint8);
/**
* @dev transfers the `amount` of tokens from caller's account
* to the `recipient` account.
*
* returns boolean value indicating the operation status.
*
* Emits a {Transfer} event
*/
function transfer(address recipient, uint256 amount)
external
returns (bool);
}
contract SMTFaucet {
// The underlying token of the Faucet
IERC20 token;
// The address of the faucet owner
address owner;
// For rate limiting
mapping(address=>uint256) nextRequestAt;
// No.of tokens to send when requested
uint256 faucetDripAmount = 1;
// Sets the addresses of the Owner and the underlying token
constructor (address _smtAddress, address _ownerAddress) {
token = IERC20(_smtAddress);
owner = _ownerAddress;
}
// Verifies whether the caller is the owner
modifier onlyOwner{
require(msg.sender == owner,"FaucetError: Caller not owner");
_;
}
// Sends the amount of token to the caller.
function send() external {
require(token.balanceOf(address(this)) > 1,"FaucetError: Empty");
require(nextRequestAt[msg.sender] < block.timestamp, "FaucetError: Try again later");
// Next request from the address can be made only after 5 minutes
nextRequestAt[msg.sender] = block.timestamp + (5 minutes);
token.transfer(msg.sender,faucetDripAmount * 10**token.decimals());
}
// Updates the underlying token address
function setTokenAddress(address _tokenAddr) external onlyOwner {
token = IERC20(_tokenAddr);
}
// Updates the drip rate
function setFaucetDripAmount(uint256 _amount) external onlyOwner {
faucetDripAmount = _amount;
}
// Allows the owner to withdraw tokens from the contract.
function withdrawTokens(address _receiver, uint256 _amount) external onlyOwner {
require(token.balanceOf(address(this)) >= _amount,"FaucetError: Insufficient funds");
token.transfer(_receiver,_amount);
}
}
I have deployed a simple token called the “Sample Medium Token (SMT)” on the Mumbai testnet for testing purposes, and this faucet will drip 1 SMT token (can be changed) at an interval of 5 minutes to the requesting wallet address.So let us compile the contract and deploy it to the Mumbai testnet.
For deployment, we need some testnet Matic tokens, which can be obtained from here. The steps to compile and deploy a contract using RemixIDE can also be found in the article mentioned above. During deployment, the tokenAddress and the ownerAddress should be passed for the contract initialisation.
The faucet has 4 methods.
i) *send() — *This function sends 1 SMT (default) to the requesting wallet.It should be noted that a mapping — nextRequestAt has been declared to implement a basic rate limit mechanism. There should be atleast an interval of 5 minutes in between 2 subsequent calls made from a single wallet.
ii) *setTokenAddress(address) — *This method can be used by the faucet owner/admin to update the underlying token address. For example, if we are launching a new version of the token, say *SMTv2, *we can pass the new token address to this method so that the faucet starts dripping the new token instead of the old one.
This is somewhat similar to the “Adapter method”, which is followed in the Upgradable contracts.
iii) *setFaucetDripAmount(uint256) — *Using this method, the owner can increase or decrease the number of tokens sent per request. The default value is 1 SMT.
iv) *withdrawTokens(address,uint256) — *The faucet owner can use this to withdraw the tokens from the smart contract.
We need to manually deposit some tokens into the faucet contract as soon as the contract is deployed.
Except the send() method, all other three functions can only be called by the faucet owner, hence the onlyOwner modifier is passed.
It’s time for live action
Once the contract has been successfully deployed, we can see the methods on the left bottom of the Remix IDE.
We can connect the MetaMask wallet and play around with the methods.
The send method will drip 1 SMT to the wallet, as shown below.
If we again try to force the contract the send tokens within 5 minutes, the transaction will be reverted with the error message “Try again later”
If we want to change the token or the amount to be sent per request, it can be done by calling the respective methods.
The faucet smart contract is built just for fun and, it is a basic implementation. A lot of changes can be made to the contract to make it more robust, secured and reliable. Feel free to modify the faucet as per your requirements and play around with it.
Until next time…👋👋