JellyfishHybridToken

0xa305a24ed54bc66dac5c68bb505aacee198fc7c1

Verification
Verified
0.8.26+commit.8a97fa7a
Type
Contract
5,460 bytes
ABI entries
61
30 read · 8 write
License
none

Contract information

Address
0xa305a24ed54bc66dac5c68bb505aacee198fc7c1
Chain
Robinhood Chain (4663)
Compiler
0.8.26+commit.8a97fa7a
Optimization
Enabled
Creation tx
0x35de232b71…5f3e2c5861

Token

Name
JELLY
Symbol
JELLY
Decimals
18
Holders
46

Read contract (30)

AUCTION_ALLOCATION()uint256
COMMUNITY_ALLOCATION()uint256
DEVELOPMENT_ALLOCATION()uint256
LIQUIDITY_ALLOCATION()uint256
MAX_BUY_CAP()uint256
MAX_BUY_GROWTH_PER_SECOND()uint256
MAX_BUY_PRECISION()uint256
MAX_LIQUIDITY_ROUNDING_DUST()uint256
MAX_SYNC()uint256
START_MAX_BUY()uint256
TOTAL_SUPPLY()uint256
TREASURY_ALLOCATION()uint256
UNIT()uint256
allowance(address, address)uint256
balanceOf(address)uint256
decimals()uint8
hook()address
isLaunched()bool
jellyExcluded(address)bool
launchConfigured()bool
launchTime()uint64
liquidityAllocator()address
maxBuy()uint256
name()string
owner()address
permanentlyExcluded(address)bool
poolManager()address
registry()address
symbol()string
totalSupply()uint256

Events (6)

ApprovalJellyExcludedSetLaunchConfiguredLaunchedOwnershipTransferredTransfer

ABI

[
  {
    "inputs": [
      {
        "internalType": "string",
        "name": "name_",
        "type": "string"
      },
      {
        "internalType": "string",
        "name": "symbol_",
        "type": "string"
      },
      {
        "internalType": "address",
        "name": "poolManager_",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "initialOwner",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "auctionReserve",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "communityReserve",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "treasuryVesting",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "developmentVesting",
        "type": "address"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  {
    "inputs": [],
    "name": "AlreadyConfigured",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "AlreadyLaunched",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "amount",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "maximum",
        "type": "uint256"
      }
    ],
    "name": "BuyLimitExceeded",
    "type": "error"
  },
  {
    "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": "LiquidityRouteOnly",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "NotHook",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "owner",
        "type": "address"
      }
    ],
    "name": "OwnableInvalidOwner",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "account",
        "type": "address"
      }
    ],
    "name": "OwnableUnauthorizedAccount",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "PermanentlyExcluded",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "UnsafePrelaunchDistribution",
    "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": "account",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "bool",
        "name": "excluded",
        "type": "bool"
      }
    ],
    "name": "JellyExcludedSet",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "hook",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "registry",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "liquidityAllocator",
        "type": "address"
      }
    ],
    "name": "LaunchConfigured",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "poolManager",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint64",
        "name": "launchTime",
        "type": "uint64"
      }
    ],
    "name": "Launched",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "previousOwner",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "newOwner",
        "type": "address"
      }
    ],
    "name": "OwnershipTransferred",
    "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": "AUCTION_ALLOCATION",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "COMMUNITY_ALLOCATION",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "DEVELOPMENT_ALLOCATION",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "LIQUIDITY_ALLOCATION",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "MAX_BUY_CAP",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "MAX_BUY_GROWTH_PER_SECOND",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "MAX_BUY_PRECISION",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "MAX_LIQUIDITY_ROUNDING_DUST",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "MAX_SYNC",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "START_MAX_BUY",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "TOTAL_SUPPLY",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "TREASURY_ALLOCATION",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "UNIT",
    "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": [
      {
        "internalType": "address",
        "name": "hook_",
        "type": "address"
      },
      {
        "internalType": "contract IJellyfishTransferSync",
        "name": "registry_",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "liquidityAllocator_",
        "type": "address"
      }
    ],
    "name": "configureLaunch",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "decimals",
    "outputs": [
      {
        "internalType": "uint8",
        "name": "",
        "type": "uint8"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "hook",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "isLaunched",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "account",
        "type": "address"
      }
    ],
    "name": "jellyExcluded",
    "outputs": [
      {
        "internalType": "bool",
        "name": "excluded",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "launchConfigured",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "launchTime",
    "outputs": [
      {
        "internalType": "uint64",
        "name": "",
        "type": "uint64"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "liquidityAllocator",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "maxBuy",
    "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": "owner",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "account",
        "type": "address"
      }
    ],
    "name": "permanentlyExcluded",
    "outputs": [
      {
        "internalType": "bool",
        "name": "excluded",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "poolManager",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "registry",
    "outputs": [
      {
        "internalType": "contract IJellyfishTransferSync",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "renounceOwnership",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "account",
        "type": "address"
      },
      {
        "internalType": "bool",
        "name": "excluded",
        "type": "bool"
      }
    ],
    "name": "setJellyExcluded",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "start",
    "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"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "newOwner",
        "type": "address"
      }
    ],
    "name": "transferOwnership",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  }
]

Source code

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

import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { IJellyfishTransferSync } from "./IJellyfishHybrid.sol";

contract JellyfishHybridToken is ERC20, Ownable {
    uint256 public constant TOTAL_SUPPLY = 4_444 ether;
    uint256 public constant AUCTION_ALLOCATION = 1_778 ether;
    uint256 public constant LIQUIDITY_ALLOCATION = 1_111 ether;
    uint256 public constant MAX_LIQUIDITY_ROUNDING_DUST = 1 gwei;
    uint256 public constant COMMUNITY_ALLOCATION = 444 ether;
    uint256 public constant TREASURY_ALLOCATION = 667 ether;
    uint256 public constant DEVELOPMENT_ALLOCATION = 444 ether;
    uint256 public constant UNIT = 1 ether;
    uint256 public constant MAX_SYNC = 64;
    uint256 public constant MAX_BUY_PRECISION = 100_000;
    uint256 public constant START_MAX_BUY = (TOTAL_SUPPLY * 250) / MAX_BUY_PRECISION;
    uint256 public constant MAX_BUY_CAP = 64 ether;
    uint256 public constant MAX_BUY_GROWTH_PER_SECOND = 3;

    address public immutable poolManager;
    address public hook;
    address public liquidityAllocator;
    IJellyfishTransferSync public registry;
    bool public launchConfigured;
    bool public isLaunched;
    uint64 public launchTime;
    mapping(address account => bool excluded) public jellyExcluded;
    mapping(address account => bool excluded) public permanentlyExcluded;

    event LaunchConfigured(
        address indexed hook, address indexed registry, address indexed liquidityAllocator
    );
    event Launched(address indexed poolManager, uint64 launchTime);
    event JellyExcludedSet(address indexed account, bool excluded);

    error ZeroAddress();
    error AlreadyConfigured();
    error AlreadyLaunched();
    error NotHook();
    error UnsafePrelaunchDistribution();
    error LiquidityRouteOnly();
    error PermanentlyExcluded();
    error BuyLimitExceeded(uint256 amount, uint256 maximum);

    constructor(
        string memory name_,
        string memory symbol_,
        address poolManager_,
        address initialOwner,
        address auctionReserve,
        address communityReserve,
        address treasuryVesting,
        address developmentVesting
    ) ERC20(name_, symbol_) Ownable(initialOwner) {
        if (
            poolManager_.code.length == 0 || initialOwner == address(0)
                || auctionReserve == address(0) || communityReserve == address(0)
                || treasuryVesting == address(0) || developmentVesting == address(0)
        ) revert ZeroAddress();
        poolManager = poolManager_;
        _setPermanentExcluded(poolManager_);
        _setPermanentExcluded(initialOwner);
        _setPermanentExcluded(address(this));
        _setPermanentExcluded(address(0xdead));
        _setPermanentExcluded(auctionReserve);
        _setPermanentExcluded(communityReserve);
        _setPermanentExcluded(treasuryVesting);
        _setPermanentExcluded(developmentVesting);
        _mint(auctionReserve, AUCTION_ALLOCATION);
        _mint(address(this), LIQUIDITY_ALLOCATION);
        _mint(communityReserve, COMMUNITY_ALLOCATION);
        _mint(treasuryVesting, TREASURY_ALLOCATION);
        _mint(developmentVesting, DEVELOPMENT_ALLOCATION);
        assert(totalSupply() == TOTAL_SUPPLY);
    }

    function configureLaunch(
        address hook_,
        IJellyfishTransferSync registry_,
        address liquidityAllocator_
    ) external onlyOwner {
        if (launchConfigured || isLaunched) {
            revert AlreadyConfigured();
        }
        if (
            hook_.code.length == 0 || address(registry_).code.length == 0
                || liquidityAllocator_.code.length == 0
        ) revert ZeroAddress();
        if (balanceOf(address(this)) != LIQUIDITY_ALLOCATION) revert UnsafePrelaunchDistribution();
        hook = hook_;
        registry = registry_;
        liquidityAllocator = liquidityAllocator_;
        _setPermanentExcluded(hook_);
        _setPermanentExcluded(address(registry_));
        _setPermanentExcluded(liquidityAllocator_);
        launchConfigured = true;
        _transfer(address(this), liquidityAllocator_, LIQUIDITY_ALLOCATION);
        emit LaunchConfigured(hook_, address(registry_), liquidityAllocator_);
    }

    function start() external {
        if (msg.sender != hook || hook == address(0)) revert NotHook();
        if (isLaunched) revert AlreadyLaunched();
        if (!launchConfigured) revert AlreadyConfigured();
        uint256 allocatorBalance = balanceOf(liquidityAllocator);
        uint256 poolBalance = balanceOf(poolManager);
        if (
            allocatorBalance > MAX_LIQUIDITY_ROUNDING_DUST
                || poolBalance < LIQUIDITY_ALLOCATION - MAX_LIQUIDITY_ROUNDING_DUST
                || poolBalance + allocatorBalance < LIQUIDITY_ALLOCATION
        ) {
            revert UnsafePrelaunchDistribution();
        }
        isLaunched = true;
        launchTime = uint64(block.timestamp);
        emit Launched(poolManager, launchTime);
    }

    function setJellyExcluded(address account, bool excluded) external onlyOwner {
        if (isLaunched) revert AlreadyLaunched();
        if (!excluded && permanentlyExcluded[account]) revert PermanentlyExcluded();
        if (excluded) permanentlyExcluded[account] = true;
        jellyExcluded[account] = excluded;
        emit JellyExcludedSet(account, excluded);
    }

    function maxBuy() public view returns (uint256) {
        if (!isLaunched) return 0;
        uint256 value = START_MAX_BUY
            + (TOTAL_SUPPLY * (block.timestamp - launchTime) * MAX_BUY_GROWTH_PER_SECOND)
            / MAX_BUY_PRECISION;
        return value > MAX_BUY_CAP ? MAX_BUY_CAP : value;
    }

    function _update(address from, address to, uint256 amount) internal override {
        if (launchConfigured && from == liquidityAllocator && to != poolManager && to != address(0))
        {
            revert LiquidityRouteOnly();
        }
        super._update(from, to, amount);
        if (!isLaunched || amount == 0 || address(registry) == address(0)) return;
        if (from == poolManager && _canReceive(to)) {
            uint256 maximum = maxBuy();
            if (amount > maximum) revert BuyLimitExceeded(amount, maximum);
        }
        registry.syncAfterTransfer(from, to, amount, bytes32(0));
    }

    function _canReceive(address account) private view returns (bool) {
        return account != address(0) && account != address(this) && !jellyExcluded[account];
    }

    function _setPermanentExcluded(address account) private {
        permanentlyExcluded[account] = true;
        jellyExcluded[account] = true;
        emit JellyExcludedSet(account, true);
    }
}
Chain explorer6015msChain node87ms