LaunchToken

0x13369c9c1cf3a3472beb4a85d048043b99f392de

Verification
Verified
v0.8.26+commit.8a97fa7a
Type
Contract
3,404 bytes
ABI entries
34
19 read · 5 write
License
mit

Contract information

Address
0x13369c9c1cf3a3472beb4a85d048043b99f392de
Chain
Robinhood Chain (4663)
Compiler
v0.8.26+commit.8a97fa7a
Optimization
Enabled
Creation tx
0xf07f2c2b9c…1519e63cde

Token

Name
Hoodog
Symbol
Hoodog
Decimals
18
Holders
774

Read contract (19)

allowance(address, address)uint256
balanceOf(address)uint256
boughtInBlock(address)uint256
buyBlock(address)uint256
decimals()uint8
launchBlock()uint256
launchFactory()address
launchOrigin()address
liquidityPool()address
maxTxLimit()uint256
maxWalletLimit()uint256
name()string
pairToken()address
poolFee()uint24
restrictionEndBlock()uint256
restrictionExempt(address)bool
symbol()string
tokenURI()string
totalSupply()uint256

Events (2)

ApprovalTransfer

ABI

[
  {
    "inputs": [
      {
        "internalType": "string",
        "name": "name_",
        "type": "string"
      },
      {
        "internalType": "string",
        "name": "symbol_",
        "type": "string"
      },
      {
        "internalType": "string",
        "name": "tokenURI_",
        "type": "string"
      },
      {
        "internalType": "uint256",
        "name": "supply_",
        "type": "uint256"
      },
      {
        "internalType": "address",
        "name": "pairToken_",
        "type": "address"
      },
      {
        "internalType": "uint24",
        "name": "poolFee_",
        "type": "uint24"
      },
      {
        "internalType": "uint256",
        "name": "restrictionBlocks_",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "maxTxLimit_",
        "type": "uint256"
      },
      {
        "internalType": "address",
        "name": "receiver_",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "launchOrigin_",
        "type": "address"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  {
    "inputs": [],
    "name": "InsufficientAllowance",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "InsufficientBalance",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "recipient",
        "type": "address"
      }
    ],
    "name": "LaunchBlockBuyBlocked",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "originator",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "attempted",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "limit",
        "type": "uint256"
      }
    ],
    "name": "MaxTxExceeded",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "account",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "balance",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "limit",
        "type": "uint256"
      }
    ],
    "name": "MaxWalletExceeded",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "Unauthorized",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "ZeroAddress",
    "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": "",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "",
        "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": "",
        "type": "address"
      }
    ],
    "name": "balanceOf",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "boughtInBlock",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "buyBlock",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "decimals",
    "outputs": [
      {
        "internalType": "uint8",
        "name": "",
        "type": "uint8"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "launchBlock",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "launchFactory",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "launchOrigin",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "liquidityPool",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "maxTxLimit",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "maxWalletLimit",
    "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": "pairToken",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "poolFee",
    "outputs": [
      {
        "internalType": "uint24",
        "name": "",
        "type": "uint24"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "restrictionEndBlock",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "restrictionExempt",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "account",
        "type": "address"
      },
      {
        "internalType": "bool",
        "name": "enabled",
        "type": "bool"
      }
    ],
    "name": "setInitialBuyExemption",
    "outputs": [],
    "stateMutability": "nonpayable",
    "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": "tokenURI",
    "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.26;

/// @notice Ordinary, non-upgradeable ERC-20 deployed for one Hooday launch.
/// @dev The complete supply is minted once to the Factory for single-sided LP.
contract LaunchToken {
    uint8 public constant decimals = 18;

    string public name;
    string public symbol;
    string public tokenURI;
    uint256 public totalSupply;
    address public immutable launchFactory;
    address public immutable launchOrigin;
    address public liquidityPool;
    address public immutable pairToken;
    uint24 public immutable poolFee;
    uint256 public immutable launchBlock;
    uint256 public immutable restrictionEndBlock;
    uint256 public immutable maxWalletLimit;
    uint256 public immutable maxTxLimit;

    mapping(address => uint256) public balanceOf;
    mapping(address => mapping(address => uint256)) public allowance;
    mapping(address => bool) public restrictionExempt;
    mapping(address => uint256) public buyBlock;
    mapping(address => uint256) public boughtInBlock;

    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);

    error Unauthorized();
    error ZeroAddress();
    error InsufficientBalance();
    error InsufficientAllowance();
    error LaunchBlockBuyBlocked(address recipient);
    error MaxWalletExceeded(address account, uint256 balance, uint256 limit);
    error MaxTxExceeded(address originator, uint256 attempted, uint256 limit);

    constructor(
        string memory name_,
        string memory symbol_,
        string memory tokenURI_,
        uint256 supply_,
        address pairToken_,
        uint24 poolFee_,
        uint256 restrictionBlocks_,
        uint256 maxTxLimit_,
        address receiver_,
        address launchOrigin_
    ) {
        if (
            bytes(name_).length == 0 ||
            bytes(symbol_).length == 0 ||
            pairToken_ == address(0) ||
            receiver_ == address(0) ||
            launchOrigin_ == address(0)
        ) revert ZeroAddress();

        name = name_;
        symbol = symbol_;
        tokenURI = tokenURI_;
        totalSupply = supply_;
        launchFactory = msg.sender;
        launchOrigin = launchOrigin_;
        pairToken = pairToken_;
        poolFee = poolFee_;
        launchBlock = block.number;
        restrictionEndBlock = block.number + restrictionBlocks_;
        maxWalletLimit = supply_ * 2 / 100;
        maxTxLimit = maxTxLimit_;
        restrictionExempt[msg.sender] = true;
        restrictionExempt[receiver_] = true;
        balanceOf[receiver_] = supply_;
        emit Transfer(address(0), receiver_, supply_);
    }

    function setPool(address pool) external {
        if (msg.sender != launchFactory || liquidityPool != address(0) || pool == address(0)) {
            revert Unauthorized();
        }
        liquidityPool = pool;
    }

    /// @notice Temporarily exempts only the Factory-executed initial-buy recipient.
    function setInitialBuyExemption(address account, bool enabled) external {
        if (msg.sender != launchFactory || block.number != launchBlock) revert Unauthorized();
        restrictionExempt[account] = enabled;
    }

    function approve(address spender, uint256 value) external returns (bool) {
        allowance[msg.sender][spender] = value;
        emit Approval(msg.sender, spender, value);
        return true;
    }

    function transfer(address to, uint256 value) external returns (bool) {
        _transfer(msg.sender, to, value);
        return true;
    }

    function transferFrom(address from, address to, uint256 value) external returns (bool) {
        uint256 approved = allowance[from][msg.sender];
        if (approved != type(uint256).max) {
            if (approved < value) revert InsufficientAllowance();
            allowance[from][msg.sender] = approved - value;
        }
        _transfer(from, to, value);
        return true;
    }

    function _transfer(address from, address to, uint256 value) private {
        if (to == address(0)) revert ZeroAddress();
        uint256 fromBalance = balanceOf[from];
        if (fromBalance < value) revert InsufficientBalance();

        if (
            from == liquidityPool &&
            block.number < restrictionEndBlock &&
            !restrictionExempt[to]
        ) {
            if (block.number == launchBlock && tx.origin != launchOrigin) {
                revert LaunchBlockBuyBlocked(to);
            }
            uint256 afterBalance = balanceOf[to] + value;
            if (afterBalance > maxWalletLimit) {
                revert MaxWalletExceeded(to, afterBalance, maxWalletLimit);
            }
            if (buyBlock[tx.origin] != block.number) {
                buyBlock[tx.origin] = block.number;
                boughtInBlock[tx.origin] = 0;
            }
            uint256 attempted = boughtInBlock[tx.origin] + value;
            if (attempted > maxTxLimit * 110 / 100) {
                revert MaxTxExceeded(tx.origin, attempted, maxTxLimit);
            }
            boughtInBlock[tx.origin] = attempted;
        }

        unchecked {
            balanceOf[from] = fromBalance - value;
            balanceOf[to] += value;
        }
        emit Transfer(from, to, value);
    }
}
Chain explorer3896msChain node80ms