// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
/// @notice ERC20 launched by the LaunchFactory. Enforces anti-snipe max-wallet /
/// max-tx limits until `restrictionsEndBlock`, after which it behaves as a plain ERC20.
contract LaunchToken is ERC20 {
error NotFactory();
error AlreadyInitialized();
error MaxWalletExceeded();
error MaxTxExceeded();
address public immutable factory;
/// @notice Set once by the factory in the launch transaction. Kept out of
/// the constructor so the CREATE2 init code is block-independent, letting
/// launchers mine vanity token addresses off-chain.
uint256 public restrictionsEndBlock;
uint256 public immutable maxWalletAmount; // 0 = no limit
uint256 public immutable maxTxAmount; // 0 = no limit
/// @notice Addresses exempt from restrictions (pool, locker, position manager, router, factory).
mapping(address => bool) public restrictionExempt;
constructor(
string memory name_,
string memory symbol_,
uint256 supply_,
uint16 maxWalletBps_,
uint16 maxTxBps_
) ERC20(name_, symbol_) {
factory = msg.sender;
maxWalletAmount = maxWalletBps_ >= 10_000 ? 0 : (supply_ * maxWalletBps_) / 10_000;
maxTxAmount = maxTxBps_ >= 10_000 ? 0 : (supply_ * maxTxBps_) / 10_000;
restrictionExempt[msg.sender] = true;
_mint(msg.sender, supply_);
}
/// @notice One-time wiring by the factory, same transaction as the deploy.
function initRestrictionsEndBlock(uint256 endBlock_) external {
if (msg.sender != factory) revert NotFactory();
if (restrictionsEndBlock != 0) revert AlreadyInitialized();
restrictionsEndBlock = endBlock_;
}
/// @notice Factory marks protocol addresses as exempt during launch (one-way).
function setRestrictionExempt(address account) external {
if (msg.sender != factory) revert NotFactory();
restrictionExempt[account] = true;
}
function restrictionsActive() public view returns (bool) {
return block.number < restrictionsEndBlock;
}
function _update(address from, address to, uint256 value) internal override {
if (from != address(0) && to != address(0) && restrictionsActive()) {
if (maxTxAmount != 0 && value > maxTxAmount && !restrictionExempt[from] && !restrictionExempt[to]) {
revert MaxTxExceeded();
}
if (maxWalletAmount != 0 && !restrictionExempt[to] && balanceOf(to) + value > maxWalletAmount) {
revert MaxWalletExceeded();
}
}
super._update(from, to, value);
}
}[
{
"type": "constructor",
"inputs": [
{
"name": "name_",
"type": "string",
"internalType": "string"
},
{
"name": "symbol_",
"type": "string",
"internalType": "string"
},
{
"name": "supply_",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "maxWalletBps_",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "maxTxBps_",
"type": "uint16",
"internalType": "uint16"
}
],
"stateMutability": "nonpayable"
},
{
"name": "AlreadyInitialized",
"type": "error",
"inputs": []
},
{
"name": "ERC20InsufficientAllowance",
"type": "error",
"inputs": [
{
"name": "spender",
"type": "address",
"internalType": "address"
},
{
"name": "allowance",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "needed",
"type": "uint256",
"internalType": "uint256"
}
]
},
{
"name": "ERC20InsufficientBalance",
"type": "error",
"inputs": [
{
"name": "sender",
"type": "address",
"internalType": "address"
},
{
"name": "balance",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "needed",
"type": "uint256",
"internalType": "uint256"
}
]
},
{
"name": "ERC20InvalidApprover",
"type": "error",
"inputs": [
{
"name": "approver",
"type": "address",
"internalType": "address"
}
]
},
{
"name": "ERC20InvalidReceiver",
"type": "error",
"inputs": [
{
"name": "receiver",
"type": "address",
"internalType": "address"
}
]
},
{
"name": "ERC20InvalidSender",
"type": "error",
"inputs": [
{
"name": "sender",
"type": "address",
"internalType": "address"
}
]
},
{
"name": "ERC20InvalidSpender",
"type": "error",
"inputs": [
{
"name": "spender",
"type": "address",
"internalType": "address"
}
]
},
{
"name": "MaxTxExceeded",
"type": "error",
"inputs": []
},
{
"name": "MaxWalletExceeded",
"type": "error",
"inputs": []
},
{
"name": "NotFactory",
"type": "error",
"inputs": []
},
{
"name": "Approval",
"type": "event",
"inputs": [
{
"name": "owner",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "spender",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "value",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "Transfer",
"type": "event",
"inputs": [
{
"name": "from",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "to",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "value",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "allowance",
"type": "function",
"inputs": [
{
"name": "owner",
"type": "address",
"internalType": "address"
},
{
"name": "spender",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "approve",
"type": "function",
"inputs": [
{
"name": "spender",
"type": "address",
"internalType": "address"
},
{
"name": "value",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "nonpayable"
},
{
"name": "balanceOf",
"type": "function",
"inputs": [
{
"name": "account",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "decimals",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint8",
"internalType": "uint8"
}
],
"stateMutability": "view"
},
{
"name": "factory",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "initRestrictionsEndBlock",
"type": "function",
"inputs": [
{
"name": "endBlock_",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "maxTxAmount",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "maxWalletAmount",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "name",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "string",
"internalType": "string"
}
],
"stateMutability": "view"
},
{
"name": "restrictionExempt",
"type": "function",
"inputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"name": "restrictionsActive",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"name": "restrictionsEndBlock",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "setRestrictionExempt",
"type": "function",
"inputs": [
{
"name": "account",
"type": "address",
"internalType": "address"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "symbol",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "string",
"internalType": "string"
}
],
"stateMutability": "view"
},
{
"name": "totalSupply",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "transfer",
"type": "function",
"inputs": [
{
"name": "to",
"type": "address",
"internalType": "address"
},
{
"name": "value",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "nonpayable"
},
{
"name": "transferFrom",
"type": "function",
"inputs": [
{
"name": "from",
"type": "address",
"internalType": "address"
},
{
"name": "to",
"type": "address",
"internalType": "address"
},
{
"name": "value",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "nonpayable"
}
]0x60806040526004361015610011575f80fd5b5f3560e01c806302215713146106c257806306fdde03146105f0578063095ea7b31461056e57806318160ddd14610551578063225a1021146104d657806323b872dd146103f75780632f982c67146103da578063313ce567146103bf57806370a082311461038857806374c6fdec146103695780638c0b5e221461032f57806394a8cbd4146102f257806395d89b41146101d7578063a9059cbb146101a6578063aa4bde281461016c578063c45a0155146101285763dd62ed3e146100d4575f80fd5b34610124576040366003190112610124576100ed61074a565b6100f5610760565b6001600160a01b039182165f908152600160209081526040808320949093168252928352819020549051908152f35b5f80fd5b34610124575f366003190112610124576040517f0000000000000000000000008f63bde659eb6f71c3bda68cff6a7fe84e7e68346001600160a01b03168152602090f35b34610124575f3660031901126101245760206040517f000000000000000000000000000000000000000000108b2a2c280290940000008152f35b34610124576040366003190112610124576101cc6101c261074a565b6024359033610776565b602060405160018152f35b34610124575f366003190112610124576040515f6004548060011c906001811680156102e8575b6020831081146102d4578285529081156102b85750600114610263575b50819003601f01601f191681019067ffffffffffffffff82118183101761024f5761024b82918260405282610720565b0390f35b634e487b7160e01b5f52604160045260245ffd5b905060045f527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5f905b8282106102a25750602091508201018261021b565b600181602092548385880101520191019061028d565b90506020925060ff191682840152151560051b8201018261021b565b634e487b7160e01b5f52602260045260245ffd5b91607f16916101fe565b34610124576020366003190112610124576001600160a01b0361031361074a565b165f526006602052602060ff60405f2054166040519015158152f35b34610124575f3660031901126101245760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610124575f3660031901126101245760206005544310604051908152f35b34610124576020366003190112610124576001600160a01b036103a961074a565b165f525f602052602060405f2054604051908152f35b34610124575f36600319011261012457602060405160128152f35b34610124575f366003190112610124576020600554604051908152f35b346101245760603660031901126101245761041061074a565b610418610760565b6001600160a01b0382165f818152600160209081526040808320338452909152902054909260443592915f198110610456575b506101cc9350610776565b8381106104bb5784156104a8573315610495576101cc945f52600160205260405f2060018060a01b0333165f526020528360405f20910390558461044b565b634a1406b160e11b5f525f60045260245ffd5b63e602df0560e01b5f525f60045260245ffd5b8390637dc7a0d960e11b5f523360045260245260445260645ffd5b34610124576020366003190112610124576104ef61074a565b7f0000000000000000000000008f63bde659eb6f71c3bda68cff6a7fe84e7e68346001600160a01b03163303610542576001600160a01b03165f908152600660205260409020805460ff19166001179055005b631966391b60e11b5f5260045ffd5b34610124575f366003190112610124576020600254604051908152f35b346101245760403660031901126101245761058761074a565b6024359033156104a8576001600160a01b031690811561049557335f52600160205260405f20825f526020528060405f20556040519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a3602060405160018152f35b34610124575f366003190112610124576040515f6003548060011c906001811680156106b8575b6020831081146102d4578285529081156102b857506001146106635750819003601f01601f191681019067ffffffffffffffff82118183101761024f5761024b82918260405282610720565b905060035f527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5f905b8282106106a25750602091508201018261021b565b600181602092548385880101520191019061068d565b91607f1691610617565b34610124576020366003190112610124577f0000000000000000000000008f63bde659eb6f71c3bda68cff6a7fe84e7e68346001600160a01b031633036105425760055461071257600435600555005b62dc149f60e41b5f5260045ffd5b602060409281835280519182918282860152018484015e5f828201840152601f01601f1916010190565b600435906001600160a01b038216820361012457565b602435906001600160a01b038216820361012457565b6001600160a01b031690811561093f576001600160a01b031691821561092c576005544310610817575b815f525f60205260405f20548181106107fe57817fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92602092855f525f84520360405f2055845f525f825260405f20818154019055604051908152a3565b8263391434e360e21b5f5260045260245260445260645ffd5b7f00000000000000000000000000000000000000000000000000000000000000008015159081610922575b508061090b575b806108f4575b6108e5577f000000000000000000000000000000000000000000108b2a2c2802909400000080151590816108cc575b81610899575b50156107a057632ce93b5960e01b5f5260045ffd5b9050835f525f60205260405f20548281018091116108b857115f610884565b634e487b7160e01b5f52601160045260245ffd5b9050835f52600660205260ff60405f205416159061087e565b63136c002360e21b5f5260045ffd5b50825f52600660205260ff60405f2054161561084f565b50815f52600660205260ff60405f20541615610849565b905081115f610842565b63ec442f0560e01b5f525f60045260245ffd5b634b637e8f60e11b5f525f60045260245ffdfea26469706673582212207896ba2769e772f8d8b767d5f614ad83b069149b3d43cc5633195ee58ecf24e364736f6c634300081a0033
| Token | Symbol | Balance | Price | Value |
|---|---|---|---|---|
| DIH | 1 | $0.0000102 | $0 |
| Transaction Hash | Method | Block | Age | From | To | Type | Item | ||
|---|---|---|---|---|---|---|---|---|---|
| no NFT transfers for this address yet | |||||||||
| Txn Hash | Age | Event | Topics / Data |
|---|---|---|---|
| 0x21ec2b…1be92a | 32 days agoThu, 16 Jul 2026 08:59:07 UTC | Transfer | [0] 0x000000000000…0dbf80c9 [1] 0x000000000000…fdfc8f17 data: 0x000000000000000000…839eec2a |
| 0x9f4b06…f42959 | 32 days agoThu, 16 Jul 2026 08:59:06 UTC | Approval | [0] 0x000000000000…0dbf80c9 [1] 0x000000000000…959e5cb2 data: 0xffffffffffffffffff…ffffffff |
| 0x6e18b7…12df4b | 32 days agoThu, 16 Jul 2026 08:58:14 UTC | Transfer | [0] 0x000000000000…76bc15df [1] 0x000000000000…fdfc8f17 data: 0x000000000000000000…8a045a24 |
| 0x7f6c4e…7fad7e | 32 days agoThu, 16 Jul 2026 08:58:14 UTC | Approval | [0] 0x000000000000…76bc15df [1] 0x000000000000…262c40dc data: 0xffffffffffffffffff…ffffffff |
| 0x61d8aa…2b8041 | 32 days agoThu, 16 Jul 2026 05:12:28 UTC | Transfer | [0] 0x000000000000…fdfc8f17 [1] 0x000000000000…0dbf80c9 data: 0x000000000000000000…839eec2a |
| 0xdc733b…ef2529 | 32 days agoThu, 16 Jul 2026 05:11:10 UTC | Transfer | [0] 0x000000000000…fdfc8f17 [1] 0x000000000000…76bc15df data: 0x000000000000000000…8a045a24 |
| 0xe5f9b4…4dcb30 | 32 days agoThu, 16 Jul 2026 04:28:41 UTC | Transfer | [0] 0x000000000000…d4124fcd [1] 0x000000000000…fdfc8f17 data: 0x000000000000000000…94000000 |
| 0xe5f9b4…4dcb30 | 32 days agoThu, 16 Jul 2026 04:28:41 UTC | Approval | [0] 0x000000000000…d4124fcd [1] 0x000000000000…959e5cb2 data: 0x000000000000000000…94000000 |
| 0x43c40f…02474d | 32 days agoThu, 16 Jul 2026 04:24:41 UTC | Transfer | [0] 0x000000000000…fdfc8f17 [1] 0x000000000000…d4124fcd data: 0x000000000000000000…94000000 |
| 0x46cc30…abc60b | 32 days agoThu, 16 Jul 2026 04:24:40 UTC | Transfer | [0] 0x000000000000…fdfc8f17 [1] 0x000000000000…99772592 data: 0x000000000000000000…eaff2d6d |
| 0x46cc30…abc60b | 32 days agoThu, 16 Jul 2026 04:24:40 UTC | Transfer | [0] 0x000000000000…4e7e6834 [1] 0x000000000000…0000dead data: 0x000000000000000000…00002fe8 |
| 0x46cc30…abc60b | 32 days agoThu, 16 Jul 2026 04:24:40 UTC | Transfer | [0] 0x000000000000…4e7e6834 [1] 0x000000000000…fdfc8f17 data: 0x000000000000000000…e7ffd018 |
| 0x46cc30…abc60b | 32 days agoThu, 16 Jul 2026 04:24:40 UTC | Approval | [0] 0x000000000000…4e7e6834 [1] 0x000000000000…638de0d3 data: 0x000000000000000000…e8000000 |
| 0x46cc30…abc60b | 32 days agoThu, 16 Jul 2026 04:24:40 UTC | Transfer | [0] 0x000000000000…00000000 [1] 0x000000000000…4e7e6834 data: 0x000000000000000000…e8000000 |
| Type | Age | Block | Details |
|---|---|---|---|
| no cross-chain L1↔L2 transactions for this address | |||
| Transaction Hash | Method | Block | Age | From | To | Amount | Token | ||
|---|---|---|---|---|---|---|---|---|---|
| 0xb91c914d…6b0da2 | Transfer | 18,585,375 | 23 days agoSat, 25 Jul 2026 00:37:36 UTC | 0xcaf7…5d11 | IN | 0x167d…600d | $0.001 DIH |
| Block | Age | Parent Transaction Hash | Type | Method | From | To | Value | |
|---|---|---|---|---|---|---|---|---|
| 10,967,335 | 32 days agoThu, 16 Jul 2026 04:24:40 UTC | 0x46cc30…abc60b | CREATE2 | launchToken | 0x8f63…6834 | IN | 0x167d…600d | 0 ETH |
| Transaction Hash | Method ? | Block | Age | From | To | Amount | Txn Fee ? | ||
|---|---|---|---|---|---|---|---|---|---|
| 0x9f4b06…f42959 | Approve | 11,131,611 | 32 days agoThu, 16 Jul 2026 08:59:06 UTC | 0x7f19…80c9 | IN | DOG | $0.000 ETH | 0.00000291 | |
| 0x7f6c4e…7fad7e | Approve | 11,131,095 | 32 days agoThu, 16 Jul 2026 08:58:14 UTC | 0xe070…15df | IN | DOG | $0.000 ETH | 0.00000291 |