LaunchToken
0x44ac7802f6ec8ae2507f246b669a4158e8d3478a
Verification
Verified
v0.8.24+commit.e11b9ed9
Type
Contract
2,901 bytes
ABI entries
33
15 read · 5 write
License
none
Contract information
- Address
- 0x44ac7802f6ec8ae2507f246b669a4158e8d3478a
- Chain
- Robinhood Chain (4663)
- Compiler
- v0.8.24+commit.e11b9ed9
- Optimization
- Enabled
- Creator
- 0x9fAfa3B9FF…Be6eaf83EA
- Creation tx
- 0xfb4a88cb6f…1ffd2b8aa9
Token
- Name
- Hood Tracker
- Symbol
- HDTX
- Decimals
- 18
- Holders
- 364
- Market
- View token page →
Read contract (15)
SUPPLY() → uint256
allowance(address, address) → uint256
balanceOf(address) → uint256
decimals() → uint8
factory() → address
isExempt(address) → bool
launchTime() → uint256
limitSeconds() → uint256
limitsLifted() → bool
maxTxAmount() → uint256
maxWalletAmount() → uint256
name() → string
pool() → 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": "creator",
"type": "address"
},
{
"internalType": "address[]",
"name": "exempt",
"type": "address[]"
},
{
"internalType": "uint256",
"name": "limitSeconds_",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "maxTxDuringWindow",
"type": "uint256"
}
],
"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"
},
{
"inputs": [],
"name": "MaxTxExceeded",
"type": "error"
},
{
"inputs": [],
"name": "MaxWalletExceeded",
"type": "error"
},
{
"inputs": [],
"name": "NotFactory",
"type": "error"
},
{
"inputs": [],
"name": "PoolAlreadySet",
"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": "SUPPLY",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"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": [],
"name": "decimals",
"outputs": [
{
"internalType": "uint8",
"name": "",
"type": "uint8"
}
],
"stateMutability": "pure",
"type": "function"
},
{
"inputs": [],
"name": "factory",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "isExempt",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "launchTime",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "liftLimits",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "limitSeconds",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "limitsLifted",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "maxTxAmount",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "maxWalletAmount",
"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": [
{
"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": "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.24;
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
/// @title LaunchToken
/// @notice Fixed-supply launchpad token with a Noxa-style anti-snipe window.
///
/// Reverse-engineered from live NOXA tokens on Robinhood Chain (RobinhoodieLife
/// 0xe70d…fcd1, CASHCAT 0x020b…18b4 — identical template bytecode). Their on-chain
/// state read exactly:
/// totalSupply = 1_000_000_000e18 (1B, 18 dec)
/// maxWalletAmount = 20_000_000e18 (2% of supply)
/// maxTxAmount = 1_000_000_000e18 (per-tx cap; lifted to full supply post-window)
///
/// The guard lives inside the token's transfer path (not a separate module), and
/// is enforced only while `block.timestamp <= launchTime + limitSeconds`. The
/// window is measured in SECONDS, not blocks: on Arbitrum-stack chains (Robinhood
/// Chain included) `block.number` returns the parent-chain (Ethereum L1) block
/// number, so a block-denominated window silently runs ~120× longer than the L2
/// block rate suggests. Timestamps are L2-native and unambiguous.
///
/// The max-wallet cap applies to what a wallet ACCUMULATES (buys, transfers in).
/// The pool is excused from the cap as a recipient — otherwise every sell
/// (wallet → pool, which holds ~all supply) would revert and only exempt parties
/// could exit. Buys stay capped: pool → wallet still checks the recipient.
/// After the window, limits lift permanently; there is no early-lift override.
contract LaunchToken is ERC20 {
uint256 public constant SUPPLY = 1_000_000_000e18; // 1B, matches Noxa
uint8 private constant _DECIMALS = 18;
/// @dev 2% of supply — the exact Noxa value (20,000,000e18).
uint256 public maxWalletAmount;
/// @dev Per-tx cap during the window. Lifted to SUPPLY when the window ends.
uint256 public maxTxAmount;
/// @dev Timestamp the token launched; the anti-snipe window is relative to it.
uint256 public immutable launchTime;
/// @dev Length of the anti-snipe window in seconds (~1h).
uint256 public immutable limitSeconds;
address public immutable factory;
/// @dev The V3 pool. Exempt from the max-wallet cap as RECIPIENT only, so
/// sells always flow; set once by the factory right after pool creation
/// (the pool doesn't exist yet when this token's constructor runs).
address public pool;
/// @dev Addresses exempt from limits (factory, NPM, locker, dead, creator).
mapping(address => bool) public isExempt;
bool public limitsLifted;
error MaxWalletExceeded();
error MaxTxExceeded();
error NotFactory();
error PoolAlreadySet();
constructor(
string memory name_,
string memory symbol_,
address creator,
address[] memory exempt,
uint256 limitSeconds_,
uint256 maxTxDuringWindow
) ERC20(name_, symbol_) {
factory = msg.sender; // deployed by the LaunchFactory
launchTime = block.timestamp;
limitSeconds = limitSeconds_;
maxWalletAmount = SUPPLY / 50; // 2%
maxTxAmount = maxTxDuringWindow == 0 ? SUPPLY : maxTxDuringWindow;
isExempt[msg.sender] = true; // factory
isExempt[creator] = true;
for (uint256 i = 0; i < exempt.length; i++) {
isExempt[exempt[i]] = true;
}
// Entire supply is minted to the factory, which seeds it single-sided
// into the V3 pool in the same transaction.
_mint(msg.sender, SUPPLY);
}
function decimals() public pure override returns (uint8) {
return _DECIMALS;
}
/// @notice One-time pool registration, factory-only, called in the same
/// launch transaction. NOT a general exemption: the pool is only
/// excused from the max-wallet check as recipient (sell path).
function setPool(address pool_) external {
if (msg.sender != factory) revert NotFactory();
if (pool != address(0)) revert PoolAlreadySet();
pool = pool_;
}
/// @notice Anyone can lift limits once the window has elapsed. There is no
/// early-lift path — not even for the factory or its owner.
function liftLimits() external {
require(block.timestamp > launchTime + limitSeconds, "window still active");
_lift();
}
function _lift() internal {
if (limitsLifted) return;
limitsLifted = true;
maxWalletAmount = SUPPLY;
maxTxAmount = SUPPLY;
}
/// @dev The anti-snipe guard. OZ v5 routes mint/burn/transfer through _update.
function _update(address from, address to, uint256 value) internal override {
// Auto-lift once the window passes so the first post-window transfer
// clears the limits without needing an explicit call.
if (!limitsLifted && block.timestamp > launchTime + limitSeconds) {
_lift();
}
if (!limitsLifted && from != address(0)) {
// Exempt parties (factory seed, NPM, locker, creator) bypass limits.
bool exemptFlow = isExempt[from] || isExempt[to];
if (!exemptFlow) {
if (value > maxTxAmount) revert MaxTxExceeded();
// The pool accumulates by design (it holds the curve): capping it
// as recipient would block every sell. Wallets stay capped at 2%.
if (to != pool && balanceOf(to) + value > maxWalletAmount) {
revert MaxWalletExceeded();
}
}
}
super._update(from, to, value);
}
}
Chain explorer5093msChain node78ms