creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "contracts/GnomeReferral.sol": {
        "content": "// SPDX-License-Identifier: MIT\n/*\n\n░██████╗░███╗░░██╗░█████╗░███╗░░░███╗███████╗██╗░░░░░░█████╗░███╗░░██╗██████╗░\n██╔════╝░████╗░██║██╔══██╗████╗░████║██╔════╝██║░░░░░██╔══██╗████╗░██║██╔══██╗\n██║░░██╗░██╔██╗██║██║░░██║██╔████╔██║█████╗░░██║░░░░░███████║██╔██╗██║██║░░██║\n██║░░╚██╗██║╚████║██║░░██║██║╚██╔╝██║██╔══╝░░██║░░░░░██╔══██║██║╚████║██║░░██║\n╚██████╔╝██║░╚███║╚█████╔╝██║░╚═╝░██║███████╗███████╗██║░░██║██║░╚███║██████╔╝\n░╚═════╝░╚═╝░░╚══╝░╚════╝░╚═╝░░░░░╚═╝╚══════╝╚══════╝╚═╝░░╚═╝╚═╝░░╚══╝╚═════╝░\n\n                                   ╓╓╓▄▄▄▓▓█▓▓▓▓▀▀▀▀▀▀▓█\n                             ╓▄██▀╙╙░░░░░░░░░░░░░░░░╠╬║█\n                        ╓▄▓▀╙░░░░░░░░░░░░░░░░░░░░░░╠╠╠║▌\n                     ╓█╩░░░░░░░░░░░░░░░░░░░░░░░░░░╠╠╠╠║▌\n                   ▄█▒░░░░░░░░░░░░░▒▄██████▄▄░░░░░╠╠╠╠║▌\n                 ╓██▀▀▀╙╙╚▀░░░░░▄██╩░░░░░░░░╙▀█▄▒░╠╠╠╠╬█\n              ╓▓▀╙░░░░░░░░░░░░░╚╩░░░░░░░░░░░░░░╙▀█╠╠╠╠╬▓\n             ▄╩░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░╠╠╠╠╠║▌\n            ║██▓▓▓▓▓▄▄▒░░░░░░░░░░░▄▄██▓█▄▄▒░░░░░░░╠╠╠╠╠╬█\n           ╔▀         ╙▀▀█▓▄▄▄██▀╙       └╙▀█▄▒░░░╠╠╠╠╠╠║▌\n          ║█▀▀╙╙╙▀▀▓▄╖       ▄▄▓▓▓▓╗▄▄╓      ╙╙█▄▒░╠╠╠╠╠╬█\n        ╓▀   ╓╓╓╓╓╓   ╙█▄ ▄▀╙          ╙▀▓▄      ╙▀▓▒▒╠╠╠║▌\n        ▐██████████╙╙▀█▄ ╙█▄▓████████▀▀╗▄           █▀███╬█\n        █║██████▌ ██    ╙██╓███████╙▀█   └▀╗╓       ║▒   ╙╙▓\n       ╒▌╫███████╦╫█     ║ ╫███████╓▄█▌     └█╕     ║▌    ▀█▀▀\n        █╚██████████    ╓╣ ║██████████▒    ╔▀╙      ║▒     └█\n       ┌╣█╣████████╓╓▄▓▓▒▄█▄║████████▌╓╗╗▀╙        ╓█        ╚▄\n       │█▄╗▀▀╙      ╙▀╙         ╙▀▀██▒            ▄█          ╙▄\n     █▒                               ╙▀▀▀▀╠█▌╓▄▓▀             ║\n      ╙█╓           ╓╓                   ╓██╩║▌                ║\n       ╓╣███▄▄▄▄▓██╬╬╠╬███▄▄▄▄╓╓╓╓╓▄▄▄▓█╬╬▒░░╠█             ╔ ┌█\n      ╓▌  ▀█╬╬▒╠╠╠╠░▒░░░╠╠╠╚╚╚╩╠╠╠╠╬███▀╩░░░▄█        ▓      █▀\n     ╒▌   ╘█░╚╚╚╚╚▀▀▀▀▀▀▀▀▀▀▀▀▀▀╚╚╚░░░░░░▄█▀╙         ║      ▐▌\n     ╟     └▀█▄▒▒▒░░░░░░░░░░░▒▒▒▒▒▄▄█▓╝▀╙                    ▐▌\n     ║░        ╙╙▀▀▀▀▀▀▀▀▀▀▀▀▀▀╙╙                        ╓   █\n      █                                                  ▓ ╓█\n      ║▌   ╔                                            ╔█▀\n       █   ╚▄                              ╓╩          ╔▀\n       ╚▌   ╙                             ▓▀         ╓█╙\n        ╙▌          ▐                  ╓═    ▄    ╓▄▀╙\n          ▀▄        ╙▒                      ▄██▄█▀\n            ╙▀▄╓║▄   └                    ▄╩\n                ╙▀█                   ╓▄▀▀\n                   ▀▓        ▄▄▓▀▀▀▀╙\n                     └▀╗▄╓▄▀╙\n    \n    \nhttps://www.gnomeland.money/\nhttps://twitter.com/Gnome0xLand\n\n$GNOMES\n$GNOME\n\nEverywhere...\n\n*/\npragma solidity ^0.8.20;\n\ninterface IGNOME {\n    function balanceOf(address account) external view returns (uint256);\n    function transfer(address recipient, uint256 amount) external returns (bool);\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n    function approve(address spender, uint256 amount) external returns (bool);\n}\n\ninterface IGNOMENFT {\n    function getTokenId() external view returns (uint256);\n    function mint(address fren) external returns (uint256);\n}\n\ncontract GnomeReferrals {\n    IGNOME public gnomeToken;\n\n    address public owner;\n    mapping(address => bool) public isSignedUp;\n    mapping(string => address) public referralCodeToAddress;\n    mapping(string => bool) public usedReferralCodes;\n    mapping(address => address) public referedBy;\n    mapping(uint256 => address) public tokenIdReferedBy;\n    mapping(address => bool) public isAuth;\n    mapping(address => uint256) public referralRewardsETH;\n    mapping(address => uint256) public referralRewardsGNOME;\n    bytes private constant CHARACTERS = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\";\n    uint256 private constant CHARACTERS_LENGTH = 62;\n    uint256 private referralCodeCounter = 0;\n    bool public referralopen = true;\n\n    uint256 public mintPriceETHReferral = 0.015 ether;\n    uint256 public referralPriceGnome = 100 ether;\n    uint256 public maxReferralLevels = 3;\n    uint256 public referralPrice = 1001 ether;\n    bool public mintETH = true;\n    mapping(address => string[]) public referralCodesByAddress;\n    modifier onlyAuth() {\n        require(msg.sender == owner || isAuth[msg.sender], \"Caller is not the authorized\");\n        _;\n    }\n\n    // Constructor\n    constructor(address gnome) {\n        owner = msg.sender;\n        isAuth[msg.sender] = true;\n        referralCodeCounter = 0;\n        gnomeToken = IGNOME(gnome);\n    }\n\n    // Modifier to restrict access to owner only\n    modifier onlyOwner() {\n        require(msg.sender == owner, \"Caller is not the owner\");\n        _;\n    }\n\n    event NewSignUp(address indexed user, string referralCode);\n    event ReferralCodeGenerated(address indexed user, string referralCode);\n\n    function setMiContracts(address _gnome) external onlyOwner {\n        gnomeToken = IGNOME(_gnome);\n    }\n\n    function setmintPriceETH(uint256 price) public onlyOwner {\n        mintPriceETHReferral = price;\n    }\n\n    function setmintToken(bool isETH) public onlyOwner {\n        mintETH = isETH;\n    }\n\n    function setReferralPriceGNOME(uint256 newPrice) public onlyOwner {\n        referralPriceGnome = newPrice;\n    }\n\n    function frensFundus() public payable onlyOwner {\n        (bool success, ) = payable(msg.sender).call{value: address(this).balance}(\"\");\n        require(success);\n    }\n\n    function somethingAboutTokens(address token) external onlyOwner {\n        uint256 balance = IGNOME(token).balanceOf(address(this));\n        IGNOME(token).transfer(msg.sender, balance);\n    }\n\n    function calculateReward(uint256 amount, uint level) internal pure returns (uint256) {\n        if (level == 0) {\n            return (amount * 10) / 100; // 10% for direct referral\n        } else if (level == 1) {\n            return (amount * 1) / 100; // 1% for the referrer of the referrer\n        } else if (level == 2) {\n            return (amount * 1) / 1000; // 0.1% for the referrer of the referrer of the referrer\n        }\n        return 0;\n    }\n\n    function signUpReferral(string memory code, address sender, uint gnomeAmount) public onlyAuth {\n        require(!isSignedUp[sender], \"Already signed up\");\n        require(!usedReferralCodes[code], \"Referral code already used\");\n        require(referralCodeToAddress[code] != address(0), \"Invalid referral code\");\n\n        isSignedUp[sender] = true;\n        usedReferralCodes[code] = true;\n        referedBy[sender] = referralCodeToAddress[code];\n        deleteReferralCode(referralCodeToAddress[code], code);\n\n        address currentReferrer = sender;\n        uint256 remainingReward = mintPriceETHReferral * gnomeAmount;\n        uint256 reward = calculateReward(remainingReward, 0);\n        referralRewardsETH[currentReferrer] += reward;\n        currentReferrer = referedBy[currentReferrer];\n\n        emit NewSignUp(msg.sender, code);\n    }\n\n    function generateReferralCode() public returns (string memory) {\n        require(\n            isSignedUp[msg.sender] || msg.sender == owner || msg.sender == address(this),\n            \"Not authorized to generate code\"\n        );\n        if (msg.sender != owner) {\n            require(gnomeToken.balanceOf(msg.sender) >= referralPriceGnome, \"Not enough gnome tokens\");\n            gnomeToken.transferFrom(msg.sender, address(this), referralPriceGnome);\n        }\n        return _generateReferralCode();\n    }\n\n    function _generateReferralCode() internal returns (string memory) {\n        referralCodeCounter++;\n        bytes memory code = new bytes(6);\n\n        for (uint256 i = 0; i < 6; i++) {\n            uint256 rand = uint256(\n                keccak256(abi.encodePacked(referralCodeCounter, block.difficulty, block.timestamp, i))\n            );\n            code[i] = CHARACTERS[rand % CHARACTERS_LENGTH];\n        }\n\n        string memory newCode = string(abi.encodePacked(\"gnome-ETH-\", string(code)));\n        referralCodeToAddress[newCode] = msg.sender;\n        referralCodesByAddress[msg.sender].push(newCode);\n\n        emit ReferralCodeGenerated(msg.sender, newCode);\n        return newCode;\n    }\n\n    function getReferralCodesByAddress(address userAddress) public view returns (string[] memory) {\n        return referralCodesByAddress[userAddress];\n    }\n\n    function claimRewardsETH() public {\n        uint256 reward = referralRewardsETH[msg.sender];\n        require(reward > 0, \"No rewards to claim\");\n\n        referralRewardsETH[msg.sender] = 0;\n        payable(msg.sender).transfer(reward);\n    }\n\n    function claimGNOME() public {\n        uint256 reward = referralRewardsGNOME[msg.sender];\n        require(reward > 0, \"No rewards to claim\");\n\n        // Reset the user's referral reward balance\n        referralRewardsGNOME[msg.sender] = 0;\n\n        // Transfer the gnome tokens from the contract to the user\n        require(gnomeToken.transfer(msg.sender, reward), \"Transfer failed\");\n    }\n\n    function uintToString(uint256 _i) internal pure returns (string memory) {\n        if (_i == 0) {\n            return \"0\";\n        }\n        uint256 j = _i;\n        uint256 length;\n        while (j != 0) {\n            length++;\n            j /= 10;\n        }\n        bytes memory bstr = new bytes(length);\n        uint256 k = length;\n        while (_i != 0) {\n            k = k - 1;\n            uint8 temp = (48 + uint8(_i - (_i / 10) * 10));\n            bytes1 b1 = bytes1(temp);\n            bstr[k] = b1;\n            _i /= 10;\n        }\n        return string(bstr);\n    }\n\n    function deleteReferralCode(address referalAddress, string memory codeToDelete) private {\n        int256 indexToDelete = -1;\n        for (uint i = 0; i < referralCodesByAddress[referalAddress].length; i++) {\n            if (keccak256(bytes(referralCodesByAddress[referalAddress][i])) == keccak256(bytes(codeToDelete))) {\n                indexToDelete = int256(i);\n                break;\n            }\n        }\n\n        if (indexToDelete != -1) {\n            removeCodeAtIndex(uint256(indexToDelete), referalAddress);\n        }\n    }\n\n    // Helper function to remove a code from the array at a given index\n    function removeCodeAtIndex(uint256 index, address userAddress) private {\n        require(index < referralCodesByAddress[userAddress].length, \"Index out of bounds\");\n\n        // Move the last element into the place to delete and pop the last element\n        referralCodesByAddress[userAddress][index] = referralCodesByAddress[userAddress][\n            referralCodesByAddress[userAddress].length - 1\n        ];\n        referralCodesByAddress[userAddress].pop();\n    }\n\n    function setIsAuth(address fren, bool isAuthorized) external onlyAuth {\n        isAuth[fren] = isAuthorized;\n    }\n\n    function setOpen(bool _open) external onlyAuth {\n        referralopen = _open;\n    }\n\n    function getTokenIdReferedBy(uint256 tokenId) public view returns (address) {\n        return tokenIdReferedBy[tokenId];\n    }\n\n    function getReferedBy(address fren) public view returns (address) {\n        return referedBy[fren];\n    }\n\n    // Additional functions like transferring ownership can be added if needed\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 200,
        "details": {
          "yul": true
        }
      },
      "viaIR": true,
      "evmVersion": "paris",
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "metadata": {
        "useLiteralContent": true
      },
      "libraries": {}
    }
  }}