FunToken

0x4d7b52e644d830d47510440477cb50295d9a8148

Verification
Verified
v0.8.26+commit.8a97fa7a
Type
Contract
5,101 bytes
ABI entries
27
13 read · 5 write
License
none

Contract information

Address
0x4d7b52e644d830d47510440477cb50295d9a8148
Chain
Robinhood Chain (4663)
Compiler
v0.8.26+commit.8a97fa7a
Optimization
Enabled
Creation tx
0x1e6e1f16aa…9bbfeee8cc

Token

Name
4FUN
Symbol
4FUN
Decimals
18
Holders
211

Read contract (13)

POSITION_MANAGER()address
WBNB()address
allowance(address, address)uint256
balanceOf(address)uint256
decimals()uint8
getTokenPair()address, address, address
indexer()address
isLaunchPeriodActive()bool
name()string
owner()address
platform()address
symbol()string
totalSupply()uint256

Events (2)

ApprovalTransfer

ABI

[
  {
    "inputs": [
      {
        "internalType": "string",
        "name": "_name",
        "type": "string"
      },
      {
        "internalType": "string",
        "name": "_symbol",
        "type": "string"
      },
      {
        "internalType": "address",
        "name": "_platform",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "_indexer",
        "type": "address"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "spender",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "allowance",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "needed",
        "type": "uint256"
      }
    ],
    "name": "ERC20InsufficientAllowance",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "sender",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "balance",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "needed",
        "type": "uint256"
      }
    ],
    "name": "ERC20InsufficientBalance",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "approver",
        "type": "address"
      }
    ],
    "name": "ERC20InvalidApprover",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "receiver",
        "type": "address"
      }
    ],
    "name": "ERC20InvalidReceiver",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "sender",
        "type": "address"
      }
    ],
    "name": "ERC20InvalidSender",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "spender",
        "type": "address"
      }
    ],
    "name": "ERC20InvalidSpender",
    "type": "error"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "owner",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "spender",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "value",
        "type": "uint256"
      }
    ],
    "name": "Approval",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "from",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "value",
        "type": "uint256"
      }
    ],
    "name": "Transfer",
    "type": "event"
  },
  {
    "inputs": [],
    "name": "POSITION_MANAGER",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "WBNB",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "owner",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "spender",
        "type": "address"
      }
    ],
    "name": "allowance",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "spender",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "value",
        "type": "uint256"
      }
    ],
    "name": "approve",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "account",
        "type": "address"
      }
    ],
    "name": "balanceOf",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "value",
        "type": "uint256"
      }
    ],
    "name": "burn",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "account",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "value",
        "type": "uint256"
      }
    ],
    "name": "burnFrom",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "decimals",
    "outputs": [
      {
        "internalType": "uint8",
        "name": "",
        "type": "uint8"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "getTokenPair",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "indexer",
    "outputs": [
      {
        "internalType": "contract IIndexer",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "isLaunchPeriodActive",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "name",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "owner",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "pure",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "platform",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "symbol",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "totalSupply",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "value",
        "type": "uint256"
      }
    ],
    "name": "transfer",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "from",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "value",
        "type": "uint256"
      }
    ],
    "name": "transferFrom",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "function"
  }
]

Source code

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.9;

import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/utils/math/Math.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";

// $$\   $$\     $$$$$$$$\ $$\   $$\ $$\   $$\
// $$ |  $$ |    $$  _____|$$ |  $$ |$$$\  $$ |
// $$ |  $$ |    $$ |      $$ |  $$ |$$$$\ $$ |
// $$$$$$$$ |    $$$$$\    $$ |  $$ |$$ $$\$$ |
// \_____$$ |    $$  __|   $$ |  $$ |$$ \$$$$ |
//       $$ |    $$ |      $$ |  $$ |$$ |\$$$ |
//       $$ |$$\ $$ |      \$$$$$$  |$$ | \$$ |
//       \__|\__|\__|       \______/ \__|  \__|

address constant PANCAKE_V3_POSITION_MANAGER = 0x73991a25C818Bf1f1128dEAaB1492D45638DE0D3;
address constant WBNB_ADDRESS = 0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73;
address constant PANCAKE_V3_SWAP_ROUTER = 0xCaf681a66D020601342297493863E78C959E5cb2;
address constant PANCAKE_V3_FACTORY = 0x1f7d7550B1b028f7571E69A784071F0205FD2EfA;
uint24 constant FEE_TIER_10000 = 10000;

interface IWBNB {
    function deposit() external payable;

    function withdraw(uint256 amount) external;
}

interface IUniswapV3PoolState {
    function liquidity() external view returns (uint128);
}

interface IUniswapV3Factory {
    function getPool(
        address tokenA,
        address tokenB,
        uint24 fee
    ) external view returns (address);
}

interface IUniswapV3Pool {
    function slot0()
        external
        view
        returns (
            uint160 sqrtPriceX96,
            int24 tick,
            uint16 observationIndex,
            uint16 observationCardinality,
            uint16 observationCardinalityNext,
            uint32 feeProtocol,
            bool unlocked
        );

    function feeGrowthGlobal0X128() external view returns (uint256);

    function feeGrowthGlobal1X128() external view returns (uint256);
}

interface IUniswapV3PoolTokens {
    function token0() external view returns (address);

    function token1() external view returns (address);
}

interface ISwapRouter02 {
    struct ExactInputSingleParams {
        address tokenIn;
        address tokenOut;
        uint24 fee;
        address recipient;
        uint256 amountIn;
        uint256 amountOutMinimum;
        uint160 sqrtPriceLimitX96;
    }

    function exactInputSingle(
        ExactInputSingleParams calldata params
    ) external payable returns (uint256 amountOut);
}

interface INonfungiblePositionManager {
    struct MintParams {
        address token0;
        address token1;
        uint24 fee;
        int24 tickLower;
        int24 tickUpper;
        uint256 amount0Desired;
        uint256 amount1Desired;
        uint256 amount0Min;
        uint256 amount1Min;
        address recipient;
        uint256 deadline;
    }

    function factory() external view returns (address);

    function WETH9() external view returns (address);

    function positions(
        uint256 tokenId
    )
        external
        view
        returns (
            uint96 nonce,
            address operator,
            address token0,
            address token1,
            uint24 fee,
            int24 tickLower,
            int24 tickUpper,
            uint128 liquidity,
            uint256 feeGrowthInside0LastX128,
            uint256 feeGrowthInside1LastX128,
            uint128 tokensOwed0,
            uint128 tokensOwed1
        );

    function createAndInitializePoolIfNecessary(
        address token0,
        address token1,
        uint24 fee,
        uint160 sqrtPriceX96
    ) external returns (address pool);

    function mint(
        MintParams calldata params
    )
        external
        returns (
            uint256 tokenId,
            uint128 liquidity,
            uint256 amount0,
            uint256 amount1
        );

    struct CollectParams {
        uint256 tokenId;
        address recipient;
        uint128 amount0Max;
        uint128 amount1Max;
    }

    function collect(
        CollectParams calldata params
    ) external payable returns (uint256 amount0, uint256 amount1);
}

interface IFactoryPoolView {
    function tokenToPool(address token) external view returns (address);
}

interface IIndexer {
    function emitERC20TokenCreated(
        address tokenAddress,
        address deployer
    ) external;

    function emitSaltBruteforced(
        bytes32 usedSalt,
        address predictedToken
    ) external;

    function emitFeesCollected(
        uint256 tokenId,
        address token,
        uint256 tokenAmount,
        uint256 bnbAmount
    ) external;

    function emitTokenPurchased(
        address buyer,
        address tokenOut,
        uint256 bnbSpent,
        uint256 tokensReceived
    ) external;

    function emitBuy(
        address buyer,
        address pool,
        address token,
        uint256 amountTokens,
        uint160 sqrtPriceX96,
        uint256 priceX96,
        uint256 bnbAmount,
        uint256 totalFeesBNB,
        uint256 totalFeesToken
    ) external;

    function emitSell(
        address seller,
        address pool,
        address token,
        uint256 amountTokens,
        uint160 sqrtPriceX96,
        uint256 priceX96,
        uint256 bnbAmount,
        uint256 totalFeesBNB,
        uint256 totalFeesToken
    ) external;

    function authorizeAddress(address _contract) external;
}

error NotController();
error DeploymentDisabled();
error InvalidConfigId();
error SaltSearchFailed();
error TokenMustBeToken0();
error MustBeWBNB();
error NoWBNBToWithdraw();
error NoBNBToWithdraw();
error BatchRange();
error ItemsPerPageRange();
error PenaltyMultiplierRange();
error NoTokensDeployed();
error PageOutOfRange();
error InternalOnly();
error NoPosition();
error NotAuthorized();

contract FunToken is ERC20, ERC20Burnable {
    using Math for uint256;

    address public platform;
    IIndexer public indexer;
    uint256 private launchBlock;
    uint256 private maxTxAmount;
    uint256 private constant LAUNCH_PERIOD = 5;
    uint256 private constant MAX_WALLET_PERCENTAGE = 2;

    address public constant POSITION_MANAGER = PANCAKE_V3_POSITION_MANAGER;
    address public constant WBNB = WBNB_ADDRESS;

    mapping(address => uint256) private tokensFromPoolPerOrigin;

    constructor(
        string memory _name,
        string memory _symbol,
        address _platform,
        address _indexer
    ) ERC20(_name, _symbol) {
        platform = _platform;
        indexer = IIndexer(_indexer);
        launchBlock = block.number;

        uint256 totalTokens = 1_000_000 * 10 ** decimals();
        maxTxAmount = (totalTokens * MAX_WALLET_PERCENTAGE) / 100;

        _mint(_platform, totalTokens);
    }

    function owner() public pure returns (address) {
        return address(0);
    }

    function _update(
        address from,
        address to,
        uint256 value
    ) internal override {
        if (
            block.number > launchBlock &&
            block.number <= launchBlock + LAUNCH_PERIOD
        ) {
            address factory = INonfungiblePositionManager(POSITION_MANAGER)
                .factory();
            address pool = IUniswapV3Factory(factory).getPool(
                address(this),
                WBNB,
                FEE_TIER_10000
            );

            if (from == pool && to != platform) {
                tokensFromPoolPerOrigin[tx.origin] += value;
                require(
                    tokensFromPoolPerOrigin[tx.origin] <=
                        (maxTxAmount * 110) / 100,
                    "Keeping 2% pool Limits In Kontrol"
                );
            }

            if (to != platform && to != pool && from != address(0)) {
                require(
                    balanceOf(to) + value <= maxTxAmount,
                    "Max wallet limit exceeded during launch period"
                );
            }
        }

        if (
            block.number == launchBlock &&
            from != address(0) &&
            to != platform &&
            from != platform
        ) {
            revert("No buys allowed during launch block!");
        }

        super._update(from, to, value);

        address factoryPool = IFactoryPoolView(platform).tokenToPool(
            address(this)
        );
        if (
            factoryPool != address(0) &&
            (from == factoryPool || to == factoryPool)
        ) {
            (uint160 sqrtPriceX96, , , , , , ) = IUniswapV3Pool(factoryPool)
                .slot0();
            uint256 priceX96 = Math.mulDiv(
                uint256(sqrtPriceX96),
                uint256(sqrtPriceX96),
                1 << 96
            );

            uint256 feeGrowthBNB = IUniswapV3Pool(factoryPool)
                .feeGrowthGlobal1X128();
            uint256 feeGrowthToken = IUniswapV3Pool(factoryPool)
                .feeGrowthGlobal0X128();

            bool tokenIsToken0 = address(this) < WBNB;
            uint256 bnbAmount;

            if (tokenIsToken0) {
                uint256 priceX192 = Math.mulDiv(
                    uint256(sqrtPriceX96),
                    uint256(sqrtPriceX96),
                    1
                );
                bnbAmount = Math.mulDiv(value, priceX192, 1 << 192);
            } else {
                uint256 priceX192 = Math.mulDiv(
                    uint256(sqrtPriceX96),
                    uint256(sqrtPriceX96),
                    1
                );
                bnbAmount = Math.mulDiv(value, 1 << 192, priceX192);
            }

            if (from == factoryPool && to != address(0)) {
                try
                    indexer.emitBuy(
                        to,
                        factoryPool,
                        address(this),
                        value,
                        sqrtPriceX96,
                        priceX96,
                        bnbAmount,
                        feeGrowthBNB,
                        feeGrowthToken
                    )
                {} catch {}
            } else if (to == factoryPool && from != address(0)) {
                try
                    indexer.emitSell(
                        from,
                        factoryPool,
                        address(this),
                        value,
                        sqrtPriceX96,
                        priceX96,
                        bnbAmount,
                        feeGrowthBNB,
                        feeGrowthToken
                    )
                {} catch {}
            }
        }
    }

    function getTokenPair() public view returns (address, address, address) {
        address find_factory = INonfungiblePositionManager(POSITION_MANAGER)
            .factory();
        address find_pool = IUniswapV3Factory(find_factory).getPool(
            address(this),
            WBNB,
            FEE_TIER_10000
        );
        return (find_pool, address(this), find_factory);
    }

    function isLaunchPeriodActive() public view returns (bool) {
        return block.number <= launchBlock + LAUNCH_PERIOD;
    }
}
Chain explorer1021msChain node84ms