BycocketToken

0xc79d46d716b33b463b3a6574d6ee26009abf4e9a

Verification
Verified
v0.8.35+commit.47b9dedd
Type
Contract
7,288 bytes
ABI entries
61
17 read · 12 write
License
mit

Contract information

Address
0xc79d46d716b33b463b3a6574d6ee26009abf4e9a
Chain
Robinhood Chain (4663)
Compiler
v0.8.35+commit.47b9dedd
Optimization
Enabled
Creation tx
0x7ab262262b…7d20b41ef0

Token

Name
Bycocket
Symbol
BYCOCKET
Decimals
18
Holders
1,597

Read contract (17)

DOMAIN_SEPARATOR()bytes32
POOL_TOKEN_AMOUNT()uint256
UNISWAP_V2_ROUTER()address
allowance(address, address)uint256
balanceOf(address)uint256
decimals()uint8
eip712Domain()bytes1, string, string, uint256, address, bytes32, uint256[]
initialLiquidityAdded()bool
isExcludedFromFees(address)bool
name()string
nonces(address)uint256
owner()address
symbol()string
totalSupply()uint256
tradingActive()bool
tradingActiveBlock()uint32
uniswapV2Pair()address

Events (8)

ApprovalEIP712DomainChangedExcludedFromFeesSetInitialLiquidityAddedOwnershipTransferredPairCreatedPublicTradingOpenedTransfer

ABI

[
  {
    "inputs": [
      {
        "components": [
          {
            "internalType": "string",
            "name": "name",
            "type": "string"
          },
          {
            "internalType": "string",
            "name": "symbol",
            "type": "string"
          },
          {
            "internalType": "uint8",
            "name": "decimals_",
            "type": "uint8"
          },
          {
            "internalType": "uint256",
            "name": "totalSupply",
            "type": "uint256"
          },
          {
            "internalType": "uint256",
            "name": "poolTokenAmount",
            "type": "uint256"
          },
          {
            "internalType": "address",
            "name": "uniswapV2Router",
            "type": "address"
          }
        ],
        "internalType": "struct BycocketToken.LaunchTokenConfig",
        "name": "config",
        "type": "tuple"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  {
    "inputs": [],
    "name": "ECDSAInvalidSignature",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "length",
        "type": "uint256"
      }
    ],
    "name": "ECDSAInvalidSignatureLength",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "bytes32",
        "name": "s",
        "type": "bytes32"
      }
    ],
    "name": "ECDSAInvalidSignatureS",
    "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": [
      {
        "internalType": "uint256",
        "name": "deadline",
        "type": "uint256"
      }
    ],
    "name": "ERC2612ExpiredSignature",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "signer",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "owner",
        "type": "address"
      }
    ],
    "name": "ERC2612InvalidSigner",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "InitialLiquidityAlreadyAdded",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "InitialLiquidityNotAdded",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "account",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "currentNonce",
        "type": "uint256"
      }
    ],
    "name": "InvalidAccountNonce",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "InvalidRecipient",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "InvalidShortString",
    "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": "PairNotCreated",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "ProtectedExclusion",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "string",
        "name": "str",
        "type": "string"
      }
    ],
    "name": "StringTooLong",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "TradingAlreadyActive",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "UnauthorizedTransferBeforeTrading",
    "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": [],
    "name": "EIP712DomainChanged",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "account",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "bool",
        "name": "excluded",
        "type": "bool"
      }
    ],
    "name": "ExcludedFromFeesSet",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "pair",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "tokenAmount",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "ethAmount",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "liquidity",
        "type": "uint256"
      }
    ],
    "name": "InitialLiquidityAdded",
    "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": "pair",
        "type": "address"
      }
    ],
    "name": "PairCreated",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "uint32",
        "name": "tradingActiveBlock",
        "type": "uint32"
      }
    ],
    "name": "PublicTradingOpened",
    "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": "DOMAIN_SEPARATOR",
    "outputs": [
      {
        "internalType": "bytes32",
        "name": "",
        "type": "bytes32"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "POOL_TOKEN_AMOUNT",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "UNISWAP_V2_ROUTER",
    "outputs": [
      {
        "internalType": "contract IUniswapV2Router02",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "tokenAmount",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "amountTokenMin",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "amountEthMin",
        "type": "uint256"
      },
      {
        "internalType": "address",
        "name": "lpRecipient",
        "type": "address"
      }
    ],
    "name": "addInitialLiquidity",
    "outputs": [],
    "stateMutability": "payable",
    "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": "uint256",
        "name": "value",
        "type": "uint256"
      }
    ],
    "name": "burn",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "account",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "value",
        "type": "uint256"
      }
    ],
    "name": "burnFrom",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "createPair",
    "outputs": [
      {
        "internalType": "address",
        "name": "pair",
        "type": "address"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "decimals",
    "outputs": [
      {
        "internalType": "uint8",
        "name": "",
        "type": "uint8"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "eip712Domain",
    "outputs": [
      {
        "internalType": "bytes1",
        "name": "fields",
        "type": "bytes1"
      },
      {
        "internalType": "string",
        "name": "name",
        "type": "string"
      },
      {
        "internalType": "string",
        "name": "version",
        "type": "string"
      },
      {
        "internalType": "uint256",
        "name": "chainId",
        "type": "uint256"
      },
      {
        "internalType": "address",
        "name": "verifyingContract",
        "type": "address"
      },
      {
        "internalType": "bytes32",
        "name": "salt",
        "type": "bytes32"
      },
      {
        "internalType": "uint256[]",
        "name": "extensions",
        "type": "uint256[]"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "initialLiquidityAdded",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "account",
        "type": "address"
      }
    ],
    "name": "isExcludedFromFees",
    "outputs": [
      {
        "internalType": "bool",
        "name": "excluded",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "name",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "owner",
        "type": "address"
      }
    ],
    "name": "nonces",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "openTrading",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "owner",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "owner",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "spender",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "value",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "deadline",
        "type": "uint256"
      },
      {
        "internalType": "uint8",
        "name": "v",
        "type": "uint8"
      },
      {
        "internalType": "bytes32",
        "name": "r",
        "type": "bytes32"
      },
      {
        "internalType": "bytes32",
        "name": "s",
        "type": "bytes32"
      }
    ],
    "name": "permit",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "renounceOwnership",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address[]",
        "name": "accounts",
        "type": "address[]"
      },
      {
        "internalType": "bool",
        "name": "excluded",
        "type": "bool"
      }
    ],
    "name": "setExcludedFromFees",
    "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": [],
    "name": "tradingActive",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "tradingActiveBlock",
    "outputs": [
      {
        "internalType": "uint32",
        "name": "",
        "type": "uint32"
      }
    ],
    "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"
  },
  {
    "inputs": [],
    "name": "uniswapV2Pair",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  }
]

Source code

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;

import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { ERC20Burnable } from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import { ERC20Permit } from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";

import { IUniswapV2Factory } from "../interfaces/IUniswapV2Factory.sol";
import { IUniswapV2Pair } from "../interfaces/IUniswapV2Pair.sol";
import { IUniswapV2Router02 } from "../interfaces/IUniswapV2Router02.sol";

contract BycocketToken is ERC20, ERC20Burnable, ERC20Permit, Ownable {
    struct LaunchTokenConfig {
        string name;
        string symbol;
        uint8 decimals_;
        uint256 totalSupply;
        uint256 poolTokenAmount;
        address uniswapV2Router;
    }

    IUniswapV2Router02 public immutable UNISWAP_V2_ROUTER;
    uint8 private immutable TOKEN_DECIMALS;
    uint256 public immutable POOL_TOKEN_AMOUNT;

    address public uniswapV2Pair;
    bool public tradingActive;
    bool public initialLiquidityAdded;
    uint32 public tradingActiveBlock;

    mapping(address account => bool excluded) public isExcludedFromFees;

    event PairCreated(address indexed pair);
    event InitialLiquidityAdded(
        address indexed pair, uint256 tokenAmount, uint256 ethAmount, uint256 liquidity
    );
    event PublicTradingOpened(uint32 tradingActiveBlock);
    event ExcludedFromFeesSet(address indexed account, bool excluded);

    error InvalidRecipient();
    error PairNotCreated();
    error InitialLiquidityAlreadyAdded();
    error InitialLiquidityNotAdded();
    error ProtectedExclusion();
    error TradingAlreadyActive();
    error UnauthorizedTransferBeforeTrading();

    /**
     * @notice Deploys a no-tax Base Uniswap v2 launch token.
     * @param config Token metadata, launch allocation, and router settings.
     */
    constructor(LaunchTokenConfig memory config)
        ERC20(config.name, config.symbol)
        ERC20Permit(config.name)
        Ownable(msg.sender)
    {
        TOKEN_DECIMALS = config.decimals_;
        POOL_TOKEN_AMOUNT = config.poolTokenAmount;
        UNISWAP_V2_ROUTER = IUniswapV2Router02(config.uniswapV2Router);

        _setFeeExcluded(msg.sender, true);
        _setFeeExcluded(address(this), true);
        _setFeeExcluded(config.uniswapV2Router, true);
        _setFeeExcluded(address(0xdead), true);

        _mint(address(this), config.poolTokenAmount);
        uint256 retainedSupply = config.totalSupply - config.poolTokenAmount;
        if (retainedSupply != 0) {
            _mint(msg.sender, retainedSupply);
        }
    }

    /**
     * @notice Returns the configured display decimals for the token.
     * @return Token decimals.
     */
    function decimals() public view override returns (uint8) {
        return TOKEN_DECIMALS;
    }

    /**
     * @notice Creates the Uniswap v2 WETH pair before Base launch construction.
     * @return pair The created pair address.
     */
    function createPair() external onlyOwner returns (address pair) {
        if (tradingActive) revert TradingAlreadyActive();

        IUniswapV2Factory factory = IUniswapV2Factory(UNISWAP_V2_ROUTER.factory());
        address weth = UNISWAP_V2_ROUTER.WETH();
        pair = factory.createPair(address(this), weth);

        uniswapV2Pair = pair;

        emit PairCreated(pair);
    }

    /**
     * @notice Adds initial Uniswap v2 liquidity while public trading remains closed.
     * @param tokenAmount Amount of this token to pair with the supplied ETH.
     * @param amountTokenMin Minimum token amount accepted by the router.
     * @param amountEthMin Minimum ETH amount accepted by the router.
     * @param lpRecipient Recipient of the minted LP tokens.
     */
    function addInitialLiquidity(
        uint256 tokenAmount,
        uint256 amountTokenMin,
        uint256 amountEthMin,
        address lpRecipient
    ) external payable onlyOwner {
        address pair = uniswapV2Pair;
        if (pair == address(0)) revert PairNotCreated();
        if (tradingActive) revert TradingAlreadyActive();
        if (initialLiquidityAdded) revert InitialLiquidityAlreadyAdded();

        IUniswapV2Pair(pair).skim(owner());
        _approve(address(this), address(UNISWAP_V2_ROUTER), type(uint256).max);

        (uint256 amountToken, uint256 amountEth, uint256 liquidity) = UNISWAP_V2_ROUTER.addLiquidityETH{
            value: msg.value
        }(
            address(this), tokenAmount, amountTokenMin, amountEthMin, lpRecipient, block.timestamp
        );

        initialLiquidityAdded = true;

        emit InitialLiquidityAdded(pair, amountToken, amountEth, liquidity);
    }

    /**
     * @notice Opens public trading after liquidity and exempt launch-wallet buys are complete.
     */
    function openTrading() external onlyOwner {
        if (uniswapV2Pair == address(0)) revert PairNotCreated();
        if (!initialLiquidityAdded) revert InitialLiquidityNotAdded();
        if (tradingActive) revert TradingAlreadyActive();

        tradingActive = true;
        tradingActiveBlock = uint32(block.number);

        emit PublicTradingOpened(tradingActiveBlock);
    }

    /**
     * @notice Adds or removes pre-trading launch exemptions.
     * @param accounts Accounts to update.
     * @param excluded Whether each account should be excluded.
     */
    function setExcludedFromFees(address[] calldata accounts, bool excluded) external onlyOwner {
        for (uint256 i = 0; i < accounts.length; i++) {
            address account = accounts[i];
            if (account == address(0)) revert InvalidRecipient();
            if (account == uniswapV2Pair) revert ProtectedExclusion();
            if (!excluded && _isProtectedExclusion(account)) revert ProtectedExclusion();

            _setFeeExcluded(account, excluded);

            emit ExcludedFromFeesSet(account, excluded);
        }
    }

    function _update(address from, address to, uint256 amount) internal override {
        if (
            from != address(0) && to != address(0) && !tradingActive && !isExcludedFromFees[from]
                && !isExcludedFromFees[to]
        ) {
            revert UnauthorizedTransferBeforeTrading();
        }
        super._update(from, to, amount);
    }

    function _setFeeExcluded(address account, bool excluded) private {
        isExcludedFromFees[account] = excluded;
    }

    function _isProtectedExclusion(address account) private view returns (bool) {
        return account == owner() || account == address(this)
            || account == address(UNISWAP_V2_ROUTER) || account == address(0xdead);
    }
}
Chain explorer3926msChain node79ms