LemonToken

0xa819754a983559ada2b9d32e95bb4492a71658af

Verification
Verified
v0.8.26+commit.8a97fa7a
Type
Contract
4,241 bytes
ABI entries
33
18 read · 6 write
License
none

Contract information

Address
0xa819754a983559ada2b9d32e95bb4492a71658af
Chain
Robinhood Chain (4663)
Compiler
v0.8.26+commit.8a97fa7a
Optimization
Enabled
Creation tx
0xd29046e768…3ae3964b98

Token

Name
Lemon Juice
Symbol
lemon
Decimals
18
Holders
3

Read contract (18)

allowance(address, address)uint256
balanceOf(address)uint256
capUntil()uint256
decimals()uint8
description()string
launcher()address
logoURI()string
maxWallet()uint256
name()string
pool()address
poolSetter()address
symbol()string
telegram()string
totalSupply()uint256
tradingOpen()bool
tradingOpensAt()uint256
twitter()string
website()string

Events (2)

ApprovalTransfer

ABI

[
  {
    "inputs": [
      {
        "internalType": "string",
        "name": "name_",
        "type": "string"
      },
      {
        "internalType": "string",
        "name": "symbol_",
        "type": "string"
      },
      {
        "internalType": "uint256",
        "name": "supply_",
        "type": "uint256"
      },
      {
        "internalType": "address",
        "name": "launcher_",
        "type": "address"
      },
      {
        "internalType": "string",
        "name": "logoURI_",
        "type": "string"
      },
      {
        "internalType": "string",
        "name": "description_",
        "type": "string"
      },
      {
        "internalType": "string",
        "name": "twitter_",
        "type": "string"
      },
      {
        "internalType": "string",
        "name": "telegram_",
        "type": "string"
      },
      {
        "internalType": "string",
        "name": "website_",
        "type": "string"
      }
    ],
    "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": [
      {
        "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": [],
    "name": "capUntil",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "maxWallet_",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "launchDelaySecs",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "capWindowSecs",
        "type": "uint256"
      }
    ],
    "name": "configureLaunch",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "decimals",
    "outputs": [
      {
        "internalType": "uint8",
        "name": "",
        "type": "uint8"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "description",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "setter_",
        "type": "address"
      }
    ],
    "name": "initPoolSetter",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "launcher",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "logoURI",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "maxWallet",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "name",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "pool",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "poolSetter",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "pool_",
        "type": "address"
      }
    ],
    "name": "setPool",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "symbol",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "telegram",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "totalSupply",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "tradingOpen",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "tradingOpensAt",
    "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"
  },
  {
    "inputs": [],
    "name": "twitter",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "website",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  }
]

Source code

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";

/// @title LemonToken
/// @notice 1:1 copy of pew.fun's `LaunchToken` (Robinhood Chain
///         0x767a41ae042bddd074e76c48bfda2339819cf786) — the reference
///         implementation that GMGN / DexScreener / honeypot scanners
///         accept cleanly. Immutable launch token: no owner, no mint after
///         construction, no tax, no pause, no blacklist. Carries on-chain
///         metadata so explorers/aggregators can render it. The only
///         privileged, one-time action is the launcher wiring the pool + a
///         temporary anti-snipe window at launch; after the window it is a
///         plain, unrestricted ERC-20 that passes honeypot/rug scanners.
/// @dev Anti-snipe is TIMESTAMP-based (not block-based): on Arbitrum/Orbit
///      `block.number` is the parent-chain block, which the frontend can't
///      read — `block.timestamp` is unambiguous on both sides and matches
///      the app's countdown.
contract LemonToken is ERC20 {
    address public immutable launcher; // the factory / presale contract that launched it

    // on-chain metadata
    string public logoURI;
    string public description;
    string public twitter;
    string public telegram;
    string public website;

    // launch protections (set once at launch)
    address public pool;
    uint256 public maxWallet; // per-wallet cap during the cap window (0 = unset)
    uint256 public tradingOpensAt; // launch-delay gate: public trading blocked before this timestamp
    uint256 public capUntil; // anti-snipe max-wallet cap active until this timestamp
    bool private _configured;

    /// @notice One-shot address (typically the BondingCurve) allowed to wire
    /// the real DEX pool at graduation. Distinct from `launcher` so we never
    /// expose an *unseeded* pool to honeypot scanners during bonding.
    address public poolSetter;
    bool private _poolSetterInit;

    constructor(
        string memory name_,
        string memory symbol_,
        uint256 supply_,
        address launcher_,
        string memory logoURI_,
        string memory description_,
        string memory twitter_,
        string memory telegram_,
        string memory website_
    ) ERC20(name_, symbol_) {
        launcher = launcher_;
        logoURI = logoURI_;
        description = description_;
        twitter = twitter_;
        telegram = telegram_;
        website = website_;
        _mint(launcher_, supply_); // full supply to the launcher; there is no other mint path
    }

    /// @notice One-time wiring by the launcher at launch. Windows are in SECONDS.
    /// @dev The real DEX pool is intentionally NOT set here — see `setPool`.
    /// Advertising an unseeded pool at launch would make honeypot simulators
    /// report "100% sell tax" throughout the bonding-curve phase.
    function configureLaunch(uint256 maxWallet_, uint256 launchDelaySecs, uint256 capWindowSecs)
        external
    {
        require(msg.sender == launcher && !_configured, "not launcher / configured");
        _configured = true;
        maxWallet = maxWallet_;
        tradingOpensAt = block.timestamp + launchDelaySecs;
        capUntil = tradingOpensAt + capWindowSecs;
    }

    /// @notice Launcher assigns the pool-setter role exactly once (the curve).
    function initPoolSetter(address setter_) external {
        require(msg.sender == launcher && !_poolSetterInit, "not launcher / init");
        require(setter_ != address(0), "zero setter");
        _poolSetterInit = true;
        poolSetter = setter_;
    }

    /// @notice Called by the curve at graduation to wire the seeded SushiSwap
    /// V3 pool. One-shot: `pool` can be set exactly once.
    function setPool(address pool_) external {
        require(msg.sender == poolSetter, "not poolSetter");
        require(pool == address(0) && pool_ != address(0), "pool set");
        pool = pool_;
    }

    function tradingOpen() external view returns (bool) {
        return _configured && block.timestamp >= tradingOpensAt;
    }

    /// @dev Launch protections apply only to *public trades* touching the pool.
    /// While `pool == address(0)` (entire bonding-curve phase) the whole branch
    /// is dead and the token behaves as a plain unrestricted ERC-20.
    function _update(address from, address to, uint256 value) internal override {
        if (_configured && pool != address(0) && (from == pool || to == pool) && from != launcher && to != launcher) {
            require(block.timestamp >= tradingOpensAt, "launch: trading not open");
            if (maxWallet != 0 && block.timestamp < capUntil && to != pool && to != address(0)) {
                require(balanceOf(to) + value <= maxWallet, "anti-snipe: max wallet");
            }
        }
        super._update(from, to, value);
    }
}
Chain explorer3067msChain node80ms