# Registry The registry is a contract on NEAR blockchain that allows storing arbitrary information on chain, where each entry can be "endorsed" by one (or more) accounts on NEAR. The main goal of *the registry* is to allow each account/contract to provide extra information that is not available in the contract itself. Entries posted in the registry are endorsed by accounts, and this can be used by off-chain or on-chain tools to verify the validity of the data. The main goal of the registry is to provide a secure and standard way for all contracts to expose information, that can be consumed by 3rd party tools. ## Design Each account can endorse entries of the type: ``` { scope: "application-scope", key: "key", value: "value" } ``` On addition to this information, it is also stored the account that is doing the endorsement and the number of times an account has modified the value for a fixed (scope, key) pair. ## Use cases ### Use Case 1: Account metadata There are existing tools like the [explorer](https://explorer.near.org) and the [wallet](https://wallet.near.org), that shows basic on chain information about contracts, tokens and accounts in general. However the information it can shows is limited, even if the author of the contract wants to show more information (like website, contact email or twitter hanlde of the project/author) there is currently no way this can be done in a trustless way (this is not done at all today). But having access to this information is both useful for the user interacting with the contract, and the author of the contract. The explorer can establish the following criteria: If there is an entry in the registry with scope `"social"` and key `"twitter"`, endorsed by `account.near`, then when showing information for `account.near`, there will be a link to the twitter page of this account, pointing to the value of this entry in the registry. ``` { scope: "social", key: "twitter", value: "https://twitter.com/auroraisnear" } ``` It will be the same of several services defined by the explorer before hand, for example telegram: ``` { scope: "social", key: "telegram", value: "https://t.me/official-registry" } ``` The registry will provide an interface to iterate over all keys endorsed by a an account on a given scope, this way information can be discovered easily. #### Contracts that can't endorse by themselves There are some accounts that can't endorse entries in the registry by themselves. This is the case for example when a contract doesn't have any key associated with it. In this case, applications using trusted processes can verify the information and endorse entries using a trusted account. The explorer team can use the account `official-explorer.near`, and endorse the entry: ``` { scope: "social-wrap.near", key: "website", value: "https://wrap.near.org" } ``` Notice this will require an endorsement from an account controlled by the explorer team, so it is up to them how and whom will be paying the fees for storage and gas. ### Use Case 2: Custom bridged NFT/FT The bridge allows moving assets from Ethereum to NEAR. However, the equivalent NEP-141 on NEAR has only vanilla features (transfers and withdrawals). NFT(ERC-721) or FT(ERC-20) that has custom features on ethereum, can't use them on NEAR. (*) The proposed solution is to deploy the extended contract on NEAR with all the customs features. When tokens are sent to NEAR network, they are automatically swapped 1:1 between the vanilla contract and the extended contract. To discover this contracts, and supports this swaps automatically from each contract (like [rainbow-bridge](https://rainbowbridge.app/)), there will be an entry in the registry endorsed by `aurora` account with the format: ``` { scope: "custom-ft", key: "6b175474e89094c44da98b954eedeac495271d0f.factory.bridge.near", value: "custom_dai.near" } ``` This will tell each application that vanilla `nDAI` should be swapped for `custom_dai.near` on arrival, and treat this new contract as the real `nDAI`. Aurora team is responsible in this case for doing the dilligence of reviewing and endorsing each account. Notice that other account can endorse differen keys/values, it is up to each application for trusting on each endorser. (*) This is done this way, since we aim to have a trustless bridge, where anyone can move/deploy a token from Ethereum on NEAR, and custom implementations can't be trusted. ### Proposals acceptance / Signature collection When there is proposal for a protocol upgrade, it is required that it is accepted by the majority of the nodes. The proposal can be stored in the registry, and can be automatically activated after more than 80% of all the validators endorsed it in the registry. So this contract can have a close role to consensus itself. Notice this is not limited to consensus/on-chain proposals. But also for proposals off-chain, DAOs, or in real live signature collection. ## Pseudo code Basic implementation of registry. ```python class Registry: def endorse(self, scope: str, key: str, value: str): """ Current account id endorse the pair (key, value). For each entry endorsed by an account, each `key` is unique. """ def remove_endorsement(self, scope: str, key: str): """ Remove an endorsement emitted by current account id for this key. """ def endorsements_by_key(self, scope: str, key: str) -> List[(AccountId, value: str)]: """ Return the list of all endorsements for this key. Each account may have endorsed a different value. """ def endorsements_by_account(self, scope: str, account_id: str) -> List[(key: str, value: str)]: """ Return the list of all endorsements by this account on a given scope. """ def is_endorsed_by(self, scope: str, key: str, account_id: str) -> Optional[str]: """ Returns the value endorsed by an account for a selected key. """ # Notes: # - More reverse index queries can be designed based on other use cases # - For functions that returns lists, an efficient pagination system # can be used to retrieve the information without hitting limits of the RPC. ``` **Note**: [official-registry.near](https://explorer.near.org/accounts/official-registry.near) was saved in case we decide to use it, but a different account can be used as well. ### Nonces For each tuple `(scope, key, account_id)` there will be a nonce associated with it indicating how many time the entry has been modified so far. This nonce will increase each time the value changes, or the endorsement is removed. The nonce can be used to detect if a value has potentially changed since the last time it was retrieved. ## Security - Contracts shouldn't be tricked into endorsing entries without their consent. Entries are approved by predecessor_account_id(). This means that web applications can try to trick accounts into endorsing some entries. - Any contract can endorse any entry, there is no limitation. Tools consuming this information must make sure they validate the entries are validated by the expected accounts. - One proposal can be endorsed by several (unlimited) accounts. Registry will provide an efficient interface to access endorsements from legitimate accounts. ### Upgrades Upgrades shouldn't be necessary. There are two major scenarios where upgrades can be required: - New interface to access the data We should brainstorm different use cases of this registry, so efficient interfaces for accessing data is available on-chain. This is important for other contracts and off-chain tools that can't afford downloading the whole state of the contract. - Bug in the contract Contract should be simple enough so it is easy to audit, and determine bugs are not present. ## Economics There is no economic model around this contract. No fee will be charged, and no deposit will be accepted on function calls, other than 1 yoctoNEAR for tx that requires signatures in the wallet. ### Storage management Each user/application is responsible for depositing enough balance to pay for storage. In general the registry will accept donations for paying for storage, though should be notice that this can be easily abused by accounts endorsing _useless_ entries. ## Other features - **Persistence**: Should the registry provide access to historical information? i.e making queries passing also the block height to provide access for old values? - **Time**: Should the registry also store the block height (time) when each registry was updated. This might be useful for polls or events that has a closing time, or for commitements that must be done before/after certaing time.