Tokenization and Governance components of IC DAPP, introducing how SNS system

blockpunk
ICP League
Published in
12 min readMar 7, 2022

Content from Lara Schmid (DFINITY) & Nicolas Zoghb (Software Engineer) Community Conversations

DFINITY’s developer forum: https://forum.dfinity.org/t/sns-deployment-and-upgrades-design-proposal/10816

Similar to how the Network Nervous System (NNS) is the open tokenized governance system that controls the Internet Computer blockchain (IC), service nervous systems (SNSs) are algorithmic DAOs that will allow developers to create decentralized, token-based governance systems for their dapps.

The Q4 of 2021, DFINITY Foundation first proposed the design of the Service Neuron System, but the community believes that the initial proposal of SNS is too complex, and the new proposal has updated a lot of content:.

  • SNS contains three parts: governance, tokens and system;
  • SNS can help DAPPs achieve decentralized governance, token issuance;
  • to build a dedicated subnet for SNS, with governance and tokenization as the underlying functionality of the system;
  • More flexible operation, developers can build their own SNS or use SNS subnets.

Overview of SNS

What is an SNS?

Network Nervous System (NNS) is the open governance system that governs the full internet computer with all its subnets and nodes. Service Nervous System (SNS), as also an open governance system, is a similar concept. Rather than the internet computer, an SNS just governs one decentralized application (dapp). Therefore, we would have one SNS for one dapp.

Why would we want an SNS?

A few key concepts that are needed for true web3 applications are:

  • Dapps are truly hosted on-chain end to end (including the front-end and everything);
  • Dapps are user-owned;
  • Dapps are user-controlled.

For the last two points, we need a DAO (Decentralized Autonomous Organization), which exactly is an SNS. Therefore, an SNS enables two key things: decentralization and tokenization. For the controlled part, the decentral control over a dapp, how it should be evolved, and so forth. Users can control where the dapp goes. SNS also enables tokenization. It introduces a token, which enables ownership of the users over this system. And thereby it also allows for a variety of new incentive systems.

Canisters in SNS:

The governance, the ledger, and the root.

Governance Canister

  • It hosts proposals, which facilitate decision-making on the SNS. Basically, proposals are suggestions on how the dapp should be evolved.
  • It also holds neurons, which determines where to participate in governance. Everyone can take some tokens and stake them in a neuron. Therefore, a neuron contains stake tokens, and then becomes a participant of this governance system. So it is really an open governance system.

Ledger Canister

Firstly, each SNS can have its own Governance token. Ledger canister can tracks two things:

  • It specifies which account has how many tokens.
  • It also tracks the transactions between those accounts.

Root Canister (system):

For this, we have to understand how upgrades of canisters work. An upgrade entails three things: first, one stops a canister, one installs the new code for this canister, and then one can restart the canister. Now the problem is that canisters cannot do that to upgrade themselves. For example, the Governance canister cannot stop and restart itself, and therefore, we need another canister to orchestrate this upgrade. This is exactly what the Root does.

We could have also thought about putting this logic into the ledger and letting the Ledger upgrades root, however, we found that the Ledger should be kept as simple as possible. This is a cleaner solution to have this in a separate canister. This is also what we do on the NNS. We also have a very similar Root canister there and we plan to reuse the code that we already have from the NNS.

SNS Subnet

We propose that this would be in the IC repo, where the NNS canisters and the rest of the open-source code is. Everyone could take the code from github and deploy these canisters on an application subnet.This is basically what provides maximum flexibility.

However, this approach also comes with some disadvantages. First, any upgrades to governance, ledgers, or root directories would need to be performed by the SNS community, which requires a great deal of complex specialized work that presents challenges to governance. In contrast, an SNS deployed as a system function provided in an NNS network, relying on NNS authentication, is much more simplified. At the same time, self-deployed SNSs run on application subnets, which do not have as many nodes as the system subnets on which the NNS is located, and are therefore less secure.

SNS as System Function:

propose to have a new SNS subnet as the native system function of an IC, that exclusively runs SNSs.

The purple dotted lines show the subnet boundaries. On the left, there is the NNS subnet and on the right button, there is a normal application subnet where the dapp already lives.

Difference from other Subnet

  • We want the subnet only to host SNSs. For security reasons, no other canister can interfere.
  • We also want to have a larger replication so that more nodes than other application subnets. Currently, we are thinking about starting with 34 nodes.
  • Because of more nodes and more replication, this subnet should be more expensive than other application subnets.

Scalability

If a subnet cannot hold an unbounded number of canisters, then, if this SNS subnet is full, we can just add new SNS subnets as we can add new subnets in general on the internet computer.

  • Anyone can make a proposal to add a new subnet.
  • If this proposal is adopted, the information would then be updated in the registry.
  • And the register would create such a new subnet.

SNS Deployment

Let’s assume we have an orange user that owns this step on this application subnet, and this orange user now wants to deploy an SNS.

  • To do so, the user could first get a cycles wallet. It does not have to be on the same application subnet as the dapp because it is just for simplicity for now.
  • Then the user can state that it wants to deploy a new SNS, and to do so, it would issue a call by this cycle wallet to this SNS wasm module canister. This call has several purposes: first, it would send the long-enough cycles to pay for the initial cycles of the SNS. Then it would also define the initial arguments of the SNS. This includes, for example, the initial accounts on the ledger, the token name, the initial neurons that should exist, and so forth.
  • The SNS wasm module canister would then check that these initial arguments are consistent. For example, for each neuron, there is an account on the ledger and so forth. It would also make some other checks. For example, it can check if there is still space for new SNSs on this subnet.
  • If all of these checks are good, it would then create these new canisters, the governance, ledger, and root.

We envisioned that this could be included in a more user-friendly front-end to make this open to any even wider audience.

SNS Usage

A user can get an SNS at any point in time, and at any other point in time they can then just change the dapp’s controller to the SNS.

It also allows developers to deploy in SNS, add the SNS as the controller of the dapp but also remain controllers themselves. After some time, if they have enough confidence that the SNS works as they intent, they can then remove themselves from the controllers and make the dapp fully SNS-controlled.

Therefore, this allows to just deploy an SNS without even having a dapp, and then maybe use the SNS to get the initial funding, or to first find out what the community even wants, and then later only develop the dapp and assign its control to the SNS.

Within the SNS, the Root canister controls all the other canisters including the dapp canisters, and that the Governance canister controls the Root canister. Updates to dapps are controlled by the SNS governance container

To upgrade the SNS itself, for example with some bugs in the ledger container, the NNS root container is required to control the SNS update. We have to make a proposal to the NNS, and after the proposal is approved, the NNS will modify its own system container and issue a request for the SNS upgrade (or fix some bugs).

SNS Upgrade

Now that we have an SNS deployed, how do we add new features or simply fix bugs (that may have been attacked)? So we need the SNS to be able to be updated.

Challenges:

  • Versions can become incompatible: not all versions of governance, ledger, and root might be compatible.This repo is always evolving, so there will be different versions of these canisters. It might be that not all these versions from the different canisters are actually compatible with each other. An extreme example is that, if we delete an API method in the governance, it could be that all of a sudden, a ledger that wants to call this API is not compatible with this governance anymore.
  • Upgrades can become insecure: not all upgrades from one to another version might be secure.It might not be possible or it might not be well defined what happens if we upgrade from any version, for example, of governance, to any newer version of governance. So it might be that, for example, if we upgrade from a very old version of governance to a very new version of governance, somewhere in the middle we should have done some cleanup that then gets lost. That is, therefore, not secure to do.

Ensure upgrade security

Because this is very challenging that each SNS has to make sure that all the upgrades are secure, we propose that we could put this information in the enermy’s registry.

The NNS community could test some things really well, and then they can bless this information and put it in the registry. The SNS communities then know that certain things have been well tested and we can already have some confidence that probably if we follow these upgrades that the outcome will be good.

There are two main informations that we want to have in this registry. As you can see from the picture below, we propose blessing deployment paths.

First, the single deployments. As you can see, for example, the first line shows that the Governance, Ledger, and Root, all at version 0, are compatible with each other. So this is a deployment that you can deploy these three canisters together. Also the Ledger Canister Version 1 is compatible with Governance and Root at Version 0. This is the first information that is in there.

The additional information is from which deployment you can upgrate to which new deployment. It is this information states that it if fine and it has been well tested that you can upgrade from this version where all canisters run Version 0 to the version where the ledger runs Version 1.

Compared to bless wasm versions, blessing upgrade path is the better option. For example, the following are governance versions that have been well tested and we think they work fine. What could then happen is that, as we already stated, it might be possible that it is fine to upgrade from version 0 to version 1 and from version 1 to version 2. But it is actually not advisable to upgrade from version 0 to version 2 because that might break something. Now if we only had the information that you see on top in the registry, namely just the versions that are blessed, it could happen that someone is currently at version 0 and sees that version 2 is blessed, and tries to upgrade to it, and then chooses this upgrade path that is not advisable.

Blessing the upgrade path of the individual containers is also problematic. For Governance and Ledger, it is fine to upgrade from version 0 to version 1. The problem could be about the compatibility that we talked about. For example, as explained here on the left, assume that Ledger Version 0 works well with both Governance Version 0 and Version 1, but Ledger Version 1 only works with the Governance version 1. It means that we should first upgrade Governance and then Ledger. However, if we just have the information on top and just know the individual canisters’ upgrade paths, it could be that someone chooses to first operate the Ledger and then ends up in this situation where we have two incompatible canisters.Therefore, it is advised to deploy the SNS as a whole.

How to Upgrade

There are two basic possibilities for how we can do it. First, everyone can choose to compile the code and install the canisters on any application subnet, and then manually upgrade them to whatever they want.

In contrast to the self-deployment, the SNSs can be provided as a system function and would live on a special subnet. Then they would be automatically kept up to date, which would not require any more input from the users.

To make sure the SNSs would upgrade themselves and not require continuous input, the container needs to know what to upgrade to and this information has to be on the chain.

We already saw that the deployments are blessed in the registry, from which the canisters can already learn what are the latest versions that have been blessed. However, these blessed versions actually only contain the hashes of the wasms. To upgrade, the canisters also have to know what wasm to be freshly installed. Therefore if all of this should be automated, we also need to have the wasms themselves on-chain. This is why we propose a new canister that holds these SNS wasm modules, and we propose to have it on this SNS subnet. For every new SNS canister that we proposed, we would then add the new wasm to this SNS wasm module canister.

As previously stated, the information about what should be the newest version that the SNSs should run on is both in the registry and the actual wasm canisters are on this new canister. This means if we want to add a new version, we have to update it in these two places first. And then the SNSs can pull this information and upgrade themselves. Here is how it works:

(1) Proposal: bless new deployment path (Ledger Version 1): Let’s assume that the blue user wants to propose that we upgrade this deployment by upgrading the ledger to Version 1. The blue user would then extensively test that and make sure that the upgrade to this new deployment actually works, that the ledger Version 1 is compatible with the current coverage and root. If they did so, they would then issue a proposal to the governance canister.

(2) On proposal adoption, update: The NNS community would do the same tests and make sure that they are confident that this is something they can support. If the proposal is adopted, the registry would be updated to say that you can upgrade to this new deployment.

(3) Update wasm of Ledger to Version 1: Now we also need to update the right side here. For that, the same user or any other user can send the wasm of this ledger Version 1 to the SNS wasm module canister.

(4) Check: The SNS wasm module canister would then check whether this new version is one that has previously been blessed on the registry. Only if that’s the case, it would actually accept this new wasm module.

(5) Update: If that’s the case, it would then update its information. We will now have the new SNS ledger available.

SNS Auto-Upgrading

(1) Check for new deployment: The governance canister of the SNS can just regularly check whether there are new versions in the registry. So it would know which version all the SNS canisters run and can compare the versions on the registry with that.

(2) Fetch new wasm & Initiate upgrade: If there are new versions, it could then get this wasm from the SNS wasm module canister and initiate the update.

--

--

blockpunk
ICP League

Co-founder of ICP League & Ourea Group, obsessed with Social Tokens, DAO & NFT.