// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
/// @title Fomo4DPlayerBook
/// @notice Referral identity layer: an address must pay to register a name before it can
/// earn referral fees. `Fomo4DGame` checks `isRegistered` at payout time, so a
/// referrer that registers later still starts earning on already-bound relations.
/// @notice One name per address, and each name can only be claimed once.
/// @notice The name is for off-chain resolution of referral links only; `buyKey` still takes
/// an address. Registration does not bind a referrer — `Fomo4DGame.referrerOf` is
/// the only source of truth for referral relationships.
/// @dev Ownerless: constant fee, immutable recipient, no pause, no upgrade.
contract Fomo4DPlayerBook {
/// @notice Minimum fee to register a name, in wei.
uint256 public constant REGISTRATION_FEE = 0.01 ether;
/// @notice Immutable recipient of all registration fees.
address public immutable teamAddress;
mapping(address => bytes32) public nameOf; // address => name (0 = not registered)
mapping(bytes32 => address) public addressOf; // name => address (0 = unclaimed)
/// @notice Fees collected and awaiting withdrawal. Pull-only: registration makes no external call.
uint256 public feeVault;
event NameRegistered(address indexed player, bytes32 indexed name, uint256 fee);
event FeesWithdrawn(uint256 amount);
error FeeTooLow();
error AlreadyRegistered();
error NameTaken();
error InvalidName();
constructor(address _team) {
require(_team != address(0), "zero team");
teamAddress = _team;
}
/// @notice Pay to register a name, which qualifies the caller to act as a referrer.
/// @param nameStr Name to claim: 1–32 bytes, lowercase a-z, 0-9 and underscore only.
/// @return name The name packed into bytes32.
/// @dev Reverts `FeeTooLow` below `REGISTRATION_FEE`, `AlreadyRegistered` if the caller
/// already has a name, `NameTaken` if the name is claimed, `InvalidName` on a bad name.
/// Any overpayment is kept, not refunded.
function registerName(string calldata nameStr) external payable returns (bytes32 name) {
if (msg.value < REGISTRATION_FEE) revert FeeTooLow();
if (nameOf[msg.sender] != bytes32(0)) revert AlreadyRegistered();
name = _validateAndPack(nameStr);
if (addressOf[name] != address(0)) revert NameTaken();
nameOf[msg.sender] = name;
addressOf[name] = msg.sender;
feeVault += msg.value;
emit NameRegistered(msg.sender, name, msg.value);
}
/// @notice Send the accumulated registration fees to `teamAddress`. Callable by anyone;
/// the destination is immutable and there is no discretion over the amount.
/// @dev Never reverts: a zero balance or a failed transfer is a no-op that leaves the
/// balance in the contract for a later retry, so registration is never blocked.
function withdrawFees() external {
uint256 amount = feeVault;
if (amount == 0) return;
feeVault = 0;
(bool ok,) = teamAddress.call{value: amount}("");
if (!ok) {
feeVault = amount; // restore for retry
return;
}
emit FeesWithdrawn(amount);
}
/// @notice Whether `who` may be paid referral fees. Called by the game at payout time.
/// @param who Address to check.
/// @return True if the address has registered a name.
function isRegistered(address who) external view returns (bool) {
return nameOf[who] != bytes32(0);
}
/// @dev Validate a name and pack it into bytes32. Lowercase a-z / 0-9 / underscore, length 1–32.
function _validateAndPack(string calldata s) internal pure returns (bytes32 packed) {
bytes memory b = bytes(s);
uint256 len = b.length;
if (len == 0 || len > 32) revert InvalidName();
for (uint256 i = 0; i < len; i++) {
uint8 c = uint8(b[i]);
bool okChar = (c >= 0x61 && c <= 0x7A) // a-z
|| (c >= 0x30 && c <= 0x39) // 0-9
|| c == 0x5F; // _
if (!okChar) revert InvalidName();
}
assembly ("memory-safe") {
packed := mload(add(b, 32))
}
}
}[
{
"type": "constructor",
"inputs": [
{
"name": "_team",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "nonpayable"
},
{
"name": "AlreadyRegistered",
"type": "error",
"inputs": []
},
{
"name": "FeeTooLow",
"type": "error",
"inputs": []
},
{
"name": "InvalidName",
"type": "error",
"inputs": []
},
{
"name": "NameTaken",
"type": "error",
"inputs": []
},
{
"name": "FeesWithdrawn",
"type": "event",
"inputs": [
{
"name": "amount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "NameRegistered",
"type": "event",
"inputs": [
{
"name": "player",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "name",
"type": "bytes32",
"indexed": true,
"internalType": "bytes32"
},
{
"name": "fee",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "REGISTRATION_FEE",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "addressOf",
"type": "function",
"inputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "feeVault",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "isRegistered",
"type": "function",
"inputs": [
{
"name": "who",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"name": "nameOf",
"type": "function",
"inputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "view"
},
{
"name": "registerName",
"type": "function",
"inputs": [
{
"name": "nameStr",
"type": "string",
"internalType": "string"
}
],
"outputs": [
{
"name": "name",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "payable"
},
{
"name": "teamAddress",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "withdrawFees",
"type": "function",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
}
]0x60a0604052348015600e575f80fd5b506040516106a93803806106a9833981016040819052602b916080565b6001600160a01b03811660705760405162461bcd60e51b81526020600482015260096024820152687a65726f207465616d60b81b604482015260640160405180910390fd5b6001600160a01b031660805260ab565b5f60208284031215608f575f80fd5b81516001600160a01b038116811460a4575f80fd5b9392505050565b6080516105e06100c95f395f818160b4015261031301526105e05ff3fe608060405260043610610079575f3560e01c806364b4f7511161004c57806364b4f75114610119578063bb34534c14610133578063c3c5a54714610167578063f5c57382146101ad575f80fd5b80630830602b1461007d5780631c75f085146100a3578063476343ee146100ee578063478222c214610104575b5f80fd5b61009061008b3660046104bf565b6101d8565b6040519081526020015b60405180910390f35b3480156100ae575f80fd5b506100d67f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161009a565b3480156100f9575f80fd5b506101026102f2565b005b34801561010f575f80fd5b5061009060025481565b348015610124575f80fd5b50610090662386f26fc1000081565b34801561013e575f80fd5b506100d661014d36600461052d565b60016020525f90815260409020546001600160a01b031681565b348015610172575f80fd5b5061019d610181366004610544565b6001600160a01b03165f90815260208190526040902054151590565b604051901515815260200161009a565b3480156101b8575f80fd5b506100906101c7366004610544565b5f6020819052908152604090205481565b5f662386f26fc100003410156102015760405163732f941360e01b815260040160405180910390fd5b335f908152602081905260409020541561022e57604051630ea075bf60e21b815260040160405180910390fd5b61023883836103b7565b5f818152600160205260409020549091506001600160a01b03161561027057604051639e4b268560e01b815260040160405180910390fd5b335f818152602081815260408083208590558483526001909152812080546001600160a01b031916909217909155600280543492906102b0908490610571565b9091555050604051348152819033907fe6a5d01fa9329c4d517e4311306e601e121d5cf6f4b214a4986bdd8714002e329060200160405180910390a392915050565b6002545f8190036103005750565b5f60028190556040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169083908381818185875af1925050503d805f811461036c576040519150601f19603f3d011682016040523d82523d5f602084013e610371565b606091505b50509050806103805750600255565b6040518281527f9800e6f57aeb4360eaa72295a820a4293e1e66fbfcabcd8874ae141304a76deb9060200160405180910390a15050565b5f8083838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505082519293505081159050806104015750602081115b1561041f5760405163430f13b360e01b815260040160405180910390fd5b5f5b818110156104b2575f83828151811061043c5761043c610596565b016020015160f81c90505f6061821080159061045c5750607a8260ff1611155b8061047a575060308260ff161015801561047a575060398260ff1611155b8061048857508160ff16605f145b9050806104a85760405163430f13b360e01b815260040160405180910390fd5b5050600101610421565b5050602001519392505050565b5f80602083850312156104d0575f80fd5b823567ffffffffffffffff8111156104e6575f80fd5b8301601f810185136104f6575f80fd5b803567ffffffffffffffff81111561050c575f80fd5b85602082840101111561051d575f80fd5b6020919091019590945092505050565b5f6020828403121561053d575f80fd5b5035919050565b5f60208284031215610554575f80fd5b81356001600160a01b038116811461056a575f80fd5b9392505050565b8082018082111561059057634e487b7160e01b5f52601160045260245ffd5b92915050565b634e487b7160e01b5f52603260045260245ffdfea26469706673582212206e2402fe5849997d2e21ec7dd48c0bdeff3c5320f0184abc4885fb698ec571a164736f6c634300081a00330000000000000000000000004b3ad373d4776f7ef310851409147cc03d8c1d4e
0x608060405260043610610079575f3560e01c806364b4f7511161004c57806364b4f75114610119578063bb34534c14610133578063c3c5a54714610167578063f5c57382146101ad575f80fd5b80630830602b1461007d5780631c75f085146100a3578063476343ee146100ee578063478222c214610104575b5f80fd5b61009061008b3660046104bf565b6101d8565b6040519081526020015b60405180910390f35b3480156100ae575f80fd5b506100d67f0000000000000000000000004b3ad373d4776f7ef310851409147cc03d8c1d4e81565b6040516001600160a01b03909116815260200161009a565b3480156100f9575f80fd5b506101026102f2565b005b34801561010f575f80fd5b5061009060025481565b348015610124575f80fd5b50610090662386f26fc1000081565b34801561013e575f80fd5b506100d661014d36600461052d565b60016020525f90815260409020546001600160a01b031681565b348015610172575f80fd5b5061019d610181366004610544565b6001600160a01b03165f90815260208190526040902054151590565b604051901515815260200161009a565b3480156101b8575f80fd5b506100906101c7366004610544565b5f6020819052908152604090205481565b5f662386f26fc100003410156102015760405163732f941360e01b815260040160405180910390fd5b335f908152602081905260409020541561022e57604051630ea075bf60e21b815260040160405180910390fd5b61023883836103b7565b5f818152600160205260409020549091506001600160a01b03161561027057604051639e4b268560e01b815260040160405180910390fd5b335f818152602081815260408083208590558483526001909152812080546001600160a01b031916909217909155600280543492906102b0908490610571565b9091555050604051348152819033907fe6a5d01fa9329c4d517e4311306e601e121d5cf6f4b214a4986bdd8714002e329060200160405180910390a392915050565b6002545f8190036103005750565b5f60028190556040516001600160a01b037f0000000000000000000000004b3ad373d4776f7ef310851409147cc03d8c1d4e169083908381818185875af1925050503d805f811461036c576040519150601f19603f3d011682016040523d82523d5f602084013e610371565b606091505b50509050806103805750600255565b6040518281527f9800e6f57aeb4360eaa72295a820a4293e1e66fbfcabcd8874ae141304a76deb9060200160405180910390a15050565b5f8083838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505082519293505081159050806104015750602081115b1561041f5760405163430f13b360e01b815260040160405180910390fd5b5f5b818110156104b2575f83828151811061043c5761043c610596565b016020015160f81c90505f6061821080159061045c5750607a8260ff1611155b8061047a575060308260ff161015801561047a575060398260ff1611155b8061048857508160ff16605f145b9050806104a85760405163430f13b360e01b815260040160405180910390fd5b5050600101610421565b5050602001519392505050565b5f80602083850312156104d0575f80fd5b823567ffffffffffffffff8111156104e6575f80fd5b8301601f810185136104f6575f80fd5b803567ffffffffffffffff81111561050c575f80fd5b85602082840101111561051d575f80fd5b6020919091019590945092505050565b5f6020828403121561053d575f80fd5b5035919050565b5f60208284031215610554575f80fd5b81356001600160a01b038116811461056a575f80fd5b9392505050565b8082018082111561059057634e487b7160e01b5f52601160045260245ffd5b92915050565b634e487b7160e01b5f52603260045260245ffdfea26469706673582212206e2402fe5849997d2e21ec7dd48c0bdeff3c5320f0184abc4885fb698ec571a164736f6c634300081a0033
| Token | Symbol | Balance | Price | Value |
|---|---|---|---|---|
| no token holdings | ||||
| Transaction Hash | Method | Block | Age | From | To | Amount | Token | ||
|---|---|---|---|---|---|---|---|---|---|
| no token transfers for this address yet | |||||||||
| Type | Age | Block | Details |
|---|---|---|---|
| no cross-chain L1↔L2 transactions for this address | |||
| Block | Age | Parent Transaction Hash | Type | Method | From | To | Value | |
|---|---|---|---|---|---|---|---|---|
| no internal transactions found for this address yet (traced blocks + on-demand) | ||||||||
| Transaction Hash | Method | Block | Age | From | To | Type | Item | ||
|---|---|---|---|---|---|---|---|---|---|
| no NFT transfers for this address yet | |||||||||
| Txn Hash | Age | Event | Topics / Data |
|---|---|---|---|
| 0x6100bb…ccf6c7 | 2 days agoSat, 15 Aug 2026 15:50:59 UTC | 0xe6a5d0…2e32 | [0] 0x000000000000…03882c47 [1] 0x636968706572…00000000 data: 0x000000000000000000…6fc10000 |
| 0x89ba9a…cdd051 | 4 days agoThu, 13 Aug 2026 16:36:12 UTC | 0xe6a5d0…2e32 | [0] 0x000000000000…0d81906e [1] 0x383834380000…00000000 data: 0x000000000000000000…6fc10000 |
| 0x5e0c22…aad752 | 4 days agoThu, 13 Aug 2026 15:27:41 UTC | 0xe6a5d0…2e32 | [0] 0x000000000000…934033a1 [1] 0x757000000000…00000000 data: 0x000000000000000000…6fc10000 |
| 0x3ba41f…737a97 | 4 days agoThu, 13 Aug 2026 15:26:37 UTC | 0xe6a5d0…2e32 | [0] 0x000000000000…1acb4d03 [1] 0x776167657200…00000000 data: 0x000000000000000000…6fc10000 |
| 0xb26211…6a15d0 | 4 days agoThu, 13 Aug 2026 15:17:05 UTC | 0xe6a5d0…2e32 | [0] 0x000000000000…b9fb9e73 [1] 0x726476000000…00000000 data: 0x000000000000000000…6fc10000 |
| 0x259fc4…5d9281 | 4 days agoThu, 13 Aug 2026 14:48:55 UTC | 0xe6a5d0…2e32 | [0] 0x000000000000…c05b19a6 [1] 0x666f6d6f3464…00000000 data: 0x000000000000000000…6fc10000 |
| Transaction Hash | Method ? | Block | Age | From | To | Amount | Txn Fee ? | ||
|---|---|---|---|---|---|---|---|---|---|
| 0x6100bb…ccf6c7 | registerName | 37,235,808 | 2 days agoSat, 15 Aug 2026 15:50:59 UTC | 0xe4e4…2c47 | IN | Fomo4DPlayerBook | $19.070.01 ETH | 0.00000227 | |
| 0x89ba9a…cdd051 | registerName | 35,538,685 | 4 days agoThu, 13 Aug 2026 16:36:12 UTC | 0xa2f5…906e | IN | Fomo4DPlayerBook | $19.070.01 ETH | 0.00000336 | |
| 0x5e0c22…aad752 | registerName | 35,497,730 | 4 days agoThu, 13 Aug 2026 15:27:41 UTC | 0xd2ab…33a1 | IN | Fomo4DPlayerBook | $19.070.01 ETH | 0.00000328 | |
| 0x3ba41f…737a97 | registerName | 35,497,094 | 4 days agoThu, 13 Aug 2026 15:26:37 UTC | 0x8883…4d03 | IN | Fomo4DPlayerBook | $19.070.01 ETH | 0.00000334 | |
| 0xb26211…6a15d0 | registerName | 35,491,380 | 4 days agoThu, 13 Aug 2026 15:17:05 UTC | 0xce59…9e73 | IN | Fomo4DPlayerBook | $19.070.01 ETH | 0.00000333 | |
| 0x259fc4…5d9281 | registerName | 35,474,534 | 4 days agoThu, 13 Aug 2026 14:48:55 UTC | 0xc87b…19a6 | IN | Fomo4DPlayerBook | $19.070.01 ETH | 0.00000415 |