# 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

```solidity
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.
