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