NNS Protocol

The protocol is a suite of smart contracts that issues names for different communities. It rewards communities, referrals, everyone in the ecosystem that resolves names directly on their product and holders of .⌐◨-◨ names. All rewards are issued in $NOGS.

Terminology

  • Each community has its own top-level domain called community level domain or CLD for short

  • 3rd parties natively resolving NNS names are referred to as the ecosystem

Smart contract architecture

The protocol is implemented with 5 key smart contracts:

  • CldRegistry: a registry of names (ERC721 tokens) for each community

  • NNSController: manages creation of CLDs, registration of new names and renewal of existing expiring names

  • NNSResolver: resolves account addresses to an NNS name

  • NNSRewarder: collects all revenues and splits them to different groups

  • NNSResolverToken: ERC721 tokens issued to the ecosystem

There are also CldFactory, AccountRewarder and ERC721BasedRewarder which are additional contracts and their use will be explained below.

CldRegistry

A CldRegistry is an ERC721 contract with a fixed CLD, eg .⌐◨-◨ or .nouns. The identifier of the CLD is its namehash. For instance, the cldId of the .⌐◨-◨ CLD is 0x739305fdceb24221237c3dea9f36a6fcc8dc81b45730358192886e1510532739.

Names are ERC721 tokens whose id is the namehash of name.extension, e.g. the token id of hello in the .⌐◨-◨ CLD is namehash("hello.⌐◨-◨") and the contract has many functionalities associated to each name:

  • nameOf returns the full name of the of the token, e.g. hello.⌐◨-◨

  • create, delete and query subdomains such as sub.hello.⌐◨-◨. Note that subdomains are not separate tokens but rather properties of each name.

  • set/delete text records

  • manage reverse name, i.e. an address -> name lookup

Moreover:

  • each registry has a community manager which has special permissions in the protocol, discussed later

  • registration and renewal of names is done via the NNSController, discussed below.

NNSController

The NNSController is the main entry point to create registries (CldRegistry), manage prices, register and renew names.

Creation of new CLDs

Creation of new CLDs is only possible via NNSController.registerCld which can be only called by a multi-sign wallet owned by the NNS team. This operation:

  • deploys a new instance of CldRegistry

  • sets up the rewarder to distribute rewards according to the given splits

  • sets up the resolver to work with the new registry

Registration of new names

Registration of new names is only possible via NNSController.register and NNSController.registerWithSignature which can be called by anyone. Only one of these method will work for each CLD, depending on what NNSController.isSignatureRequired returns.

We have implemented a signature-based registration process to give communities extreme flexibility in determining when someone can register a name. For instance:

  • .⌐◨-◨ names that were registered in the original version of NNS on ETH Mainnet can only be registered by the original owner

  • .nouns names can only be registered by owners of a Noun or a $NOUN token and numbered names such as 1.nouns or 123.nouns can only be registered by the owner of the associated Noun.

Signatures are issued by our api at https://api.nns.xyz/register.

Names of CLDs without special rules can be registed directly with NNSController.register.

Pricing of names is determined for each CLD by its pricing oracle (IPricingOracle) which can be found by calling NNSController.pricingOracleOf. Only the community manager can change the pricing oracle of their CLD.

NNSResolver

The NNSResolver is responsible for resolving addresses to names, i.e. to return a name from an address. This is generally called the primary name. The basic functionality is just to proxy the call to the underlying registry to fetch the associated lookup but it can also help people aggregate their names across the NNS registries.

In fact, one functionality the NNS protocol provides is allowing people to set one reverse per registry which means that you can have 0x123...abc being resolved to A.⌐◨-◨ in the .⌐◨-◨ registry and to B.nouns in the .nouns registry. The NNSResolver makes cross-registry resolutions really easy thanks to

function reverseNameOf(
    address addr,
    uint256[] calldata cldIds,
    bool fallbackToDefault
) external view returns (string memory);

which resolves a given address in a certain list of CLDs, falling back to a set default in case none of the given clds has a lookup set.

The default CLD can be customised for each account via NNSResolver.setDefaultCld and fallback to NNSResolver.fallbackCld() which is set by the NNS team (to .⌐◨-◨).

You can find the default CLD being referred to as the Primary Collection following the same naming used for names.

NNSRewarder

The NNSRewarder is responsible for collecting revenues from registrations and renewal and distribute them to the different groups.

Distribuition of revenues

Each community (via the community manager) can define and change how revenues are split and specifically set the following values:

  • referral share: percentage given to the referrer which must own at least one .⌐◨-◨. In case the refer is not set of doesn't own .⌐◨-◨ names, this shares goes to the community.

  • community share: percentage given to the community owning the CLD

  • ecosystem share: percentage given to the ecosystem of resolvers

There are also two additional splits:

  • protocol share: percentage given to the protocol and is fixed to 5%

  • holder share: percentage given to holders of .⌐◨-◨ names. This automatically set to what is left, i.e. 100 - referral - community - ecosystem - protocol.

Revenues come from the NNSController and are transferred to the NNSRewarder via the collect method which exchanges ETH to $NOGS via Uniswap and then splits the $NOGS to each group according to the splits for the community.

There are two ways of distributing rewards:

  • to a specific account: used for referrals, communities and the protocol which is implemented via the AccountRewarder contract which simply keeps a balance for each address.

  • to holders of an ERC71: used for the ecosystem and holders of .⌐◨-◨ which is implemented via the ERC721BasedRewarder contract.

ERC721BasedRewarder

This contract is responsible for accumulating and distributing revenues to a group on ERC721 holders. Since the number of holders can change at any time, this process is implemented via snapshotting and has different phases.

  1. Revenues are simply accumulated in a simple counter without actually distributing them.

  2. At regular intervals (30 days), anyone can take a snapshot which:

    • Equally distributes the accumulated balance to all existing ERC721 tokens for a given collection at the time of snapshot

    • Tracks the block in which the snapshot was taken

    • Keeps track of how much revenues have been withdrawn

  3. One a snapshot exists, holders can withdraw their share long as their ERC721 was minted before the snapshot was taken. This is achieved by keeping the minting block when tokens are minted. Note that while a snapshot exists revenues are still accumulated, but won't be added to it.

When a new snapshot is taken, the unclaimed balance is redistributed to ensure nothing is ever lost.

The protocol has 2 instances of this contract:

  • the first distributes rewards to holders of .⌐◨-◨ and it's simply setup with the .⌐◨-◨ registry

  • the second distributes rewards the ecosystem and to track who is part of this group we issue a special ERC721 called NNS Resolver (NNSR) (contract NNSResolverToken). The process of verifying whether projects integrate with NNS is off-chain and therefore, the NNS Team is responsible for minting and burning these tokens as new community add or remove integrations.

Last updated