LaunchToken
0xfb4729659eef22bfc1c2b680f6f873f8147aaaab
Verification
Verified
v0.8.24+commit.e11b9ed9
Type
Contract
2,831 bytes
ABI entries
29
14 read · 5 write
License
none
Contract information
- Address
- 0xfb4729659eef22bfc1c2b680f6f873f8147aaaab
- Chain
- Robinhood Chain (4663)
- Compiler
- v0.8.24+commit.e11b9ed9
- Optimization
- Enabled
- Creator
- 0xEb3FeeD271…794e1f5a80
- Creation tx
- 0x74685f1275…b53b1ab84e
Token
- Name
- Robin
- Symbol
- ROBIN
- Decimals
- 6
- Holders
- 600
- Market
- View token page →
Read contract (14)
TOTAL_SUPPLY() → uint256
allowance(address, address) → uint256
antiSnipeBlocks() → uint64
balanceOf(address) → uint256
decimals() → uint8
factory() → address
launchBlock() → uint64
limitExempt(address) → bool
limitsActive() → bool
maxWallet() → uint256
maxWalletBps() → uint16
name() → string
symbol() → string
totalSupply() → uint256
Events (3)
ApprovalLimitsUpdatedTransfer
ABI
[
{
"inputs": [
{
"internalType": "string",
"name": "name_",
"type": "string"
},
{
"internalType": "string",
"name": "symbol_",
"type": "string"
},
{
"internalType": "address",
"name": "recipient",
"type": "address"
},
{
"internalType": "uint16",
"name": "maxWalletBps_",
"type": "uint16"
},
{
"internalType": "uint64",
"name": "antiSnipeBlocks_",
"type": "uint64"
}
],
"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": false,
"internalType": "uint16",
"name": "maxWalletBps",
"type": "uint16"
},
{
"indexed": false,
"internalType": "uint64",
"name": "antiSnipeBlocks",
"type": "uint64"
}
],
"name": "LimitsUpdated",
"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": "TOTAL_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": [],
"name": "antiSnipeBlocks",
"outputs": [
{
"internalType": "uint64",
"name": "",
"type": "uint64"
}
],
"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": [],
"name": "launchBlock",
"outputs": [
{
"internalType": "uint64",
"name": "",
"type": "uint64"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "limitExempt",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "limitsActive",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "maxWallet",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "maxWalletBps",
"outputs": [
{
"internalType": "uint16",
"name": "",
"type": "uint16"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "name",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "a",
"type": "address"
},
{
"internalType": "bool",
"name": "ok",
"type": "bool"
}
],
"name": "setLimitExempt",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint16",
"name": "maxWalletBps_",
"type": "uint16"
},
{
"internalType": "uint64",
"name": "antiSnipeBlocks_",
"type": "uint64"
}
],
"name": "setLimits",
"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 The per-launch ERC-20. 6 decimals, a fixed 1,000,000,000 * 1e6 supply minted ONCE to the
/// factory at construction, no mint function (mint authority effectively renounced).
///
/// Optional NOXA-style anti-snipe: when `maxWalletBps > 0`, a max-wallet cap (in bps of total
/// supply) is enforced for the first `antiSnipeBlocks` blocks after launch — it applies during
/// the bonding curve, so no single wallet can grab more than the cap at launch — then it
/// auto-lifts and the token trades freely. Enforced in OZ's `_update` hook. The factory (the
/// constructor `recipient`) is exempt and can exempt the graduated Uniswap pool (which holds
/// the 20% LP reserve) so the cap never blocks migration.
///
/// `maxWalletBps == 0` ⇒ no limits at all (the Monad / back-compatible default). The factory
/// bakes its current limits into each token's CREATE2 init code.
contract LaunchToken is ERC20 {
uint8 private constant DECIMALS = 6;
uint256 public constant TOTAL_SUPPLY = 1_000_000_000 * 10 ** 6; // 1B, 6dp = 1e15
address public immutable factory; // the launchpad — holds reserves, runs the curve + graduation
uint16 public maxWalletBps; // e.g. 300 = 3% of supply; 0 = no limit. Owner-mutable post-launch (via factory).
uint64 public antiSnipeBlocks; // anti-snipe window length, in blocks. Owner-mutable post-launch (via factory).
uint64 public immutable launchBlock; // creation block — window = [launchBlock, launchBlock+window)
mapping(address => bool) public limitExempt; // factory / zero / dead / the graduated pool
event LimitsUpdated(uint16 maxWalletBps, uint64 antiSnipeBlocks);
/// @param recipient the factory — it holds the for-sale (800M) + LP-held (200M) reserves.
constructor(
string memory name_,
string memory symbol_,
address recipient,
uint16 maxWalletBps_,
uint64 antiSnipeBlocks_
) ERC20(name_, symbol_) {
factory = recipient;
maxWalletBps = maxWalletBps_;
antiSnipeBlocks = antiSnipeBlocks_;
launchBlock = uint64(block.number);
limitExempt[recipient] = true; // factory holds ~100% of supply through the curve phase
limitExempt[address(0)] = true; // mint / burn endpoints
limitExempt[0x000000000000000000000000000000000000dEaD] = true; // LP / burn sink
_mint(recipient, TOTAL_SUPPLY);
}
/// @notice Max tokens a non-exempt wallet may hold while limits are active (max ⇒ unlimited).
function maxWallet() public view returns (uint256) {
return maxWalletBps == 0 ? type(uint256).max : (TOTAL_SUPPLY * maxWalletBps) / 10000;
}
/// @notice True while the max-wallet cap is enforced (anti-snipe window still open).
function limitsActive() public view returns (bool) {
return maxWalletBps > 0 && block.number < uint256(launchBlock) + antiSnipeBlocks;
}
/// @notice Factory-only: exempt an address from the cap. The factory calls this for the graduated
/// Uniswap pool (which receives the 200M LP reserve, > the cap) so graduation within the
/// anti-snipe window isn't blocked.
function setLimitExempt(address a, bool ok) external {
require(msg.sender == factory, "only factory");
limitExempt[a] = ok;
}
/// @notice Factory-only: retune this token's anti-snipe AFTER launch. The factory gates this behind
/// onlyOwner, so effectively only the platform owner can call it. `maxWalletBps_ == 0` disables
/// the cap; the window stays anchored at launchBlock, i.e. [launchBlock, launchBlock+blocks).
function setLimits(uint16 maxWalletBps_, uint64 antiSnipeBlocks_) external {
require(msg.sender == factory, "only factory");
require(maxWalletBps_ <= 10000, "bps");
maxWalletBps = maxWalletBps_;
antiSnipeBlocks = antiSnipeBlocks_;
emit LimitsUpdated(maxWalletBps_, antiSnipeBlocks_);
}
function decimals() public pure override returns (uint8) {
return DECIMALS;
}
/// @dev Enforce the max wallet on the recipient during the anti-snipe window only; exempt addresses
/// (factory, pool, zero, dead) are never capped. After the window — or when maxWalletBps==0 —
/// the cap is inert.
function _update(address from, address to, uint256 value) internal override {
if (limitsActive() && !limitExempt[to]) {
require(balanceOf(to) + value <= maxWallet(), "max wallet (anti-snipe)");
}
super._update(from, to, value);
}
}
Chain explorer8814msChain node75ms