Skip to content

Smart Contract Distribution

Distribution through a smart contract is a good way to implement the distribution as well as other requirements/logic in more secure and decentralized manner.

It’s important to take in consideration that the sFUEL distribution should be handle carefully. This means sFUEL should be given in small amounts (suggested amount: 0.00001 sFUEL) and it’s crucial to make sure no unauthorized address can drain all sFUEL given to the distribution contract.

Implementation Example

pragma solidity ^0.8.19;
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
contract NFT is ERC1155, AccessControl, ReentrancyGuard{
bytes32 public constant MANAGER_ROLE = keccak256("MANAGER_ROLE");
bytes32 public constant WHITELIST_ROLE = keccak256("WHITELIST_ROLE");
uint256 public amount = 0.00001 ether;
uint256 public currentTokenID;
event Whitelist(address indexed to);
event AmountUpdated(uint256 indexed originalAmount, uint256 indexed newAmount, address indexed signer);
event Mint(address indexed to, uint256 tokenId);
event UpdateCurrentTokenId(uint256 indexed tokenId);
constructor(string memory _baseURI) ERC1155(_baseURI){
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
_grantRole(MANAGER_ROLE, msg.sender);
currentTokenID = 0;
}
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC1155, AccessControl)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
function setBaseURI(string memory newBaseURI) external onlyRole(DEFAULT_ADMIN_ROLE) {
_setURI(newBaseURI);
}
/**
Update amount to distribute to user
*/
function updateAmount(uint256 _newAmount) external onlyRole(MANAGER_ROLE) {
require(_newAmount > 0, "sFUEL_Distribution: Invalid Amount");
uint256 originalAmount = amount;
amount = _newAmount;
emit AmountUpdated(originalAmount, amount, msg.sender);
}
/**
Update of the current tokenId
*/
function updateCurrentTokenId(uint256 newTokenId) external onlyRole(MANAGER_ROLE) {
currentTokenID = newTokenId;
emit UpdateCurrentTokenId(newTokenId);
}
/**
Whitelists address to be allowed to mint. It also distributes sFUEL in order to perform the mint transaction
*/
function whitelist(address to) external onlyRole(MANAGER_ROLE) {
require(!hasRole(WHITELIST_ROLE, to), "AlreadyWhitelisted");
if(to.balance < 0.000005 ether){
require(address(this).balance >= amount, "ContractOutOfSFuel");
payable(to).transfer(amount);
emit Whitelist(to);
}
_grantRole(WHITELIST_ROLE, to);
}
/**
Mint transaction with access control
*/
function mint() public onlyRole(WHITELIST_ROLE) nonReentrant {
require(balanceOf(msg.sender, currentTokenID) == 0, "Address already owns a token");
_mint(msg.sender, currentTokenID, 1, "");
_revokeRole(WHITELIST_ROLE, msg.sender);
emit Mint(msg.sender, currentTokenID);
}
/**
* @dev function to receive Ether. msg.data must be empty
*/
receive() external payable {}
}