// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)pragmasolidity ^0.8.20;/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/abstractcontractContext{
function_msgSender() internalviewvirtualreturns (address) {
returnmsg.sender;
}
function_msgData() internalviewvirtualreturns (bytescalldata) {
returnmsg.data;
}
function_contextSuffixLength() internalviewvirtualreturns (uint256) {
return0;
}
}
Contract Source Code
File 2 of 3: Ownable.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)pragmasolidity ^0.8.20;import {Context} from"../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/abstractcontractOwnableisContext{
addressprivate _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/errorOwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/errorOwnableInvalidOwner(address owner);
eventOwnershipTransferred(addressindexed previousOwner, addressindexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/constructor(address initialOwner) {
if (initialOwner ==address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/modifieronlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/functionowner() publicviewvirtualreturns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/function_checkOwner() internalviewvirtual{
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/functionrenounceOwnership() publicvirtualonlyOwner{
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/functiontransferOwnership(address newOwner) publicvirtualonlyOwner{
if (newOwner ==address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/function_transferOwnership(address newOwner) internalvirtual{
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
Contract Source Code
File 3 of 3: TokiemonUserRegistry.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.24;import"@openzeppelin/contracts/access/Ownable.sol";
/// @title TokiemonUserRegistry/// @notice Human readable username registry for users on leaderboard and referral system/// @dev This contract manages the mapping between Ethereum addresses and usernames for our gamecontractTokiemonUserRegistryisOwnable{
mapping(address=>string) private addressToUsername;
mapping(string=>address) private usernameToAddress;
uint8publicconstant MAX_USERNAME_LENGTH =14;
eventUsernameSet(addressindexed user, string username);
constructor() Ownable(msg.sender) {}
/// @notice Get the username associated with a given address/// @param _user The address to look up/// @return The username associated with the given addressfunctiongetUsername(address _user) publicviewreturns (stringmemory) {
return addressToUsername[_user];
}
/// @notice Get the address associated with a given username/// @param _username The username to look up/// @return The address associated with the given usernamefunctiongetAddress(stringmemory _username) publicviewreturns (address) {
return usernameToAddress[_username];
}
/// @notice Set or update the username for the caller's address/// @param _username The new username to set/// @dev Emits UsernameSet eventfunctionsetUsername(stringmemory _username) public{
require(bytes(_username).length>0, "Username cannot be empty");
require(bytes(_username).length<= MAX_USERNAME_LENGTH, "Username too long");
require(usernameToAddress[_username] ==address(0), "Username already taken");
require(isValidUsername(_username), "Username must be lowercase letters and numbers only");
stringmemory oldUsername = addressToUsername[msg.sender];
if (bytes(oldUsername).length>0) {
delete usernameToAddress[oldUsername];
}
addressToUsername[msg.sender] = _username;
usernameToAddress[_username] =msg.sender;
emit UsernameSet(msg.sender, _username);
}
/// @notice Set or update the username for a specific user address by the owner/// @param _user The address of the user to set the username for/// @param _username The new username to set/// @dev Emits UsernameSet eventfunctionsetUsernameByOwner(address _user, stringmemory _username) publiconlyOwner{
require(bytes(_username).length>0, "Username cannot be empty");
require(usernameToAddress[_username] ==address(0), "Username already taken");
stringmemory oldUsername = addressToUsername[_user];
if (bytes(oldUsername).length>0) {
delete usernameToAddress[oldUsername];
}
addressToUsername[_user] = _username;
usernameToAddress[_username] = _user;
emit UsernameSet(_user, _username);
}
/// @notice Check if a username contains only lowercase letters and numbers/// @param _username The username to check/// @return True if the username is valid, false otherwisefunctionisValidUsername(stringmemory _username) internalpurereturns (bool) {
bytesmemory b =bytes(_username);
for (uint i; i < b.length; i++) {
bytes1 char = b[i];
if (!(char >=0x30&& char <=0x39) &&!(char >=0x61&& char <=0x7A)) {
returnfalse;
}
}
returntrue;
}
}