bns-contract
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title ENS Mobile Mapper with Relayer-Paid Transactions
/// @notice This contract allows users to register their mobile number and link it to an ENS subdomain, with gas fees paid by a relayer.
interface ENSRegistry {
function setSubnodeOwner(bytes32 node, bytes32 label, address owner) external returns (bytes32);
function setResolver(bytes32 node, address resolver) external;
}
interface ENSResolver {
function setAddr(bytes32 node, address addr) external;
function setName(bytes32 node, string calldata name) external;
}
contract ENSMobileMapperNoSig {
ENSRegistry public ensRegistry;
ENSResolver public ensResolver;
bytes32 public rootNode; // e.g., the node for 'example.eth'
address public relayer; // Address of the relayer that pays for gas
// Structure to hold user information
struct UserInfo {
string ensBaseName;
address walletAddress;
bool isRegistered;
}
// Mapping from mobile number to UserInfo
mapping(string => UserInfo) public mobileToUser;
// Mapping from ENS base name to mobile number to prevent duplicate ENS names
mapping(string => string) public ensToMobile;
// Events
event MobileRegistered(string mobileNumber, string ensBaseName, address walletAddress);
event MobileUpdated(string mobileNumber, string ensBaseName, address walletAddress);
// Constructor to initialize the contract
constructor(address _ensRegistry, address _ensResolver, bytes32 _rootNode, address _relayer) {
ensRegistry = ENSRegistry(_ensRegistry);
ensResolver = ENSResolver(_ensResolver);
rootNode = _rootNode;
relayer = _relayer;
}
/// @notice Registers a mobile number with an ENS base name and links it to the wallet.
/// @param mobileNumber The user's mobile number as a string.
/// @param ensBaseName The desired ENS subdomain (e.g., "john.doe").
/// @param userAddress The wallet address of the user.
function registerMobile(
string memory mobileNumber,
string memory ensBaseName,
address userAddress
) external {
require(msg.sender == relayer, "Only the relayer can call this function");
// Ensure the mobile number isn't already registered and ENS name isn't taken
require(!mobileToUser[mobileNumber].isRegistered, "Mobile number already registered");
require(bytes(ensBaseName).length > 0, "ENS base name cannot be empty");
require(bytes(ensToMobile[ensBaseName]).length == 0, "ENS base name already taken");
// Generate the label for the subdomain
bytes32 label = keccak256(abi.encodePacked(ensBaseName));
bytes32 subnode = keccak256(abi.encodePacked(rootNode, label));
// Create the subdomain and assign ownership to the user
ensRegistry.setSubnodeOwner(rootNode, label, userAddress);
// Set the resolver for the subdomain
ensRegistry.setResolver(subnode, address(ensResolver));
// Link the ENS name to the user's wallet address
ensResolver.setAddr(subnode, userAddress);
// Store the mapping
mobileToUser[mobileNumber] = UserInfo({
ensBaseName: ensBaseName,
walletAddress: userAddress,
isRegistered: true
});
ensToMobile[ensBaseName] = mobileNumber;
emit MobileRegistered(mobileNumber, ensBaseName, userAddress);
}
/// @notice Updates the relayer address.
/// @param newRelayer The new address of the relayer.
function updateRelayer(address newRelayer) external {
require(msg.sender == relayer, "Only the relayer can update the address");
relayer = newRelayer;
}
}
Last updated