TrencherToken
0x36b920cf00e1f5caff97071835213cd3c069760f
Verification
Verified
v0.8.28+commit.7893614a
Type
Contract
13,824 bytes
ABI entries
84
35 read · 13 write
License
none
Contract information
- Address
- 0x36b920cf00e1f5caff97071835213cd3c069760f
- Chain
- Robinhood Chain (4663)
- Compiler
- v0.8.28+commit.7893614a
- Optimization
- Enabled
- Creator
- 0xE769D83293…1920bc7734
- Creation tx
- 0x3ad2859e52…d2a31572ca
Token
- Name
- test
- Symbol
- TEST
- Decimals
- 18
- Holders
- 5
- Market
- View token page →
Read contract (35)
CLOCK_MODE() → string
DEAD() → address
DOMAIN_SEPARATOR() → bytes32
MAX_WALLET_BPS() → uint256
RESTRICTION_BLOCKS() → uint256
admin() → address
allowance(address, address) → uint256
balanceOf(address) → uint256
checkpoints(address, uint32) → tuple
clock() → uint48
context() → string
decimals() → uint8
delegates(address) → address
eip712Domain() → bytes1, string, string, uint256, address, bytes32, uint256[]
getPastTotalSupply(uint256) → uint256
getPastVotes(address, uint256) → uint256
getVotes(address) → uint256
imageUrl() → string
initialBuyer() → address
isVerified() → bool
launchBlock() → uint256
launcher() → address
locker() → address
maxWallet() → uint256
metadata() → string
name() → string
nonces(address) → uint256
numCheckpoints(address) → uint32
pool() → address
restrictionEndBlock() → uint256
restrictionsActive() → bool
supportsInterface(bytes4) → bool
symbol() → string
totalSupply() → uint256
vault() → address
Events (10)
ApprovalCrosschainBurnCrosschainMintDelegateChangedDelegateVotesChangedEIP712DomainChangedTransferUpdateImageUpdateMetadataVerified
ABI
[
{
"inputs": [
{
"internalType": "string",
"name": "name_",
"type": "string"
},
{
"internalType": "string",
"name": "symbol_",
"type": "string"
},
{
"internalType": "uint256",
"name": "maxSupply_",
"type": "uint256"
},
{
"internalType": "address",
"name": "admin_",
"type": "address"
},
{
"internalType": "string",
"name": "image_",
"type": "string"
},
{
"internalType": "string",
"name": "metadata_",
"type": "string"
},
{
"internalType": "string",
"name": "context_",
"type": "string"
},
{
"internalType": "uint256",
"name": "initialSupplyChainId_",
"type": "uint256"
},
{
"internalType": "address",
"name": "locker_",
"type": "address"
},
{
"internalType": "address",
"name": "vault_",
"type": "address"
},
{
"internalType": "address",
"name": "uniswapV3Factory_",
"type": "address"
},
{
"internalType": "address",
"name": "weth_",
"type": "address"
},
{
"internalType": "uint24",
"name": "poolFee_",
"type": "uint24"
},
{
"internalType": "address",
"name": "initialBuyer_",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "AlreadyVerified",
"type": "error"
},
{
"inputs": [],
"name": "CheckpointUnorderedInsertion",
"type": "error"
},
{
"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": "uint256",
"name": "increasedSupply",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "cap",
"type": "uint256"
}
],
"name": "ERC20ExceededSafeSupply",
"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": [
{
"internalType": "uint256",
"name": "timepoint",
"type": "uint256"
},
{
"internalType": "uint48",
"name": "clock",
"type": "uint48"
}
],
"name": "ERC5805FutureLookup",
"type": "error"
},
{
"inputs": [],
"name": "ERC6372InconsistentClock",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
},
{
"internalType": "uint256",
"name": "currentNonce",
"type": "uint256"
}
],
"name": "InvalidAccountNonce",
"type": "error"
},
{
"inputs": [],
"name": "InvalidPoolKey",
"type": "error"
},
{
"inputs": [],
"name": "InvalidShortString",
"type": "error"
},
{
"inputs": [],
"name": "MaxWalletExceeded",
"type": "error"
},
{
"inputs": [],
"name": "NotAdmin",
"type": "error"
},
{
"inputs": [
{
"internalType": "uint8",
"name": "bits",
"type": "uint8"
},
{
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "SafeCastOverflowedUintDowncast",
"type": "error"
},
{
"inputs": [
{
"internalType": "string",
"name": "str",
"type": "string"
}
],
"name": "StringTooLong",
"type": "error"
},
{
"inputs": [],
"name": "Unauthorized",
"type": "error"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "expiry",
"type": "uint256"
}
],
"name": "VotesExpiredSignature",
"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": false,
"internalType": "uint256",
"name": "amount",
"type": "uint256"
},
{
"indexed": true,
"internalType": "address",
"name": "sender",
"type": "address"
}
],
"name": "CrosschainBurn",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "to",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "amount",
"type": "uint256"
},
{
"indexed": true,
"internalType": "address",
"name": "sender",
"type": "address"
}
],
"name": "CrosschainMint",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "delegator",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "fromDelegate",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "toDelegate",
"type": "address"
}
],
"name": "DelegateChanged",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "delegate",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "previousVotes",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "newVotes",
"type": "uint256"
}
],
"name": "DelegateVotesChanged",
"type": "event"
},
{
"anonymous": false,
"inputs": [],
"name": "EIP712DomainChanged",
"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"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "image",
"type": "string"
}
],
"name": "UpdateImage",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "string",
"name": "metadata",
"type": "string"
}
],
"name": "UpdateMetadata",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "admin",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "token",
"type": "address"
}
],
"name": "Verified",
"type": "event"
},
{
"inputs": [],
"name": "CLOCK_MODE",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "DEAD",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "DOMAIN_SEPARATOR",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "MAX_WALLET_BPS",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "RESTRICTION_BLOCKS",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "admin",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"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": "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": [
{
"internalType": "address",
"name": "account",
"type": "address"
},
{
"internalType": "uint32",
"name": "pos",
"type": "uint32"
}
],
"name": "checkpoints",
"outputs": [
{
"components": [
{
"internalType": "uint48",
"name": "_key",
"type": "uint48"
},
{
"internalType": "uint208",
"name": "_value",
"type": "uint208"
}
],
"internalType": "struct Checkpoints.Checkpoint208",
"name": "",
"type": "tuple"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "clock",
"outputs": [
{
"internalType": "uint48",
"name": "",
"type": "uint48"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "context",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_from",
"type": "address"
},
{
"internalType": "uint256",
"name": "_amount",
"type": "uint256"
}
],
"name": "crosschainBurn",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_to",
"type": "address"
},
{
"internalType": "uint256",
"name": "_amount",
"type": "uint256"
}
],
"name": "crosschainMint",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "decimals",
"outputs": [
{
"internalType": "uint8",
"name": "",
"type": "uint8"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "delegatee",
"type": "address"
}
],
"name": "delegate",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "delegatee",
"type": "address"
},
{
"internalType": "uint256",
"name": "nonce",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "expiry",
"type": "uint256"
},
{
"internalType": "uint8",
"name": "v",
"type": "uint8"
},
{
"internalType": "bytes32",
"name": "r",
"type": "bytes32"
},
{
"internalType": "bytes32",
"name": "s",
"type": "bytes32"
}
],
"name": "delegateBySig",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "delegates",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"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": [
{
"internalType": "uint256",
"name": "timepoint",
"type": "uint256"
}
],
"name": "getPastTotalSupply",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
},
{
"internalType": "uint256",
"name": "timepoint",
"type": "uint256"
}
],
"name": "getPastVotes",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "getVotes",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "imageUrl",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "initialBuyer",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "isVerified",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "launchBlock",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "launcher",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "locker",
"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": "metadata",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"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": [
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "numCheckpoints",
"outputs": [
{
"internalType": "uint32",
"name": "",
"type": "uint32"
}
],
"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": "pool",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "restrictionEndBlock",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "restrictionsActive",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes4",
"name": "_interfaceId",
"type": "bytes4"
}
],
"name": "supportsInterface",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "pure",
"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": "string",
"name": "image_",
"type": "string"
}
],
"name": "updateImage",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "string",
"name": "metadata_",
"type": "string"
}
],
"name": "updateMetadata",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "vault",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "verify",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]Source code
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
import {IERC7802} from "../lib/optimism/packages/contracts-bedrock/interfaces/L2/IERC7802.sol";
import {Predeploys} from "../lib/optimism/packages/contracts-bedrock/src/libraries/Predeploys.sol";
import {Unauthorized} from "../lib/optimism/packages/contracts-bedrock/src/libraries/errors/CommonErrors.sol";
import {IERC165} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol";
import {IERC5805} from "../lib/openzeppelin-contracts/contracts/interfaces/IERC5805.sol";
import {ERC20} from "../lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol";
import {IERC20} from "../lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import {ERC20Burnable} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import {ERC20Permit} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Permit.sol";
import {ERC20Votes} from "../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Votes.sol";
import {Nonces} from "../lib/openzeppelin-contracts/contracts/utils/Nonces.sol";
import {PoolAddress} from "./libraries/PoolAddress.sol";
/// @notice TRENCHER ERC-20 with a factory-fixed anti-snipe max-wallet window.
/// @dev Limits are immutable protocol constants — not settable by token admin / creator.
/// After `restrictionEndBlock` the token is permanently vanilla (no owner toggle to re-enable).
contract TrencherToken is ERC20, ERC20Permit, ERC20Votes, ERC20Burnable, IERC7802 {
error NotAdmin();
error AlreadyVerified();
error MaxWalletExceeded();
/// @dev 2.00% of total supply. Fixed — creators cannot choose a weaker or stronger cap.
uint256 public constant MAX_WALLET_BPS = 200;
/// @dev ~300 L1-estimate blocks on Arbitrum Orbit (~1h). Fixed — not extendable.
uint256 public constant RESTRICTION_BLOCKS = 300;
address public constant DEAD = 0x000000000000000000000000000000000000dEaD;
address private _admin;
string private _metadata;
string private _context;
string private _image;
bool private _verified;
/// @notice Factory that deployed this token (only msg.sender at construction).
address public immutable launcher;
address public immutable locker;
address public immutable vault;
/// @notice Deterministic Uniswap v3 pool; must match factory.createPool.
address public immutable pool;
/// @notice Absolute max balance for non-exempt wallets during the window.
uint256 public immutable maxWallet;
uint256 public immutable launchBlock;
uint256 public immutable restrictionEndBlock;
/// @notice Wallet that called `deployToken` (dev / initial buyer). Exempt from max-wallet
/// for the restriction window so launch-time buys can exceed 2%; other wallets stay capped.
address public immutable initialBuyer;
event Verified(address indexed admin, address indexed token);
event UpdateImage(string image);
event UpdateMetadata(string metadata);
constructor(
string memory name_,
string memory symbol_,
uint256 maxSupply_,
address admin_,
string memory image_,
string memory metadata_,
string memory context_,
uint256 initialSupplyChainId_,
address locker_,
address vault_,
address uniswapV3Factory_,
address weth_,
uint24 poolFee_,
address initialBuyer_
) ERC20(name_, symbol_) ERC20Permit(name_) {
_admin = admin_;
_image = image_;
_metadata = metadata_;
_context = context_;
launcher = msg.sender;
locker = locker_;
vault = vault_;
pool = PoolAddress.computeAddress(
uniswapV3Factory_, PoolAddress.getPoolKey(address(this), weth_, poolFee_)
);
maxWallet = (maxSupply_ * MAX_WALLET_BPS) / 10_000;
launchBlock = block.number;
restrictionEndBlock = block.number + RESTRICTION_BLOCKS;
initialBuyer = initialBuyer_;
// Only mint initial supply on a single chain
if (block.chainid == initialSupplyChainId_) {
_mint(msg.sender, maxSupply_);
}
}
function updateImage(string memory image_) external {
if (msg.sender != _admin) {
revert NotAdmin();
}
_image = image_;
emit UpdateImage(image_);
}
function updateMetadata(string memory metadata_) external {
if (msg.sender != _admin) {
revert NotAdmin();
}
_metadata = metadata_;
emit UpdateMetadata(metadata_);
}
/// @dev Max wallet applies to every hop during the window (closes router-custody bypass).
/// Protocol sinks are exempt: pool (sells/LP), locker, vault, factory, dead.
/// `initialBuyer` (deployer / launch-time buyer) is exempt so a large dev buy can land.
/// Other EOAs — including token admin if different — stay under the 2% cap.
/// No owner knobs: cannot disable, extend, or add exemptions after deploy.
function _update(address from, address to, uint256 value)
internal
override(ERC20, ERC20Votes)
{
if (from != address(0) && block.number < restrictionEndBlock) {
bool exemptRecipient = to == pool || to == locker || to == vault || to == launcher
|| to == DEAD || to == initialBuyer;
if (!exemptRecipient && balanceOf(to) + value > maxWallet) {
revert MaxWalletExceeded();
}
}
super._update(from, to, value);
}
function verify() external {
if (msg.sender != _admin) {
revert NotAdmin();
}
if (_verified) {
revert AlreadyVerified();
}
_verified = true;
emit Verified(msg.sender, address(this));
}
function isVerified() external view returns (bool) {
return _verified;
}
function restrictionsActive() external view returns (bool) {
return block.number < restrictionEndBlock;
}
function nonces(address owner) public view override(ERC20Permit, Nonces) returns (uint256) {
return super.nonces(owner);
}
function admin() external view returns (address) {
return _admin;
}
function imageUrl() external view returns (string memory) {
return _image;
}
function metadata() external view returns (string memory) {
return _metadata;
}
function context() external view returns (string memory) {
return _context;
}
function crosschainMint(address _to, uint256 _amount) external {
// Only the `SuperchainTokenBridge` has permissions to mint tokens during crosschain transfers.
if (msg.sender != Predeploys.SUPERCHAIN_TOKEN_BRIDGE) revert Unauthorized();
// Mint tokens to the `_to` account's balance.
_mint(_to, _amount);
// Emit the CrosschainMint event included on IERC7802 for tracking token mints associated with cross chain transfers.
emit CrosschainMint(_to, _amount, msg.sender);
}
function crosschainBurn(address _from, uint256 _amount) external {
// Only the `SuperchainTokenBridge` has permissions to burn tokens during crosschain transfers.
if (msg.sender != Predeploys.SUPERCHAIN_TOKEN_BRIDGE) revert Unauthorized();
// Burn the tokens from the `_from` account's balance.
_burn(_from, _amount);
// Emit the CrosschainBurn event included on IERC7802 for tracking token burns associated with cross chain transfers.
emit CrosschainBurn(_from, _amount, msg.sender);
}
function supportsInterface(bytes4 _interfaceId) public pure returns (bool) {
return _interfaceId == type(IERC7802).interfaceId
|| _interfaceId == type(IERC20).interfaceId || _interfaceId == type(IERC165).interfaceId
|| _interfaceId == type(IERC5805).interfaceId;
}
}
Chain explorer2740msChain node80ms