- // SPDX-License-Identifier: MIT
- pragma solidity ^0.8.0;
- // Import ERC20 interface and other necessary contracts
- import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
- import "@openzeppelin/contracts/access/Ownable.sol";
- contract VPNIDGenerator is Ownable {
- IERC20 public sVPNToken;
- uint256 public nextID;
- uint256 constant public IDLength = 15;
- uint256 public paymentAmountMonthly = 200000; // Default monthly payment amount
- uint256 public paymentAmountYearly = 2200000; // Default yearly payment amount, assuming some discount or different rate
- event IDGenerated(address indexed payer, string indexed generatedID, string paymentType);
- event TokenContractUpdated(address indexed newTokenContract);
- event MonthlyPaymentAmountUpdated(uint256 newPaymentAmount);
- event YearlyPaymentAmountUpdated(uint256 newPaymentAmount);
- mapping(address => string[]) public userIDs; // Mapping to store user IDs against wallet address
- mapping(string => bool) public usedIDs; // Mapping to track used IDs
- constructor(address _sVPNTokenAddress, address initialOwner) Ownable(initialOwner) {
- sVPNToken = IERC20(_sVPNTokenAddress);
- nextID = 1;
- }
- modifier validPayment(uint256 paymentAmount) {
- require(sVPNToken.allowance(msg.sender, address(this)) >= paymentAmount, "Insufficient allowance");
- require(sVPNToken.balanceOf(msg.sender) >= paymentAmount, "Insufficient balance");
- _;
- }
- function payForUniqueIDMonthly() external validPayment(paymentAmountMonthly) {
- require(sVPNToken.transferFrom(msg.sender, address(this), paymentAmountMonthly), "Token transfer failed");
- string memory generatedID = generateUniqueID();
- userIDs[msg.sender].push(generatedID);
- emit IDGenerated(msg.sender, generatedID, "Monthly");
- }
- function payForUniqueIDYearly() external validPayment(paymentAmountYearly) {
- require(sVPNToken.transferFrom(msg.sender, address(this), paymentAmountYearly), "Token transfer failed");
- string memory generatedID = generateUniqueID();
- userIDs[msg.sender].push(generatedID);
- emit IDGenerated(msg.sender, generatedID, "Yearly");
- }
- function generateUniqueID() internal returns (string memory) {
- bytes memory characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
- bytes memory result = new bytes(IDLength);
- uint256 rand = uint256(keccak256(abi.encodePacked(block.timestamp, block.difficulty, nextID))) % characters.length;
- for (uint256 i = 0; i < IDLength; i++) {
- if (i == IDLength - 1) {
- result[i] = bytes1(uint8(48 + (rand % 10))); // ASCII code for numbers 0-9
- } else {
- result[i] = characters[rand % characters.length];
- }
- rand = rand / characters.length;
- }
- string memory newID = string(result);
- // Check if the ID already exists, regenerate if necessary
- while (usedIDs[newID]) {
- rand = uint256(keccak256(abi.encodePacked(rand))) % characters.length;
- for (uint256 i = 0; i < IDLength; i++) {
- if (i == IDLength - 1) {
- result[i] = bytes1(uint8(48 + (rand % 10))); // ASCII code for numbers 0-9
- } else {
- result[i] = characters[rand % characters.length];
- }
- rand = rand / characters.length;
- }
- newID = string(result);
- }
- usedIDs[newID] = true;
- nextID++;
- return newID;
- }
- function getUserIDs(address userAddress) external view returns (string[] memory) {
- return userIDs[userAddress];
- }
- function withdrawTokens(uint256 _amount) external onlyOwner {
- require(sVPNToken.transfer(owner(), _amount), "Token transfer failed");
- }
- function updateTokenContract(address _newTokenContract) external onlyOwner {
- require(_newTokenContract != address(0), "Invalid token contract address");
- sVPNToken = IERC20(_newTokenContract);
- emit TokenContractUpdated(_newTokenContract);
- }
- function updateMonthlyPaymentAmount(uint256 _newPaymentAmount) external onlyOwner {
- require(_newPaymentAmount > 0, "Invalid payment amount");
- paymentAmountMonthly = _newPaymentAmount;
- emit MonthlyPaymentAmountUpdated(_newPaymentAmount);
- }
- function updateYearlyPaymentAmount(uint256 _newPaymentAmount) external onlyOwner {
- require(_newPaymentAmount > 0, "Invalid payment amount");
- paymentAmountYearly = _newPaymentAmount;
- emit YearlyPaymentAmountUpdated(_newPaymentAmount);
- }
- }