Difference between revisions of "How-to: Verify SNS decentralization swap proposal"
Line 21: | Line 21: | ||
== Step 2: Verifying the SNS canisters == | == Step 2: Verifying the SNS canisters == | ||
The proposal payload contains the canister ID of the decentralization sale that it will call if the proposal is adopted. A good proposal summary will contain the canister IDs of the other SNS canisters as well as that of the dapp controlled by the SNS. | The proposal payload contains the canister ID of the decentralization sale that it will call if the proposal is adopted. A good proposal summary will contain the canister IDs of the other SNS canisters as well as that of the dapp controlled by the SNS. | ||
− | The next step is to verify that the provided decentralization sale is indeed part of an SNS composed of the canisters claimed in the proposal summary. | + | The next step is to verify that the provided decentralization sale is indeed part of an SNS composed of the canisters claimed in the proposal summary. These steps are outlined in the [[How-to: Interact with SNS canisters]] page, but we repeat them below for convenience. |
+ | |||
+ | === 1. Preparation === | ||
+ | |||
+ | ==== DFX ==== | ||
+ | If you want to use DFX, download these snippets into an empty repo so that DFX can point at the correct canisters. This will allow you to call the canisters and read the output in a human friendly way. Snippet 1: [https://gitlab.com/-/snippets/2431348 dfx.json and candid files] | ||
+ | |||
+ | === 2. Get the SNS root canister. === | ||
+ | The SNS root canister is the SNS canister that knows about and controls all the other SNS canisters and the dapp canisters. Therefore it is the canister by which a particular SNS can be identified. All SNS root canisters, and thus all SNSs, are listed in the NNS canister called SNS ''wasm modules canister'', or ''SNS-W'' for short. As such, the first step is to verify that the root canister in the proposal summary is in the list of '''deployed_snses'''. SNS-W is a fixed canister ID in the NNS subnet and its canister ID is qaa6y-5yaaa-aaaaa-aaafa-cai. | ||
+ | Call the method list_deployed_snses and verify that the root canister ID from the proposal is in the returned list. | ||
+ | |||
+ | ==== DFX ==== | ||
+ | <nowiki>$ dfx canister --network ic call qaa6y-5yaaa-aaaaa-aaafa-cai list_deployed_snses '(record {})'</nowiki> | ||
+ | |||
+ | ==== Dashboard ==== | ||
+ | In the [https://dashboard.internetcomputer.org/canister/qaa6y-5yaaa-aaaaa-aaafa-cai SNS-W canister interface], click ‘+’ next to <syntaxhighlight inline>list_deployed_snses</syntaxhighlight>, and then click “Call”. | ||
+ | |||
+ | === 3. Get all SNS and dapp canisters === | ||
+ | From the last step, the root canister ID has been verified as a “true” SNS root canister ID deployed through the blessed canister wasm path. You can next get the rest of the canister IDs associated with that SNS by calling <syntaxhighlight inline>list_sns_canisters</syntaxhighlight> on the SNS root canister. | ||
+ | The response from this method should have a “swap” entry that matches the swap_canister_id in the NNS proposal from Step 1. By verifying that the canister of this decentralization sale matches, you verify that the NNS proposal will indeed call the sale canister of the SNS that you are inspecting. | ||
+ | The response from this method also has a “dapps” entry that should match what the proposal suggests is under control of the SNS. | ||
+ | |||
+ | ==== DFX ==== | ||
+ | <nowiki>$ dfx canister --network ic call zxeu2-7aaaa-aaaaq-aaafa-cai list_sns_canisters '(record {} )'</nowiki> | ||
+ | You can verify that the human friendly labels match the canister ids returned by inspecting the canister_ids.json file. | ||
+ | |||
+ | ==== Dashboard ==== | ||
+ | On the dashboard, enter the canister ID of SNS root in the search tab. You should see all the methods of SNS root now. Similarly to the last step, click ‘+’ next to <syntaxhighlight inline>list_sns_canisters</syntaxhighlight>, and then click “Call”. | ||
+ | |||
+ | === 4. Get the summary of all SNS and dapp canisters === | ||
+ | Finally, you can get the summary and ownership graph of the SNS including the dapps. To do so, call <syntaxhighlight inline>get_sns_canisters_summary</syntaxhighlight> on the SNS root canister. This will return the status of each canister in the SNS, including information such as the canister’s controller and cycles balance. | ||
+ | |||
+ | ==== DFX ==== | ||
+ | <nowiki>$ dfx canister --network ic call zxeu2-7aaaa-aaaaq-aaafa-cai get_sns_canisters_summary '(record {} )'</nowiki> | ||
+ | |||
+ | ==== Dashboard ==== | ||
+ | On the dashboard, where you should still be in SNS root canister interface from the last Step, click ‘+’ next to <syntaxhighlight inline>get_sns_canisters_summary</syntaxhighlight>, and then click “Call”. | ||
+ | |||
+ | == Step 3: Verifying the initial SNS Parameters == | ||
+ | After Step 2, the IDs of all SNS canisters are known. The next step is to verify the parameters that these canisters have been initialized with. | ||
+ | |||
+ | === 1. Check the initialization parameters === | ||
+ | The SNS governance canister stores all the initial parameters that were provided to SNS-W when the SNS was first installed. SNS governance can be queried for this information to learn how the SNS was set up. This information includes the initial token distribution, as well as the initial neurons, consisting of developer and airdrop neurons. | ||
+ | |||
+ | === DFX === | ||
+ | <nowiki>$ dfx canister --network ic call zqfso-syaaa-aaaaq-aaafq-cai get_sns_initialization_parameters '(record {})'</nowiki> | ||
+ | |||
+ | === Dashboard === | ||
+ | On the dashboard, navigate to the SNS governance canister by entering the canister ID in the search bar. Then, click ‘+’ next to <syntaxhighlight inline>get_sns_initialization_parameters</syntaxhighlight>, and click “Call”. | ||
+ | |||
+ | === 2. List the neurons that exist in SNS Governance === | ||
+ | You can then see that the neurons available add up to the initialization parameters that you just inspected and that the current stake of them is as expected. | ||
+ | |||
+ | ==== DFX ==== | ||
+ | <nowiki>$ dfx canister --network ic call zqfso-syaaa-aaaaq-aaafq-cai list_neurons '(record { of_principal=null; limit=100: nat32; start_page_at=null } )'</nowiki> | ||
+ | |||
+ | ==== Dashboard ==== | ||
+ | Navigate to the SNS governance canister by entering the canister ID in the search bar. For SNS-1, this is <syntaxhighlight inline>zqfso-syaaa-aaaaq-aaafq-cai</syntaxhighlight>. | ||
+ | Then, click ‘+’ next to <syntaxhighlight inline>list_neurons</syntaxhighlight>. You don't need to choose anything for <syntaxhighlight inline>of_principle</syntaxhighlight> if you want to look at all neurons. Choose a limit as described above. For the first page you don't need to select a <syntaxhighlight inline>start_page_at</syntaxhighlight> and can click “Call”. For the subsequent calls, adjust <syntaxhighlight inline>start_page_at</syntaxhighlight> as described above. | ||
+ | |||
+ | === 3. Verify that the SNS tokens in the decentralization sale match what was claimed in the proposal === | ||
+ | The SNS tokens that are sold off in the initial sale are stored in the SNS ledger account that is owned by the SNS sale canister. Thus, to learn how many tokens are in the decentralization sale, call <syntaxhighlight inline>icrc1_balance_of</syntaxhighlight> to get the balance of the Swap canister. The returned value is given in fractions of 10E-8 of an SNS token. You can now compare this value to '''snsTokensE8s''' that is specified in the NNS proposal. | ||
+ | |||
+ | === DFX === | ||
+ | <syntaxhighlight> | ||
+ | $ dfx canister --network https://ic0.app call zfcdd-tqaaa-aaaaq-aaaga-cai --query icrc1_balance_of '(record {owner = principal "zcdfx-6iaaa-aaaaq-aaagq-cai" })' | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==== Dashboard (Future) ==== | ||
+ | ''For this to work, we first have to upgrade the SNS ledger canister to a new version.'' | ||
+ | <!--*On the dashboard, navigate to the SNS ledger canister by entering the canister ID in the search bar. Then, click ‘+’ next to <syntaxhighlight inline>icrc1_balance_of</syntaxhighlight>, and provide as the argument the ID of the SNS swap canister. Then press <syntaxhighlight inline>call</syntaxhighlight>. | ||
+ | --> | ||
+ | |||
+ | === 4. Learn how many tokens are in the SNS treasury === | ||
+ | The SNS treasury is a SNS ledger account that is owned by SNS governance. Specifically, it is on a defined subaccount of the SNS governance’s ledger account. To learn it, use <syntaxhighlight inline>icrc1_balance_of</syntaxhighlight> to get the balance of the SNS ledger account with the following arguments: | ||
+ | |||
+ | ==== DFX ==== | ||
+ | <syntaxhighlight> | ||
+ | dfx canister --network https://ic0.app call --query zfcdd-tqaaa-aaaaq-aaaga-cai icrc1_balance_of '(record {owner = principal "zqfso-syaaa-aaaaq-aaafq-cai"; subaccount = blob "\ce\c2\14\5a\75\0f\d4\a4\72\b2\a0\21\f6\df\f1\e4\a9\07\29\97\00\06\2a\0a\02\bc\1e\a6\5c\a2\92\58" })' | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==== Dashboard (Future) ==== | ||
+ | ''For this to work, we first have to upgrade the SNS ledger canister to a new version.'' | ||
+ | <!--* On the dashboard, navigate to the SNS ledger canister by entering the canister ID in the search bar. Then, click ‘+’ next to <syntaxhighlight inline>icrc1_balance_of</syntaxhighlight>, and provide as the argument TODO. Then press “Call”. | ||
+ | --> | ||
+ | |||
+ | <!--* | ||
+ | === 5. Learn how much SNS tokens are reserved for future sales === | ||
+ | In addition to the (initial) decentralization sale, an SNS can reserve more tokens to be sold in future sales. These are stored on another SNS ledger subaccount that is also owned by SNS governance. Get the balance of the reserve sales account as follows: | ||
+ | |||
+ | ==== DFX ==== | ||
+ | <nowiki>$ dfx canister --network small12 call sns-ledger icrc1_balance_of '(record { owner = principal "w6ozc-gaaaa-aaaaa-aaarq-cai"; subaccount = opt vec{230;189;98;113;207;46;8;177;99;250;48;152;235;47;252;52;48;240;220;105;254;236;8;61;79;30;8;171;9;0;149;167}: opt vec nat8;})'</nowiki> | ||
+ | |||
+ | ==== Dashboard ==== | ||
+ | TODO | ||
+ | --> |
Revision as of 10:18, 25 November 2022
The process of launching an SNS for a dapp goes through the following main stages:
- Stage 1: A developer makes a call to the SNS wasm modules canister on the NNS requesting to get an SNS. The SNS canisters are installed on the SNS subnet based on the initial parameters chosen by the developer (e.g., initial neurons, number of tokens). The developer hands control of the dapp over to the SNS.
- Stage 2: An NNS proposal is created to start a decentralization sale for the SNS. In addition to the initial parameters set when the SNS was installed, this proposal specifies additional parameters for the decentralization sale.
- Stage 3: If the NNS proposal is adopted, the decentralization sale starts immediately.
This page contains information for NNS neuron holders to consider when voting in Stage 2. Specifically, it explains how the parameters in the NNS proposals can be interpreted and verified, and how SNS canisters can be queried to learn whether the SNS's configurations are valid. All this information is available on chain and can be accessed via (as yet) a manual process where there are two options to interact with the relevant canister: using the DFX tool, or using the Internet Computer Dashboard. Below, there are step by step instructions describing how to proceed and, whenever canister calls are involved, explanations for DFX and dashboard interactions are given.
Step 1: Verify the Parameters for the Decentralization Sale in the NNS proposal
As mentioned above, some of the parameters for the decentralization sale are set in the NNS proposal. To verify them, you can look at the field Params in the NNS proposal (e.g. in the NNS frontend dapp or on the dashboard). These parameters are submitted as part of the proposal and represent the information with which the NNS governance canister will open the decentralization sale if the proposal is adopted. You can check if the parameters match with those submitted in the proposal summary. In contrast to the parameters here, the summary can be freely chosen by the proposer and should not be trusted.
This is what the different entries mean:
- minParticipantsIcpE8s is the minimum amount of ICP that a sale participant has to invest for a valid participation. The value is given in fractions of 10E-8 of an ICP, which means that you have to remove eight zeros to convert this to an ICP value: In the example, 10000000 e8s = 0.1 ICP.
- maxIcpE8s is the maximum number of ICP that the decentralization sale will collect. If this maximum is reached, the sale will be finished. The value is given in fractions of 10E-8 of an ICP.
- swapDueTimestampSeconds denotes a timestamp when the decentralization sale (previously called “swap”) will be finished in case that the maximum ICP is not reached before this time. The unit of this parameter is in seconds from the Unix epoch. You can use an online converter to convert this to a human readable date and time.
- minParticipants is the minimum number of sale participants for the decentralization sale to be considered successful. If the sale ends and there are less participants, the sale failed.
- snsTokensE8s is the number of SNS tokens that are sold in the initial decentralization sale. The value is given in fractions of 10E-8 of an SNS token. This value should match the “sales supply allocated to initial decentralization sale” that the SNS was initialized with. This can be checked in Step 3.
- maxParticipantIcpE8s is the maximum contribution that an individual sale participant can make. The value is given in fractions of 10E-8 of an ICP.
- minIcpE8s is the minimum number of ICP that the decentralization sale will collect. The value is given in fractions of 10E-8 of an ICP.
Step 2: Verifying the SNS canisters
The proposal payload contains the canister ID of the decentralization sale that it will call if the proposal is adopted. A good proposal summary will contain the canister IDs of the other SNS canisters as well as that of the dapp controlled by the SNS. The next step is to verify that the provided decentralization sale is indeed part of an SNS composed of the canisters claimed in the proposal summary. These steps are outlined in the How-to: Interact with SNS canisters page, but we repeat them below for convenience.
1. Preparation
DFX
If you want to use DFX, download these snippets into an empty repo so that DFX can point at the correct canisters. This will allow you to call the canisters and read the output in a human friendly way. Snippet 1: dfx.json and candid files
2. Get the SNS root canister.
The SNS root canister is the SNS canister that knows about and controls all the other SNS canisters and the dapp canisters. Therefore it is the canister by which a particular SNS can be identified. All SNS root canisters, and thus all SNSs, are listed in the NNS canister called SNS wasm modules canister, or SNS-W for short. As such, the first step is to verify that the root canister in the proposal summary is in the list of deployed_snses. SNS-W is a fixed canister ID in the NNS subnet and its canister ID is qaa6y-5yaaa-aaaaa-aaafa-cai. Call the method list_deployed_snses and verify that the root canister ID from the proposal is in the returned list.
DFX
$ dfx canister --network ic call qaa6y-5yaaa-aaaaa-aaafa-cai list_deployed_snses '(record {})'
Dashboard
In the SNS-W canister interface, click ‘+’ next to list_deployed_snses
, and then click “Call”.
3. Get all SNS and dapp canisters
From the last step, the root canister ID has been verified as a “true” SNS root canister ID deployed through the blessed canister wasm path. You can next get the rest of the canister IDs associated with that SNS by calling list_sns_canisters
on the SNS root canister.
The response from this method should have a “swap” entry that matches the swap_canister_id in the NNS proposal from Step 1. By verifying that the canister of this decentralization sale matches, you verify that the NNS proposal will indeed call the sale canister of the SNS that you are inspecting.
The response from this method also has a “dapps” entry that should match what the proposal suggests is under control of the SNS.
DFX
$ dfx canister --network ic call zxeu2-7aaaa-aaaaq-aaafa-cai list_sns_canisters '(record {} )'
You can verify that the human friendly labels match the canister ids returned by inspecting the canister_ids.json file.
Dashboard
On the dashboard, enter the canister ID of SNS root in the search tab. You should see all the methods of SNS root now. Similarly to the last step, click ‘+’ next to list_sns_canisters
, and then click “Call”.
4. Get the summary of all SNS and dapp canisters
Finally, you can get the summary and ownership graph of the SNS including the dapps. To do so, call get_sns_canisters_summary
on the SNS root canister. This will return the status of each canister in the SNS, including information such as the canister’s controller and cycles balance.
DFX
$ dfx canister --network ic call zxeu2-7aaaa-aaaaq-aaafa-cai get_sns_canisters_summary '(record {} )'
Dashboard
On the dashboard, where you should still be in SNS root canister interface from the last Step, click ‘+’ next to get_sns_canisters_summary
, and then click “Call”.
Step 3: Verifying the initial SNS Parameters
After Step 2, the IDs of all SNS canisters are known. The next step is to verify the parameters that these canisters have been initialized with.
1. Check the initialization parameters
The SNS governance canister stores all the initial parameters that were provided to SNS-W when the SNS was first installed. SNS governance can be queried for this information to learn how the SNS was set up. This information includes the initial token distribution, as well as the initial neurons, consisting of developer and airdrop neurons.
DFX
$ dfx canister --network ic call zqfso-syaaa-aaaaq-aaafq-cai get_sns_initialization_parameters '(record {})'
Dashboard
On the dashboard, navigate to the SNS governance canister by entering the canister ID in the search bar. Then, click ‘+’ next to get_sns_initialization_parameters
, and click “Call”.
2. List the neurons that exist in SNS Governance
You can then see that the neurons available add up to the initialization parameters that you just inspected and that the current stake of them is as expected.
DFX
$ dfx canister --network ic call zqfso-syaaa-aaaaq-aaafq-cai list_neurons '(record { of_principal=null; limit=100: nat32; start_page_at=null } )'
Dashboard
Navigate to the SNS governance canister by entering the canister ID in the search bar. For SNS-1, this is zqfso-syaaa-aaaaq-aaafq-cai
.
Then, click ‘+’ next to list_neurons
. You don't need to choose anything for of_principle
if you want to look at all neurons. Choose a limit as described above. For the first page you don't need to select a start_page_at
and can click “Call”. For the subsequent calls, adjust start_page_at
as described above.
3. Verify that the SNS tokens in the decentralization sale match what was claimed in the proposal
The SNS tokens that are sold off in the initial sale are stored in the SNS ledger account that is owned by the SNS sale canister. Thus, to learn how many tokens are in the decentralization sale, call icrc1_balance_of
to get the balance of the Swap canister. The returned value is given in fractions of 10E-8 of an SNS token. You can now compare this value to snsTokensE8s that is specified in the NNS proposal.
DFX
$ dfx canister --network https://ic0.app call zfcdd-tqaaa-aaaaq-aaaga-cai --query icrc1_balance_of '(record {owner = principal "zcdfx-6iaaa-aaaaq-aaagq-cai" })'
Dashboard (Future)
For this to work, we first have to upgrade the SNS ledger canister to a new version.
4. Learn how many tokens are in the SNS treasury
The SNS treasury is a SNS ledger account that is owned by SNS governance. Specifically, it is on a defined subaccount of the SNS governance’s ledger account. To learn it, use icrc1_balance_of
to get the balance of the SNS ledger account with the following arguments:
DFX
dfx canister --network https://ic0.app call --query zfcdd-tqaaa-aaaaq-aaaga-cai icrc1_balance_of '(record {owner = principal "zqfso-syaaa-aaaaq-aaafq-cai"; subaccount = blob "\ce\c2\14\5a\75\0f\d4\a4\72\b2\a0\21\f6\df\f1\e4\a9\07\29\97\00\06\2a\0a\02\bc\1e\a6\5c\a2\92\58" })'
Dashboard (Future)
For this to work, we first have to upgrade the SNS ledger canister to a new version.