Token
0x9f8b669a4d61a47d402edefe4f43d87ed0e36b1f
Verification
Verified
v0.8.24+commit.e11b9ed9
Type
Contract
11,431 bytes
ABI entries
72
24 read · 19 write
License
none
Contract information
- Address
- 0x9f8b669a4d61a47d402edefe4f43d87ed0e36b1f
- Chain
- Robinhood Chain (4663)
- Compiler
- v0.8.24+commit.e11b9ed9
- Optimization
- Enabled
- Creator
- 0xB94F65B2a3…4939b0D0aD
- Creation tx
- 0x19f8615587…2fb3a8dc56
Token
- Name
- Token
- Symbol
- TOKEN
- Decimals
- 18
- Holders
- 1
- Market
- View token page →
Read contract (24)
FEE_PRECISION() → uint16
MAX_FEE() → uint16
MAX_SWAP_THRESHOLD_RATIO() → uint256
MIN_ANTI_WHALE_RATIO() → uint256
allowance(address, address) → uint256
autoProcessFees() → bool
balanceOf(address) → uint256
decimals() → uint8
feeCollectorShares(address) → uint256
feeCollectors(uint256) → address
feeConfiguration() → uint16, uint16, uint16, uint16, uint16, uint16, bool
isExcludedFromFees(address) → bool
isExemptFromAntiWhale(address) → bool
isLpPool(address) → bool
liquidityOwner() → address
maxWalletHolding() → uint256
name() → string
numTokensToSwap() → uint256
owner() → address
symbol() → string
totalFeeCollectorShares() → uint256
totalSupply() → uint256
uniswapV2Pair() → address
uniswapV2Router() → address
Events (19)
ApprovalAutoProcessFeesUpdatedETHRescuedExcludedFromFeesUpdatedExemptFromAntiWhaleUpdatedFeeCollectorRemovedFeeCollectorUpdatedFeeConfigurationUpdatedFeeDistributionFailedFeesProcessedLiquidityOwnerUpdatedLpPoolUpdatedMaxWalletHoldingUpdatedNumTokensToSwapUpdatedOwnershipTransferredSwapRouterUpdatedTokensBurnedTokensRescuedTransfer
ABI
[
{
"inputs": [
{
"internalType": "string",
"name": "name",
"type": "string"
},
{
"internalType": "string",
"name": "symbol",
"type": "string"
},
{
"internalType": "uint256",
"name": "totalSupply",
"type": "uint256"
},
{
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"internalType": "uint8",
"name": "decimals_",
"type": "uint8"
},
{
"internalType": "uint256",
"name": "_maxWalletHolding",
"type": "uint256"
},
{
"internalType": "address",
"name": "_uniswapV2Router",
"type": "address"
},
{
"internalType": "address",
"name": "_liquidityWallet",
"type": "address"
},
{
"components": [
{
"internalType": "uint16",
"name": "buyFees",
"type": "uint16"
},
{
"internalType": "uint16",
"name": "sellFees",
"type": "uint16"
},
{
"internalType": "uint16",
"name": "transferFees",
"type": "uint16"
},
{
"internalType": "uint16",
"name": "burnFeeRatio",
"type": "uint16"
},
{
"internalType": "uint16",
"name": "liquidityFeeRatio",
"type": "uint16"
},
{
"internalType": "uint16",
"name": "collectorsFeeRatio",
"type": "uint16"
},
{
"internalType": "bool",
"name": "feesInToken",
"type": "bool"
}
],
"internalType": "struct Token.FeeConfiguration",
"name": "_feeConfiguration",
"type": "tuple"
},
{
"internalType": "address[]",
"name": "_feeCollectors",
"type": "address[]"
},
{
"internalType": "uint256[]",
"name": "_feeCollectorShares",
"type": "uint256[]"
},
{
"internalType": "address[]",
"name": "_dexRouters",
"type": "address[]"
}
],
"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": [
{
"internalType": "address",
"name": "owner",
"type": "address"
}
],
"name": "OwnableInvalidOwner",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "OwnableUnauthorizedAccount",
"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": false,
"internalType": "bool",
"name": "enabled",
"type": "bool"
}
],
"name": "AutoProcessFeesUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "to",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "ETHRescued",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "account",
"type": "address"
},
{
"indexed": false,
"internalType": "bool",
"name": "excluded",
"type": "bool"
}
],
"name": "ExcludedFromFeesUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "account",
"type": "address"
},
{
"indexed": false,
"internalType": "bool",
"name": "exempt",
"type": "bool"
}
],
"name": "ExemptFromAntiWhaleUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "collector",
"type": "address"
}
],
"name": "FeeCollectorRemoved",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "collector",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "share",
"type": "uint256"
}
],
"name": "FeeCollectorUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint16",
"name": "buyFees",
"type": "uint16"
},
{
"indexed": false,
"internalType": "uint16",
"name": "sellFees",
"type": "uint16"
},
{
"indexed": false,
"internalType": "uint16",
"name": "transferFees",
"type": "uint16"
},
{
"indexed": false,
"internalType": "uint16",
"name": "burnFeeRatio",
"type": "uint16"
},
{
"indexed": false,
"internalType": "uint16",
"name": "liquidityFeeRatio",
"type": "uint16"
},
{
"indexed": false,
"internalType": "uint16",
"name": "collectorsFeeRatio",
"type": "uint16"
},
{
"indexed": false,
"internalType": "bool",
"name": "feesInToken",
"type": "bool"
}
],
"name": "FeeConfigurationUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "collector",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "FeeDistributionFailed",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint256",
"name": "tokensSwapped",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "ethReceived",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "liquidityTokens",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "liquidityETH",
"type": "uint256"
}
],
"name": "FeesProcessed",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "oldOwner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "LiquidityOwnerUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "pair",
"type": "address"
},
{
"indexed": false,
"internalType": "bool",
"name": "isLp",
"type": "bool"
}
],
"name": "LpPoolUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint256",
"name": "maxHolding",
"type": "uint256"
}
],
"name": "MaxWalletHoldingUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "NumTokensToSwapUpdated",
"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": "oldRouter",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "newRouter",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "newPair",
"type": "address"
}
],
"name": "SwapRouterUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "TokensBurned",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "token",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "to",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "TokensRescued",
"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": "FEE_PRECISION",
"outputs": [
{
"internalType": "uint16",
"name": "",
"type": "uint16"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "MAX_FEE",
"outputs": [
{
"internalType": "uint16",
"name": "",
"type": "uint16"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "MAX_SWAP_THRESHOLD_RATIO",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "MIN_ANTI_WHALE_RATIO",
"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": [],
"name": "autoProcessFees",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "decimals",
"outputs": [
{
"internalType": "uint8",
"name": "",
"type": "uint8"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "feeCollectorShares",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "feeCollectors",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "feeConfiguration",
"outputs": [
{
"internalType": "uint16",
"name": "buyFees",
"type": "uint16"
},
{
"internalType": "uint16",
"name": "sellFees",
"type": "uint16"
},
{
"internalType": "uint16",
"name": "transferFees",
"type": "uint16"
},
{
"internalType": "uint16",
"name": "burnFeeRatio",
"type": "uint16"
},
{
"internalType": "uint16",
"name": "liquidityFeeRatio",
"type": "uint16"
},
{
"internalType": "uint16",
"name": "collectorsFeeRatio",
"type": "uint16"
},
{
"internalType": "bool",
"name": "feesInToken",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "isExcludedFromFees",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "isExemptFromAntiWhale",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "isLpPool",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "liquidityOwner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "maxWalletHolding",
"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": "numTokensToSwap",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "minAmountOut",
"type": "uint256"
}
],
"name": "processFees",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "collector",
"type": "address"
}
],
"name": "removeFeeCollector",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "rescueETH",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "token",
"type": "address"
},
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "rescueTokens",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bool",
"name": "_autoProcess",
"type": "bool"
}
],
"name": "setAutoProcessFees",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
},
{
"internalType": "bool",
"name": "exempt",
"type": "bool"
}
],
"name": "setExemptFromAntiWhale",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "collector",
"type": "address"
},
{
"internalType": "uint256",
"name": "share",
"type": "uint256"
}
],
"name": "setFeeCollector",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"components": [
{
"internalType": "uint16",
"name": "buyFees",
"type": "uint16"
},
{
"internalType": "uint16",
"name": "sellFees",
"type": "uint16"
},
{
"internalType": "uint16",
"name": "transferFees",
"type": "uint16"
},
{
"internalType": "uint16",
"name": "burnFeeRatio",
"type": "uint16"
},
{
"internalType": "uint16",
"name": "liquidityFeeRatio",
"type": "uint16"
},
{
"internalType": "uint16",
"name": "collectorsFeeRatio",
"type": "uint16"
},
{
"internalType": "bool",
"name": "feesInToken",
"type": "bool"
}
],
"internalType": "struct Token.FeeConfiguration",
"name": "_feeConfiguration",
"type": "tuple"
}
],
"name": "setFeeConfiguration",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
},
{
"internalType": "bool",
"name": "excluded",
"type": "bool"
}
],
"name": "setIsExcludedFromFees",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "pairAddress",
"type": "address"
},
{
"internalType": "bool",
"name": "isLp",
"type": "bool"
}
],
"name": "setIsLpPool",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_liquidityOwner",
"type": "address"
}
],
"name": "setLiquidityOwner",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_maxHolding",
"type": "uint256"
}
],
"name": "setMaxWalletHolding",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_numTokensToSwap",
"type": "uint256"
}
],
"name": "setNumTokensToSwap",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_newRouter",
"type": "address"
}
],
"name": "setSwapRouter",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "symbol",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "totalFeeCollectorShares",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"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"
},
{
"inputs": [],
"name": "uniswapV2Pair",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "uniswapV2Router",
"outputs": [
{
"internalType": "contract IUniswapV2Router02",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"stateMutability": "payable",
"type": "receive"
}
]Source code
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
// Uniswap V2 interfaces for DEX router support
interface IUniswapV2Factory {
function createPair(address tokenA, address tokenB) external returns (address pair);
function getPair(address tokenA, address tokenB) external view returns (address pair);
}
interface IUniswapV2Router02 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);
}
/**
* @title Token
* @notice ERC20 token with customizable features
* @dev Generated by Tokenry.tools
*/
contract Token is ERC20,
Ownable {
/// @notice Custom decimals (immutable, set at deployment)
uint8 private immutable _decimals;
/// @notice Mapping for addresses exempt from anti-whale restrictions
mapping(address => bool) public isExemptFromAntiWhale;
/// @notice Events
event ExemptFromAntiWhaleUpdated(address indexed account, bool exempt);
event MaxWalletHoldingUpdated(uint256 maxHolding);
/// @notice Tax fee configuration
struct FeeConfiguration {
uint16 buyFees; // Buy fee (0-2000 = 0-20%)
uint16 sellFees; // Sell fee (0-2000 = 0-20%)
uint16 transferFees; // Transfer fee (0-2000 = 0-20%)
uint16 burnFeeRatio; // % of tax to burn (0-10000 = 0-100%)
uint16 liquidityFeeRatio; // % of tax for liquidity (0-10000 = 0-100%)
uint16 collectorsFeeRatio; // % of tax for fee collectors (0-10000 = 0-100%)
bool feesInToken; // If false, swap fees to native currency before distributing
}
FeeConfiguration public feeConfiguration;
/// @notice DEX router for LP pair creation and swaps
IUniswapV2Router02 public uniswapV2Router;
address public uniswapV2Pair;
address public liquidityOwner;
/// @notice Fee recipients and their shares
address[] public feeCollectors;
mapping(address => uint256) public feeCollectorShares;
uint256 public totalFeeCollectorShares;
/// @notice LP pool tracking
mapping(address => bool) public isLpPool;
/// @notice Addresses excluded from fees
mapping(address => bool) public isExcludedFromFees;
/// @notice Fee processing state
bool private _processingFees;
bool public autoProcessFees;
uint256 public numTokensToSwap;
/// @notice Constants
uint16 public constant MAX_FEE = 2000;
uint16 public constant FEE_PRECISION = 10000; // 100% in basis points
uint256 public constant MAX_SWAP_THRESHOLD_RATIO = 100;
/// @notice Events
event FeeConfigurationUpdated(
uint16 buyFees,
uint16 sellFees,
uint16 transferFees,
uint16 burnFeeRatio,
uint16 liquidityFeeRatio,
uint16 collectorsFeeRatio,
bool feesInToken
);
event LpPoolUpdated(address indexed pair, bool isLp);
event FeeCollectorUpdated(address indexed collector, uint256 share);
event FeeCollectorRemoved(address indexed collector);
event ExcludedFromFeesUpdated(address indexed account, bool excluded);
event LiquidityOwnerUpdated(address indexed oldOwner, address indexed newOwner);
event SwapRouterUpdated(address indexed oldRouter, address indexed newRouter, address indexed newPair);
event FeeDistributionFailed(address indexed collector, uint256 amount);
event FeesProcessed(uint256 tokensSwapped, uint256 ethReceived, uint256 liquidityTokens, uint256 liquidityETH);
event AutoProcessFeesUpdated(bool enabled);
event NumTokensToSwapUpdated(uint256 amount);
event TokensBurned(uint256 amount);
event ETHRescued(address indexed to, uint256 amount);
event TokensRescued(address indexed token, address indexed to, uint256 amount);
/// @notice Anti-whale configuration
uint256 public maxWalletHolding;
/**
* @param name Token name
* @param symbol Token symbol
* @param totalSupply Initial total supply
* @param owner Token owner address
* @param decimals_ Number of decimals (0-18)
* @param _maxWalletHolding Maximum tokens per wallet (0 to disable, must be >= 0.5% of supply if > 0)
* @param _uniswapV2Router DEX router address (Uniswap V2 compatible)
* @param _liquidityWallet Wallet to receive LP tokens
* @param _feeConfiguration Tax fee configuration
* @param _feeCollectors Array of fee collector addresses
* @param _feeCollectorShares Array of shares for each collector (must sum to 10000)
* @param _dexRouters Array of DEX router addresses to exempt from restrictions
*/
constructor(
string memory name,
string memory symbol,
uint256 totalSupply,
address owner,
uint8 decimals_
,
uint256 _maxWalletHolding
,
address _uniswapV2Router,
address _liquidityWallet,
FeeConfiguration memory _feeConfiguration,
address[] memory _feeCollectors,
uint256[] memory _feeCollectorShares,
address[] memory _dexRouters
) ERC20(name, symbol) Ownable(owner) {
require(decimals_ <= 18, "Token: decimals must be <= 18" ); _decimals=decimals_; _mint(owner, totalSupply); if (_maxWalletHolding > 0) { uint256 minLimit = (totalSupply * MIN_ANTI_WHALE_RATIO) / 100000; require(_maxWalletHolding >= minLimit, "Token: max holding too low (min 0.5% of supply)"); } maxWalletHolding=_maxWalletHolding; isExemptFromAntiWhale[owner]=true; isExemptFromAntiWhale[address(this)]=true; require(_uniswapV2Router !=address(0), "Token: invalid router" ); require(_liquidityWallet
!=address(0), "Token: invalid liquidity wallet" ); uniswapV2Router=IUniswapV2Router02(_uniswapV2Router);
liquidityOwner=_liquidityWallet; IUniswapV2Factory factory=IUniswapV2Factory(uniswapV2Router.factory()); address
weth=uniswapV2Router.WETH(); uniswapV2Pair=factory.getPair(address(this), weth); if (uniswapV2Pair==address(0)) {
uniswapV2Pair=factory.createPair(address(this), weth); } require(uniswapV2Pair
!=address(0), "Token: pair creation failed" ); isLpPool[uniswapV2Pair]=true; require(_feeConfiguration.buyFees
<=MAX_FEE, "Token: buy fee exceeds max" ); require(_feeConfiguration.sellFees
<=MAX_FEE, "Token: sell fee exceeds max" ); require(_feeConfiguration.transferFees
<=MAX_FEE, "Token: transfer fee exceeds max" ); require( _feeConfiguration.burnFeeRatio +
_feeConfiguration.liquidityFeeRatio +
_feeConfiguration.collectorsFeeRatio==FEE_PRECISION, "Token: fee ratios must sum to 100%" );
feeConfiguration=_feeConfiguration;
require(_feeCollectors.length==_feeCollectorShares.length, "Token: arrays length mismatch" );
require(_feeCollectors.length <=10, "Token: too many collectors" ); uint256 totalShares=0; for (uint256 i=0; i <
_feeCollectors.length; i++) { require(_feeCollectors[i] !=address(0), "Token: invalid collector" );
require(_feeCollectorShares[i]> 0, "Token: invalid share");
feeCollectors.push(_feeCollectors[i]);
feeCollectorShares[_feeCollectors[i]] = _feeCollectorShares[i];
totalShares += _feeCollectorShares[i];
}
require(totalShares == FEE_PRECISION, "Token: shares must sum to 100%");
totalFeeCollectorShares = totalShares;
isExcludedFromFees[address(0)] = true;
isExcludedFromFees[address(this)] = true;
isExcludedFromFees[owner] = true;
for (uint256 i = 0; i < _dexRouters.length; i++) {
isExemptFromAntiWhale[_dexRouters[i]]=true; isExcludedFromFees[_dexRouters[i]]=true; }
isExcludedFromFees[address(uniswapV2Router)]=true; autoProcessFees=true; numTokensToSwap=totalSupply / 2000;
} /** * @notice Set exempt addresses from anti-whale restrictions (owner
only) */ function setExemptFromAntiWhale(address account, bool exempt) external onlyOwner {
isExemptFromAntiWhale[account]=exempt; emit ExemptFromAntiWhaleUpdated(account, exempt); } /** * @notice
Returns the number of decimals used for token amounts * @return The number of decimals (0-18) */ function
decimals() public view virtual override returns (uint8) { return _decimals; } receive() external payable {} /** * @notice Set fee configuration (owner
only) */ function setFeeConfiguration(FeeConfiguration calldata _feeConfiguration) external onlyOwner {
require(_feeConfiguration.buyFees <=MAX_FEE, "Token: buy fee exceeds max" ); require(_feeConfiguration.sellFees
<=MAX_FEE, "Token: sell fee exceeds max" ); require(_feeConfiguration.transferFees
<=MAX_FEE, "Token: transfer fee exceeds max" ); require( _feeConfiguration.burnFeeRatio +
_feeConfiguration.liquidityFeeRatio +
_feeConfiguration.collectorsFeeRatio==FEE_PRECISION, "Token: fee ratios must sum to 100%" );
feeConfiguration=_feeConfiguration; emit FeeConfigurationUpdated( _feeConfiguration.buyFees,
_feeConfiguration.sellFees, _feeConfiguration.transferFees, _feeConfiguration.burnFeeRatio,
_feeConfiguration.liquidityFeeRatio, _feeConfiguration.collectorsFeeRatio, _feeConfiguration.feesInToken ); }
/** * @notice Add or update fee collector (owner only) */ function setFeeCollector(address collector, uint256
share) external onlyOwner { require(collector !=address(0), "Token: invalid collector" ); require(share> 0,
"Token: invalid share");
require(feeCollectors.length < 10 || feeCollectorShares[collector]> 0, "Token: too many collectors");
if (feeCollectorShares[collector] == 0) {
feeCollectors.push(collector);
}
totalFeeCollectorShares = totalFeeCollectorShares - feeCollectorShares[collector] + share;
feeCollectorShares[collector] = share;
require(totalFeeCollectorShares <= FEE_PRECISION, "Token: total shares exceed 100%" ); emit
FeeCollectorUpdated(collector, share); } /** * @notice Remove fee collector (owner only) */ function
removeFeeCollector(address collector) external onlyOwner { require(feeCollectorShares[collector]> 0,
"Token: collector not found");
totalFeeCollectorShares -= feeCollectorShares[collector];
delete feeCollectorShares[collector];
for (uint256 i = 0; i < feeCollectors.length; i++) { if (feeCollectors[i]==collector) {
feeCollectors[i]=feeCollectors[feeCollectors.length - 1]; feeCollectors.pop(); break; } } emit
FeeCollectorRemoved(collector); } /** * @notice Set LP pool address (owner only) */ function
setIsLpPool(address pairAddress, bool isLp) external onlyOwner { isLpPool[pairAddress]=isLp; emit
LpPoolUpdated(pairAddress, isLp); } /** * @notice Set address excluded from fees (owner only) */
function setIsExcludedFromFees(address account, bool excluded) external onlyOwner {
isExcludedFromFees[account]=excluded; emit ExcludedFromFeesUpdated(account, excluded); } /** *
@notice Set auto-process fees (owner only) */ function setAutoProcessFees(bool _autoProcess)
external onlyOwner { autoProcessFees=_autoProcess; emit AutoProcessFeesUpdated(_autoProcess); } /**
* @notice Set number of tokens to swap threshold (owner only) * @param _numTokensToSwap Amount of
tokens to accumulate before processing fees */ function setNumTokensToSwap(uint256 _numTokensToSwap)
external onlyOwner { require(_numTokensToSwap <=totalSupply() /
MAX_SWAP_THRESHOLD_RATIO, "Token: threshold too high" ); numTokensToSwap=_numTokensToSwap; emit
NumTokensToSwapUpdated(_numTokensToSwap); } /** * @notice Set liquidity owner (owner only) */
function setLiquidityOwner(address _liquidityOwner) external onlyOwner { require(_liquidityOwner
!=address(0), "Token: invalid address" ); address oldOwner=liquidityOwner;
liquidityOwner=_liquidityOwner; emit LiquidityOwnerUpdated(oldOwner, _liquidityOwner); } /** *
@notice Set swap router (owner only) * @param _newRouter New DEX router address */ function
setSwapRouter(address _newRouter) external onlyOwner { require(_newRouter
!=address(0), "Token: invalid router" ); IUniswapV2Router02
newRouter=IUniswapV2Router02(_newRouter); IUniswapV2Factory
factory=IUniswapV2Factory(newRouter.factory()); require(address(factory)
!=address(0), "Token: invalid factory" ); address weth=newRouter.WETH(); address
newPair=factory.getPair(address(this), weth); if (newPair==address(0)) {
newPair=factory.createPair(address(this), weth); } require(newPair
!=address(0), "Token: pair creation failed" ); address oldRouter=address(uniswapV2Router);
uniswapV2Router=newRouter; uniswapV2Pair=newPair; isLpPool[newPair]=true;
isExcludedFromFees[address(newRouter)]=true; emit SwapRouterUpdated(oldRouter, _newRouter, newPair);
emit LpPoolUpdated(newPair, true); } /** * @notice Manually process fees (owner only) */ function
processFees(uint256 amount, uint256 minAmountOut) external onlyOwner { require(amount
<=balanceOf(address(this)), "Token: amount too high" ); _processFees(amount, minAmountOut); } /** *
@notice Rescue stuck ETH from contract (owner only) */ function rescueETH(address to, uint256
amount) external onlyOwner { require(to !=address(0), "Token: invalid address" ); (bool success,
)=payable(to).call{value: amount}(""); require(success, "Token: ETH transfer failed" ); emit
ETHRescued(to, amount); } /** * @notice Rescue stuck ERC20 tokens from contract (owner only) * @dev
Cannot rescue this token itself */ function rescueTokens(address token, address to, uint256 amount)
external onlyOwner { require(token !=address(this), "Token: cannot rescue own token" ); require(to
!=address(0), "Token: invalid address" ); IERC20(token).transfer(to, amount); emit
TokensRescued(token, to, amount); }
uint256 public constant MIN_ANTI_WHALE_RATIO=500;
function setMaxWalletHolding(uint256 _maxHolding) external onlyOwner { if (_maxHolding> 0) {
uint256 minLimit = (totalSupply() * MIN_ANTI_WHALE_RATIO) / 100000;
require(_maxHolding >= minLimit, "Token: max holding too low (min 0.5% of supply)");
}
maxWalletHolding = _maxHolding;
emit MaxWalletHoldingUpdated(_maxHolding);
}
/**
* @notice Override transfer to apply features
* @dev Applies anti-whale restrictions and fee calculations before executing transfer
*/
function _update(address from, address to, uint256 value) internal override {
require(value > 0, "Token: transfer amount must be greater than zero");
if (maxWalletHolding > 0 && to != address(0) && !isExemptFromAntiWhale[to]
&& !isLpPool[to]) {
require(balanceOf(to) + value <= maxWalletHolding, "Token: exceeds max wallet holding" ); }
uint256 taxFee=0; bool shouldProcessFees=!_processingFees &&
autoProcessFees; if (!_processingFees) { bool fromLP=isLpPool[from]; bool toLP=isLpPool[to];
bool fromExcluded=isExcludedFromFees[from]; bool toExcluded=isExcludedFromFees[to]; bool
fromRouter=(from==address(uniswapV2Router)); bool toRouter=(to==address(uniswapV2Router)); if
(fromLP && !toLP && !toExcluded && !toRouter) { taxFee=feeConfiguration.buyFees; } else if (toLP
&& !fromLP && !fromExcluded && !toExcluded) { taxFee=feeConfiguration.sellFees; } else if
(!fromLP && !toLP && !fromExcluded && !fromRouter && !toExcluded) {
taxFee=feeConfiguration.transferFees; } } if (shouldProcessFees && taxFee> 0 && isLpPool[to]) {
uint256 contractTokenBalance = balanceOf(address(this));
if (contractTokenBalance >= numTokensToSwap) {
_processFees(numTokensToSwap, 0);
}
}
if (taxFee > 0) {
uint256 taxAmount = (value * taxFee) / FEE_PRECISION;
uint256 sendAmount = value - taxAmount;
uint256 burnAmount = (taxAmount * feeConfiguration.burnFeeRatio) / FEE_PRECISION;
uint256 liquidityAmount = (taxAmount * feeConfiguration.liquidityFeeRatio) / FEE_PRECISION;
uint256 collectorsAmount = taxAmount - burnAmount - liquidityAmount;
if (burnAmount > 0) {
super._update(from, address(0), burnAmount);
emit TokensBurned(burnAmount);
}
if (liquidityAmount + collectorsAmount > 0) {
super._update(from, address(this), liquidityAmount + collectorsAmount);
}
value = sendAmount;
}
super._update(from, to, value);
}
/**
* @notice Internal function to process accumulated fees
* @dev Swaps tokens for ETH, adds liquidity, and distributes to collectors
*/
function _processFees(uint256 tokenAmount, uint256 minAmountOut) private {
if (_processingFees) return;
uint256 contractTokenBalance = balanceOf(address(this));
if (contractTokenBalance < tokenAmount) return; if (balanceOf(uniswapV2Pair)==0) return;
_processingFees=true; uint256 liquidityShare=feeConfiguration.liquidityFeeRatio; uint256
collectorShare=feeConfiguration.collectorsFeeRatio; uint256 totalShare=liquidityShare +
collectorShare; if (totalShare==0) { _processingFees=false; return; } uint256
liquidityAmount=(tokenAmount * liquidityShare) / totalShare; uint256
collectorsAmount=tokenAmount - liquidityAmount; uint256 halfLiquidity=liquidityAmount / 2;
uint256 otherHalfLiquidity=liquidityAmount - halfLiquidity; uint256
tokensToSwap=halfLiquidity; if (!feeConfiguration.feesInToken) { tokensToSwap
+=collectorsAmount; }
_processingFees=false; if (tokensToSwap> 0) {
uint256 initialBalance = address(this).balance;
_swapTokensForEth(tokensToSwap, minAmountOut);
uint256 swapBalance = address(this).balance - initialBalance;
uint256 liquidityETH = (swapBalance * halfLiquidity) / tokensToSwap;
if (liquidityETH > 0 && otherHalfLiquidity > 0) {
_addLiquidity(otherHalfLiquidity, liquidityETH);
}
if (!feeConfiguration.feesInToken) {
uint256 collectorsETH = address(this).balance;
_distributeFees(collectorsETH, false);
}
emit FeesProcessed(tokensToSwap, swapBalance, otherHalfLiquidity, liquidityETH);
}
if (feeConfiguration.feesInToken && collectorsAmount > 0) {
_distributeFees(collectorsAmount, true);
}
}
/**
* @notice Swap tokens for ETH
* @param tokenAmount Amount of tokens to swap
* @param minAmountOut Minimum amount of ETH to receive
*/
function _swapTokensForEth(uint256 tokenAmount, uint256 minAmountOut) private {
address[] memory path = new address[](2);
path[0] = address(this);
path[1] = uniswapV2Router.WETH();
_approve(address(this), address(uniswapV2Router), tokenAmount);
uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
tokenAmount,
minAmountOut,
path,
address(this),
block.timestamp
);
}
/**
* @notice Add liquidity to DEX
* @param tokenAmount Amount of tokens to add
* @param ethAmount Amount of ETH to add
*/
function _addLiquidity(uint256 tokenAmount, uint256 ethAmount) private {
_approve(address(this), address(uniswapV2Router), tokenAmount);
uniswapV2Router.addLiquidityETH{value: ethAmount}(
address(this),
tokenAmount,
0,
0,
liquidityOwner,
block.timestamp
);
}
/**
* @notice Distribute fees to collectors
* @param amount Total amount to distribute
* @param inToken If true, distribute tokens; if false, distribute ETH
*/
function _distributeFees(uint256 amount, bool inToken) private {
if (amount == 0 || totalFeeCollectorShares == 0) return;
uint256 distributed = 0;
uint256 len = feeCollectors.length;
for (uint256 i = 0; i < len; i++) { address collector=feeCollectors[i]; uint256 share=i==len
- 1 ? amount - distributed : (amount * feeCollectorShares[collector]) /
totalFeeCollectorShares; if (inToken) { super._update(address(this), collector, share);
} else { (bool success, )=payable(collector).call{value: share, gas: 30000}(""); if
(!success) { emit FeeDistributionFailed(collector, share); } } distributed +=share; } }
}Chain explorer3274msChain node92ms