Handing over dapp canisters to an SNS DAO

TL;DR

  • Recently the NNS approved a new flow to launch SNSs, in which it is unclear how asset canisters can be handed over to an SNS DAO.
  • We propose slight modifications to the asset canister that allow a flow where the asset canister can be updated with the right information after the SNS is launched. This flow also works for other dapp canisters.
  • This does not require any changes to the SNS code and does not affect existing SNSs.

Context & Problem statement

Each SNS community might have functions that should only be executed if the SNS DAO agrees on it but that might be very dapp-specific. Generic proposals allow a flexible way for SNS communities to define such functions. Usually, the dapp canisters that implement these functions enforce that the caller of the respective method must be the SNS governance’s canister ID.

One example canister that makes use of this is the asset canister where dapps can store and retrieve assets for their frontends. To ensure decentralized decisions making, only the SNS governance canister should be able to “commit” new assets and change the permissions who can “prepare” new assets (see more details about how the assets can be updated by SNS proposal here). As long as a dapp is still under the developers’ control, the developers can trigger these functions. However, once the dapp is handed over to an SNS DAO, it is essential that these functions can only be triggered by SNS DAO decisions.

As pointed out by this user, since a new SNS launch process was introduced, there is no good way of handing over the asset canister during an SNS launch without additional trust assumptions. The same holds for other dapp canisters that work in a similar way to the asset canister.

How it worked before August 2023

Let’s first understand how this worked for the first SNS launches. Until recently, SNSs were launched in the following steps:

  1. An NNS proposal approved that an SNS launch could be started.

  2. The SNS canisters were created and initialized. As a result, everyone could learn the canister ID of the SNS governance canister.

  3. The developers handed over the dapp canisters to the SNS

  • They updated the methods implementing generic proposals so that they can only be called by the SNS governance canister’s ID.
  • They assigned the SNS root canister as the dapp canisters’ controller.
  1. An NNS proposal started the decentralization swap and, if successful, fully launched the SNS.

Why this does not work with the 1-proposal flow

With proposal 124279 the NNS released a new feature that allows SNSs to be created with a single NNS proposal.

In this new flow,

  1. The dapp’s control is handed over from the dapp developers to the NNS.
  2. A single NNS proposal creates the SNS canisters, initializes them, hands over the dapp canisters to the newly created SNS, and starts the decentralization swap.

Compared to the old flow, at the time of the dapp handover the SNS canisters do not yet exist. Therefore the ID of the SNS governance canister cannot be set at the time of the handover.

New proposed flow

Once an SNS is launched and the dapp canisters are handed over to it, the dapp canisters can be changed by SNS proposal. The idea is to make use of this fact and add one more step to the launch where a dapp canister upgrade changes the necessary privileges in the dapp canisters.

To better understand this, let us consider a concrete example, namely a canister game with a method called change_color() that changes the background color of the dapp and should only be triggered by SNS DAO decision.

The new flow would be as follows:

  1. The dapp’s control is handed over from the dapp developers to the NNS.
    In the example, this means that the controller of the canister game is set to the NNS root canister.
  2. A single NNS proposal creates the SNS canisters, initializes them, hands over the dapp canisters to the newly created SNS, and starts the decentralization swap.
    By this, everyone can learn the canister ID of the newly created SNS governance canister. Let us call it SNS_governance_ID.
  3. The SNS community upgrades the dapp canister by an SNS proposal and sets the privileges in the dapp correctly.
    The canister game is upgraded to a new version where change_color() checks that the method’s caller equals SNS_governance_ID.

In more detail, Step 3 can be realized in one of the following ways.

  • At Step 1, the canister game does not include the method change_color(). The method is only added at Step 3 with the right check that the caller is SNS_governance_ID.
  • At Step 1, the canister game already includes the method change_color() which specifies that the caller must equal a constant. At this time the constant is not set. In Step 3, the canister is upgraded to a version where the constant is set to SNS_governance_ID.
  • At Step 1, the canister game already includes the method change_color() which specifies that the caller must equal a variable that is not set at this time. In Step 3, the canister is upgraded with upgrade arguments SNS_governance_ID and this variable is set to it.

Asset canister

We intend to adopt the asset canister so that the third version above would also work for this case. This means that projects that use an asset canister can hand over the asset canister to the NNS in Step 1 of the SNS launch and, after the SNS is created, upgrade it with upgrade arguments that specify the SNS governance’s canister ID.

We intend to do this by adding optional upgrade arguments that can be used to replace the existing permission settings with new permissions.

Next steps

We are looking forward to hearing your feedback on this proposed flow. This new proposed flow requires no changes to the SNS launch process and minimal changes to the asset canister.

If there are no big concerns raised here, we plan to make the appropriate adoptions in the publicly accessible implementation of the asset canister.

8 Likes