FlowPadCurveToken

0x8eb0d8aad30167e598597ca1b4910640e59c7c6c

Verification
Verified
v0.8.26+commit.8a97fa7a
Type
Contract
2,644 bytes
ABI entries
28
13 read · 4 write
License
none

Contract information

Address
0x8eb0d8aad30167e598597ca1b4910640e59c7c6c
Chain
Robinhood Chain (4663)
Compiler
v0.8.26+commit.8a97fa7a
Optimization
Enabled
Creation tx
0xcdf41e1cb0…9874a8968b

Token

Name
Collector Hood
Symbol
Collector
Decimals
18
Holders
9

Read contract (13)

TOTAL_SUPPLY()uint256
allowance(address, address)uint256
balanceOf(address)uint256
creator()address
decimals()uint8
graduated()bool
hook()address
launcher()address
maxWallet()uint256
name()string
poolManager()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": "hook_",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "poolManager_",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "creator_",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "maxWallet_",
        "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": "MaxWalletExceeded",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "NotAuthorized",
    "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": "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": [
      {
        "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": "creator",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "decimals",
    "outputs": [
      {
        "internalType": "uint8",
        "name": "",
        "type": "uint8"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "graduated",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "hook",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "launcher",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "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": "poolManager",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "setGraduated",
    "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.26;

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

/// @title FlowPadCurveToken (v4 single-sided model)
/// @notice Fixed 1B-supply ERC-20 for the single-sided-liquidity model: the
/// ENTIRE curve supply is seeded as a real Uniswap v4 concentrated-liquidity
/// position at launch (see FlowPadCurveHook), so the token is a genuine on-chain
/// market — routable by any v4 aggregator (GMGN, Axiom, Universal Router) from
/// block one.
///
/// The token is fully SELF-CONTAINED: it makes NO external calls in `_update`,
/// so nothing outside the token can ever influence a transfer. It has no owner
/// and no governor — the only knobs are IMMUTABLE, baked at launch: an anti-whale
/// `maxWallet` cap and the exempt `creator`. This is what lets automated scanners
/// (GMGN, honeypot detectors) read it as a plain, renounced ERC-20 rather than a
/// token whose transfers depend on a mutable external authority.
///
/// The cap applies ONLY to the pool-exit leg (`from == poolManager`) BEFORE
/// graduation; the venue and the creator are exempt, and `maxWallet == 0`
/// disables it. `setGraduated` (launcher/hook only) permanently LIFTS the cap —
/// it can only ever make the token freer, never more restricted — after which
/// the token trades with zero restrictions.
contract FlowPadCurveToken is ERC20 {
    error MaxWalletExceeded();
    error NotAuthorized();

    uint256 public constant TOTAL_SUPPLY = 1_000_000_000 ether;

    address public immutable launcher; // deployer; may lift the cap (one-way)
    address public immutable hook; // curve venue (seeds/holds LP + fees)
    address public immutable poolManager; // v4 PoolManager (the AMM venue)
    address public immutable creator; // max-wallet exempt (fixed at launch)
    uint256 public immutable maxWallet; // pre-grad per-holder cap in tokens (0 = none)

    bool public graduated;

    constructor(
        string memory name_,
        string memory symbol_,
        address hook_,
        address poolManager_,
        address creator_,
        uint256 maxWallet_
    ) ERC20(name_, symbol_) {
        launcher = msg.sender;
        hook = hook_;
        poolManager = poolManager_;
        creator = creator_;
        maxWallet = maxWallet_;
        _mint(msg.sender, TOTAL_SUPPLY);
    }

    /// @notice Lift the pre-graduation cap. Callable once, only by the launcher
    /// or the hook (which runs graduation). One-way: only ever un-restricts.
    function setGraduated() external {
        if (msg.sender != launcher && msg.sender != hook) revert NotAuthorized();
        graduated = true;
    }

    function _isVenue(address a) internal view returns (bool) {
        return a == launcher || a == hook || a == poolManager;
    }

    function _update(address from, address to, uint256 value) internal override {
        // Self-contained anti-whale cap — NO external calls, no mutable authority.
        // Caps ONLY the pool-exit leg (a buy out of the PoolManager) pre-grad, so
        // ordinary wallet↔wallet transfers are never touched; the venue and the
        // creator are exempt. maxWallet == 0 disables the cap entirely.
        if (
            !graduated && maxWallet != 0 && from == poolManager && to != address(0) && !_isVenue(to) && to != creator
                && balanceOf(to) + value > maxWallet
        ) {
            revert MaxWalletExceeded();
        }
        super._update(from, to, value);
    }
}
Chain explorer2828msChain node79ms