Get desktop application:
View/edit binary Protocol Buffers messages
Used in: , ,
The amount of ICP accepted from this buyer. ICP is accepted by first making a ledger transfer and then calling the method `refresh_buyer_token_e8s`. Can only be set when a buyer state record for a new buyer is created, which can only happen when the lifecycle state is `Open`. Must be at least `min_participant_icp_e8s`, and at most `max_participant_icp_e8s`. Invariant between canisters in the OPEN state: ```text icp.amount_e8 <= icp_ledger.balance_of(subaccount(swap_canister, P)), ``` where `P` is the principal ID associated with this buyer's state. ownership * PENDING - a `BuyerState` cannot exist * OPEN - owned by the buyer, cannot be transferred out * COMMITTED - owned by the SNS governance canister, can be transferred out * ABORTED - owned by the buyer, can be transferred out
Idempotency flag indicating whether the neuron recipes have been created for the BuyerState. When set to true, it signifies that the action of creating neuron recipes has been performed on this structure. If the action is retried, this flag can be checked to avoid duplicate operations.
Used in: , , , ,
Information about a Neurons' Fund investment. The NNS Governance canister is the controller of these neurons.
Used in:
Represents one NNS neuron from the Neurons' Fund participating in this swap.
Used in:
The NNS neuron ID of the participating neuron.
The amount of ICP that the Neurons' Fund invests associated with this neuron.
Idempotency flag indicating whether the neuron recipes have been created for the CfNeuron. When set to true, it signifies that the action of creating neuron recipes has been performed on this structure. If the action is retried, this flag can be checked to avoid duplicate operations.
Represents a Neurons' Fund participant, possibly with several neurons.
Used in: , , , ,
The principal that can vote on behalf of these Neurons' Fund neurons.
Information about the participating neurons. Must not be empty.
Used in:
Current number of non-Neurons' Fund swap participants
Current number of Neurons' Fund swap participants. In particular, it's the number of unique controllers of the neurons participating in the Neurons' Fund.
Current number of Neurons' Fund neurons participating in the swap May be greater than cf_participant_count if multiple neurons in the Neurons' Fund have the same controller.
Current approximate rate SNS tokens per ICP. Note that this should not be used for super precise financial accounting, because this is floating point.
Current amount of contributions from direct swap participants.
Current amount that the Neurons' Fund promises to participate with if the swap were to successfully finalize now. Until the swap's success criterium is satisfied, this value is merely a progress indicator.
Information about a direct investor.
Used in:
Request a refund of tokens that were sent to the canister in error. The refund is always on the ICP ledger, from this canister's subaccount of the caller to the account of the caller.
Principal who originally sent the funds to us, and is now asking for any unaccepted balance to be returned.
Request was not successful, and no funds were transferred.
Used in:
Used in:
There is something wrong with the request. If repeated, the request will always be rejected.
Most likely, the canister is in the wrong Lifecycle. More generally, the system is not yet in a state where the request can be fulfilled, but it might enter a suitable state later. In this case, the same request might be accepted later.
Most likely, a request to the ledger failed, in which case, it can be assumed that no funds were transferred. In general, this is caused by something outside this canister, which usually means some other canister (such as ledger).
Request was completed successfully.
Used in:
The ledger transfer went through at this block height.
Once a swap is committed or aborted, the tokens need to be distributed, and, if the swap was committed, neurons created.
(message has no fields)
Response from the `finalize_swap` canister API.
Used in: ,
Explains what (if anything) went wrong.
(message has no fields)
Reflects whether auto-finalization has been enabled via in the init parameters (`should_auto_finalize`).
True if and only if auto-finalization has been started.
Will be populated with the FinalizeSwapResponse once auto-finalization has completed.
The principal_id of the user who's buyer state is being queried for.
(message has no fields)
The total amount of ICP deposited by buyers.
(message has no fields)
Request struct for the method `get_derived_state`
(message has no fields)
Response struct for the method `get_derived_state`
Current number of non-Neurons' Fund swap participants
Current number of Neurons' Fund swap participants. In particular, it's the number of unique controllers of the neurons participating in the Neurons' Fund.
Current number of Neurons' Fund neurons participating in the swap May be greater than cf_participant_count if multiple neurons in the Neurons' Fund have the same controller.
Current amount of contributions from direct swap participants.
Current amount of contributions from the Neurons' Fund.
Request struct for the method `get_init`
(message has no fields)
Response struct for the method `get_init`
Request struct for the method `get_lifecycle`
(message has no fields)
Response struct for the method `get_lifecycle`
Request struct for the method `get_open_ticket`
(message has no fields)
Response struct for the method `get_open_ticket`
Request was not successful, and no ticket was created.
Used in:
Used in:
Request was completed successfully.
Used in:
If there is an open swap ticket for the caller then this field contains it.
Request struct for the method `get_sale_parameters`.
(message has no fields)
Response struct for the method `get_sale_parameters`.
TODO: introduce a limits on the number of buyers to include?
(message has no fields)
Copied from nns governance.proto.
Used in: ,
Used in:
The operation was successfully completed.
This operation is not available, e.g., not implemented.
The caller is not authorized to perform this operation.
Some entity required for the operation (for example, a neuron) was not found.
The command was missing or invalid. This is a permanent error.
The neuron is dissolving or dissolved and the operation requires it to be not dissolving (that is, having a non-zero dissolve delay that is accumulating age).
The neuron is not dissolving or dissolved and the operation requires it to be dissolving (that is, having a non-zero dissolve delay with zero age that is not accumulating).
The neuron is not dissolving and not dissolved and the operation requires it to be dissolved (that is, having a dissolve delay of zero and an age of zero).
When adding or removing a hot key: the key to add was already present or the key to remove was not present or the key to add was invalid or adding another hot key would bring the total number of the maximum number of allowed hot keys per neuron.
Some canister side resource is exhausted, so this operation cannot be performed.
Some precondition for executing this method was not met (e.g. the neuron's dissolve time is too short). There could be a change in the state of the system such that the operation becomes allowed (e.g. the owner of the neuron increases its dissolve delay).
Executing this method failed for some reason external to the governance canister.
A neuron has an ongoing ledger update and thus can't be changed.
There wasn't enough funds to perform the operation.
The principal provided was invalid.
The proposal is defective in some way (e.g. title is too long). If the same proposal is submitted again without modification, it will be rejected regardless of changes in the system's state (e.g. increasing the neuron's dissolve delay will not make the proposal acceptable).
The neuron attempted to join the Neurons' Fund while already a member.
The neuron attempted to leave the Neurons' Fund but is not a member.
ICRC-1 Account. See https://github.com/dfinity/ICRC-1/tree/main/standards/ICRC-1
Used in:
This function is called "ideal" because it serves as the guideline that the Neurons' Fund will try to follow, but may deviate from in order to satisfy SNS-specific participation constraints while allocating its overall participation amount among its neurons' maturity. In contrast, The "effective" matched participation function `crate::neurons_fund::MatchedParticipationFunction` is computed *based* on this one. TODO(NNS1-1589): Until the Jira ticket gets solved, this definition needs to be synchronized with that from nns/governance/proto/ic_nns_governance/pb/v1/governance.proto.
Used in:
The encoding of the "ideal" matched participation function is defined in `crate::neurons_fund`. In the future, we could change this message to represent full abstract syntactic trees comprised of elementary mathematical operators, with literals and variables as tree leaves.
The initialisation data of the canister. Always specified on canister creation, and cannot be modified afterwards. If the initialization parameters are incorrect, the swap will immediately be aborted.
Used in: ,
The canister ID of the NNS governance canister. This is the only principal that can open the swap.
The canister ID of the governance canister of the SNS that this token swap pertains to.
The ledger canister of the SNS.
The ledger canister for the base token, typically ICP. The base token is typically ICP, but this assumption is not used anywhere, so, in principle, any token type can be used as base token.
Analogous to `sns_governance_canister_id`, but for the "root" canister instead of the governance canister.
If the swap is aborted, control of the canister(s) should be set to these principals. Must not be empty.
Same as SNS ledger. Must hold the same value as SNS ledger. Whether the values match is not checked. If they don't match things will break.
Same as SNS governance. Must hold the same value as SNS governance. Whether the values match is not checked. If they don't match things will break.
An optional text that swap participants should confirm before they may participate in the swap. If the field is set, its value should be plain text with at least 1 and at most 1,000 characters.
An optional set of countries that should not participate in the swap.
The minimum number of buyers that must participate for the swap to take place. Must be greater than zero.
The total number of ICP that is required for this token swap to take place. This number divided by the number of SNS tokens being offered gives the seller's reserve price for the swap, i.e., the minimum number of ICP per SNS tokens that the seller of SNS tokens is willing to accept. If this amount is not achieved, the swap will be aborted (instead of committed) when the due date/time occurs. Must be smaller than or equal to `max_icp_e8s`.
The number of ICP that is "targeted" by this token swap. If this amount is achieved with sufficient participation, the swap will be triggered immediately, without waiting for the due date (`end_timestamp_seconds`). This means that an investor knows the minimum number of SNS tokens received per invested ICP. If this amount is achieved without reaching sufficient_participation, the swap will abort without waiting for the due date. Must be at least `min_participants * min_participant_icp_e8s`
The total number of ICP that is required to be "directly contributed" for this token swap to take place. This number divided by the number of SNS tokens being offered gives the seller's reserve price for the swap, i.e., the minimum number of ICP per SNS tokens that the seller of SNS tokens is willing to accept. If this amount is not achieved, the swap will be aborted (instead of committed) when the due date/time occurs. Must be smaller than or equal to `max_icp_e8s`.
The number of ICP that is "targeted" by this token swap. If this amount is achieved with sufficient participation, the swap will be triggered immediately, without waiting for the due date (`end_timestamp_seconds`). This means that an investor knows the minimum number of SNS tokens received per invested ICP. If this amount is achieved without reaching sufficient_participation, the swap will abort without waiting for the due date. Must be at least `min_participants * min_participant_icp_e8s`.
The minimum amount of ICP that each buyer must contribute to participate. Must be greater than zero.
The maximum amount of ICP that each buyer can contribute. Must be greater than or equal to `min_participant_icp_e8s` and less than or equal to `max_icp_e8s`. Can effectively be disabled by setting it to `max_icp_e8s`.
The date/time when the swap should start.
The date/time when the swap is due, i.e., it will automatically end and commit or abort depending on whether the parameters have been fulfilled.
The number of tokens (of `init.sns_ledger_canister_id`) that are being offered. The tokens are held in escrow for the SNS governance canister. Invariant for the OPEN state: ```text state.sns_token_e8s <= token_ledger.balance_of(<swap-canister>) ```
The construction parameters for the basket of neurons created for all investors in the decentralization swap. Each investor, whether via the Neurons' Fund or direct, will receive `count` Neurons with increasing dissolve delays. The total number of Tokens swapped for by the investor will be evenly distributed across the basket. This is effectively a vesting schedule to ensure there is a gradual release of SNS Tokens available to all investors instead of being liquid immediately. See `NeuronBasketConstructionParameters` for more details on how the basket is configured.
The ID of the NNS proposal submitted to launch this SNS decentralization swap.
The Neurons' Fund participants of this SNS decentralization swap.
Controls whether swap finalization should be attempted automatically in the canister heartbeat. If set to false, `finalize_swap` must be called manually. Note: it is safe to call `finalize_swap` multiple times (regardless of the value of this field).
Constraints for the Neurons' Fund participation in this swap.
Whether Neurons' Fund participation is requested.
Lifecycle states of the swap canister. The details of their meanings are provided in the documentation of the `Swap` message.
Used in: , ,
The canister is incorrectly configured. Not a real lifecycle state.
In PENDING state, the canister is correctly initialized. Once SNS tokens have been transferred to the swap canister's account on the SNS ledger, a call to `open` with valid parameters will start the swap.
In ADOPTED state, the proposal to start the decentralization swap has been adopted, and the swap will be automatically opened after a delay. In the legacy (non-one-proposal) flow, the swap delay is specified by params.sale_delay_seconds. In the one-proposal flow, the swap delay is specified by `init.swap_start_timestamp_seconds`.
In OPEN state, prospective buyers can register for the token swap. The swap will be committed when the target (max) ICP has been reached or the swap's due date/time occurs, whichever happens first.
In COMMITTED state the token price has been determined; on a call to finalize`, buyers receive their SNS neurons and the SNS governance canister receives the ICP.
In ABORTED state the token swap has been aborted, e.g., because the due date/time occurred before the minimum (reserve) amount of ICP has been retrieved. On a call to `finalize`, participants get their ICP refunded.
Some Neurons' Fund neurons might be too small, and some might be too large to participate in a given SNS swap. This causes the need to adjust Neurons' Fund participation from an "ideal" amount to an "effective" amount. * The ideal-participation of the Neurons' Fund refers to the value dictated by some curve that specifies how direct contributions should be matched with Neurons' Fund maturity. * The effective-participation of the Neurons' Fund refers to the value that the NNS Governance can actually allocate, given (1) the configuration of the Neurons' Fund at the time of execution of the corresponding CreateServiceNervousSystem proposal and (2) the amount of direct participation. This structure represents the coefficients of a linear transformation used for mapping the Neurons' Fund ideal-participation to effective-participation on a given linear (semi-open) interval. Say we have the following function for matching direct participants' contributions: `f: ICP e8s -> ICP e8s`; then the *ideal* Neuron's Fund participation amount corresponding to the direct participation of `x` ICP e8s is `f(x)`, while the Neuron's Fund *effective* participation amount is: ``` g(x) = (c.slope_numerator / c.slope_denominator) * f(x) + c.intercept ``` where `c: LinearScalingCoefficient` with `c.from_direct_participation_icp_e8s <= x < c.to_direct_participation_icp_e8s`. Note that we represent the slope as a rational number (as opposed to floating point), enabling equality comparison between two instances of this structure.
Used in:
(Included) lower bound on the amount of direct participation (in ICP e8s) at which these coefficients apply.
(Excluded) upper bound on the amount of direct participation (in ICP e8s) at which these coefficients apply.
Numerator or the slope of the linear transformation.
Denominator or the slope of the linear transformation.
Intercept of the linear transformation (in ICP e8s).
Request struct for the method `list_community_fund_participants`.
The maximum number of elements that will be in the response. This is capped at 10_000.
Skip the first `offset` elements when constructing the response
Response struct for the method `list_community_fund_participants`.
Request struct for the method `list_direct_participants`. This method paginates over all direct participants in the decentralization swap. Direct participants are participants who did not participate via the Neurons' Fund.
The limit of the number of Participants returned in each page, in range [0, 30,000]. If no value, or a value outside of this range is requested, 30,000 will be used.
Skip the first `offset` elements when constructing the response.
Response struct for the method `list_direct_participants`.
The list of Participants returned from the invocation of `list_direct_participants`. The list is a page of all the buyers in the Swap canister at the time of the method call. The size of the page is equal to either: - the max page size (30,000), - the corresponding `ListDirectParticipantsRequest.limit`, - the remaining Participants, if there are fewer than `limit` participants left. Pagination through the entire list of participants is complete if len(participants) < `ListDirectParticipantsRequest.limit`.
Request for the method `list_sns_neuron_recipes`
The maximum number of elements that will be in the response. This is capped at 10_000.
Skip the first `offset` elements when constructing the response
Response for the method `list_sns_neuron_recipes`
The construction parameters for the basket of neurons created for all investors in the decentralization swap.
Used in: ,
The number of neurons each investor will receive after the decentralization swap. The total tokens swapped for will be evenly distributed across the `count` neurons.
The amount of additional time it takes for the next neuron to dissolve.
The id of a specific neuron, which equals the neuron's subaccount on the ledger canister (the account that holds the neuron's staked tokens).
Used in:
Represents multiple Neurons' Fund participants.
Used in:
Constraints for the Neurons' Fund participation in an SNS swap.
Used in:
The Neurons' Fund will not participate in this swap unless the direct contributions reach this threshold (in ICP e8s).
Maximum amount (in ICP e8s) of contributions from the Neurons' Fund to this swap.
List of intervals in which the given linear coefficients apply for scaling the ideal Neurons' Fund participation amount (down) to the effective Neurons' Fund participation amount.
The function used in the implementation of Matched Funding for mapping amounts of direct participation to "ideal" Neurons' Fund participation amounts. The value needs to be adjusted to a potentially smaller value due to SNS-specific participation constraints and the configuration of the Neurons' Fund at the time of the CreateServiceNervousSystem proposal execution.
Request struct for the method `new_sale_ticket`
The user-set amount of the ticket in ICP e8s
The subaccount of the caller to be used for the ticket
Response struct for the method `new_sale_ticket`
Request was not successful, and no ticket was created.
Used in:
When `error_type` is `INVALID_USER_AMOUNT` then this field describes the minimum and maximum amounts.
When `error_type` is `TICKET_EXISTS` then this field contains the ticket that already exists.
Used in:
Used in:
There is already an open ticket associated with the caller. When this is the `error_type`, then the field existing_ticket is set and contains the ticket itself.
The amount sent by the user is not within the Swap parameters. When this is the `error_type`, then the field invalid_user_amount is set and describes minimum and maximum amounts.
The specified subaccount is not a valid subaccount (length != 32 bytes).
The specified principal is forbidden from creating tickets.
Request was completed successfully.
Used in:
The created ticket.
Request struct for the method `notify_payment_failure`
(message has no fields)
Response for the method `notify_payment_failure` Returns the ticket if a ticket was found for the caller and the ticket was removed successfully. Returns None if no ticket was found for the caller.
The parameters of the swap.
Neurons' Fund participation.
The ID of the proposal whose execution consists of calling this method.
(message has no fields)
The parameters of the swap, provided in the call to `open`. Cannot be modified after the call to `open`.
Used in: , , ,
The minimum number of buyers that must participate for the swap to take place. Must be greater than zero.
The total number of ICP that is required for this token swap to take place. This number divided by the number of SNS tokens being offered gives the seller's reserve price for the swap, i.e., the minimum number of ICP per SNS tokens that the seller of SNS tokens is willing to accept. If this amount is not achieved, the swap will be aborted (instead of committed) when the due date/time occurs. Must be smaller than or equal to `max_icp_e8s`.
The number of ICP that is "targeted" by this token swap. If this amount is achieved with sufficient participation, the swap will be triggered immediately, without waiting for the due date (`end_timestamp_seconds`). This means that an investor knows the minimum number of SNS tokens received per invested ICP. If this amount is achieved without reaching sufficient_participation, the swap will abort without waiting for the due date. Must be at least `min_participants * min_participant_icp_e8s`.
The total number of ICP that is required for this token swap to take place. This number divided by the number of SNS tokens being offered gives the seller's reserve price for the swap, i.e., the minimum number of ICP per SNS tokens that the seller of SNS tokens is willing to accept. If this amount is not achieved, the swap will be aborted (instead of committed) when the due date/time occurs. Must be smaller than or equal to `max_icp_e8s`.
The number of ICP that is "targeted" by this token swap. If this amount is achieved with sufficient participation, the swap will be triggered immediately, without waiting for the due date (`end_timestamp_seconds`). This means that an investor knows the minimum number of SNS tokens received per invested ICP. If this amount is achieved without reaching sufficient_participation, the swap will abort without waiting for the due date. Must be at least `min_participants * min_participant_icp_e8s`.
The minimum amount of ICP that each buyer must contribute to participate. Must be greater than zero.
The maximum amount of ICP that each buyer can contribute. Must be greater than or equal to `min_participant_icp_e8s` and less than or equal to `max_icp_e8s`. Can effectively be disabled by setting it to `max_icp_e8s`.
The date/time when the swap is due, i.e., it will automatically end and commit or abort depending on whether the parameters have been fulfilled.
The number of tokens (of `init.sns_ledger_canister_id`) that are being offered. The tokens are held in escrow for the SNS governance canister. Invariant for the OPEN state: ```text state.sns_token_e8s <= token_ledger.balance_of(<swap-canister>) ```
The construction parameters for the basket of neurons created for all investors in the decentralization swap. Each investor, whether via the Neurons' Fund or direct, will receive `count` Neurons with increasing dissolve delays. The total number of Tokens swapped for by the investor will be evenly distributed across the basket. This is effectively a vesting schedule to ensure there is a gradual release of SNS Tokens available to all investors instead of being liquid immediately. See `NeuronBasketConstructionParameters` for more details on how the basket is configured.
An optional delay, so that the actual swap does not get opened immediately after the adoption of the swap proposal.
A direct Participant in the decentralization swap.
Used in:
The PrincipalId of the participant.
The BuyerState of the participant, which includes the amount of participation in e8s of a Token, and the transfer status of those tokens.
Informs the swap canister that a buyer has sent funds to participate in the swap. Only in lifecycle state `open`.
If not specified, the caller is used.
To accept the swap participation confirmation, a participant should send the confirmation text via refresh_buyer_tokens, matching the text set during SNS initialization.
Request struct for the method restore_dapp_controllers.
(message has no fields)
Response of the method restore_dapp_controllers. Analogous to Rust type Result<SetDappControllersResponse, CanisterCallError>.
TODO(NNS1-1589): Uncomment. ic_sns_root.pb.v1.
Analogous to Rust type Result<SetDappControllersResponse, CanisterCallError>.
Used in:
TODO(NNS1-1589): Uncomment. ic_sns_root.pb.v1.
Change control of the listed canisters to the listed principal id. Copy of the type in root.proto. TODO(NNS1-1589)
Used in:
Used in: ,
Used in:
Analogous to Rust type Result<SetModeResponse, CanisterCallError>.
Used in:
Used in:
(message has no fields)
Used in:
Duration must be between 1 and 90 days. The TimeWindow's end time but be greater than or equal to the TimeWindow's start time.
Response if setting the open time window succeeded.
(message has no fields)
Copied from nns governance.proto.
The caller's principal ID must match the value in the target_swap_canister_id field in the proposal (more precisely, in the OpenSnsTokenSwap).
Each of the possibilities here corresponds to one of two ways that a swap can terminate. See also sns_swap_pb::Lifecycle::is_terminal.
When this happens, maturity needs to be restored to Neurons' Fund neurons. The amounts to be refunded can be found in the ProposalData's `cf_participants` field.
Used in:
(message has no fields)
When this happens, ICP needs to be minted, and sent to the SNS governance canister's main account on the ICP Ledger. As with Aborted, the amount of ICP that needs to be minted can be deduced from the ProposalData's cf_participants field.
Used in:
This is where the minted ICP will be sent. In principal, this could be fetched using the swap canister's get_state method.
Total amount of contributions from direct swap participants.
Total amount of contributions from the Neuron's Fund. TODO[NNS1-2570]: Ensure this field is set.
Used in:
Used in:
Can be blank.
Request to settle the Neurons' Fund participation in this SNS Swap. When a swap ends, the Swap canister notifies the Neurons' Fund of the swap's ultimate result, which can be either `Committed` or `Aborted`. Note that currently, the Neurons' Fund is managed by the NNS Governance canister. * If the result is `Committed`: - Neurons' Fund computes the "effective" participation amount for each of its neurons (as per the Matched Funding rules). This computation is based on the total direct participation amount, which is thus a field of `Committed`. - Neurons' Fund converts the "effective" amount of maturity into ICP by: - Requesting the ICP Ledger to mint an appropriate amount of ICP tokens and sending them to the SNS treasury. - Refunding whatever maturity is left over (the maximum possible maturity is reserved by the Neurons' Fund before the swap begins). - Neurons' Fund returns the Neurons' Fund participants back to the Swap canister (see SettleNeuronsFundParticipationResponse). - The Swap canister then creates SNS neurons for the Neurons' Fund participants. * If the result is Aborted, the Neurons' Fund is refunded for all maturity reserved for this SNS. This design assumes trust between the Neurons' Fund and the SNS Swap canisters. In the one hand, the Swap trusts that the Neurons' Fund sends the correct amount of ICP to the SNS treasury, and that the Neurons' Fund allocates its participants following the Matched Funding rules. On the other hand, the Neurons' Fund trusts that the Swap will indeed create appropriate SNS neurons for the Neurons' Fund participants. The justification for this trust assumption is as follows. The Neurons' Fund can be trusted as it is controlled by the NNS. The SNS Swap can be trusted as it is (1) deployed by SNS-W, which is also part of the NNS and (2) upgraded via an NNS proposal (unlike all other SNS canisters). This request may be submitted only by the Swap canister of an SNS instance created by a CreateServiceNervousSystem proposal. TODO(NNS1-1589): Until the Jira ticket gets solved, changes here need to be manually propagated to (sns) swap.proto.
Proposal ID of the CreateServiceNervousSystem proposal that created this SNS instance.
Each of the possibilities here corresponds to one of two ways that a swap can terminate. See also sns_swap_pb::Lifecycle::is_terminal.
When this happens, all priorly reserved maturity for this SNS instance needs to be restored to the Neurons' Fund neurons.
Used in:
(message has no fields)
When this happens, the NNS Governance needs to do several things: (1) Compute the effective amount of ICP per neuron of the Neurons' Fund as a function of `total_direct_participation_icp_e8s`. The overall Neurons' Fund participation should equal `total_neurons_fund_contribution_icp_e8s`. (2) Mint (via the ICP Ledger) and sent to the SNS governance the amount of `total_neurons_fund_contribution_icp_e8s`. (3) Respond to this request with `SettleNeuronsFundParticipationResponse`, providing the set of `NeuronsFundParticipant`s with the effective amount of ICP per neuron, as computed in step (1). (4) Refund each neuron of the Neurons' Fund with (reserved - effective) amount of ICP. Effective amounts depend on `total_direct_participation_icp_e8s` and the participation limits of a particular SNS instance, namely, each participation must be between `min_participant_icp_e8s` and `max_participant_icp_e8s`. - If a neuron of the Neurons' Fund has less than `min_participant_icp_e8s` worth of maturity, then it is ineligible to participate. - If a neuron of the Neurons' Fund has more than `max_participant_icp_e8s` worth of maturity, then its participation amount is limited to `max_participant_icp_e8s`. Reserved amounts are computed as the minimal upper bound on the effective amounts, i.e., when the value `total_direct_participation_icp_e8s` reaches its theoretical maximum.
Used in:
This is where the minted ICP will be sent.
Total amount of participation from direct swap participants.
Total amount of participation from the Neurons' Fund. TODO[NNS1-2570]: Ensure this field is set.
Handling the Neurons' Fund and transferring some of its maturity to an SNS treasury is thus the responsibility of the NNS Governance. When a swap succeeds, a Swap canister should send a `settle_neurons_fund_participation` request to the NNS Governance, specifying its `result` field as `committed`. The NNS Governance then computes the ultimate distribution of maturity in the Neurons' Fund. However, this distribution also needs to be made available to the SNS Swap that will use this information to create SNS neurons of an appropriate size for each Neurons' Fund (as well as direct) participant. That is why in the `committed` case, the NNS Governance should populate the `neurons_fund_participants` field, while in the `aborted` case it should be empty. TODO(NNS1-1589): Until the Jira ticket gets solved, changes here need to be manually propagated to (sns) swap.proto.
Represents one NNS neuron from the Neurons' Fund participating in this swap.
Used in:
The NNS neuron ID of the participating neuron.
The amount of Neurons' Fund participation associated with this neuron.
The principal that can vote on behalf of this neuron.
Whether the amount maturity amount of Neurons' Fund participation associated with this neuron has been capped to reflect the maximum participation amount for this SNS swap.
Request was completed successfully.
Used in:
The result from settling the neurons' fund participation in finalization.
Used in:
The failure branch of the result. This message can be set for a number of reasons not limited to - invalid state - replica errors - canister errors While some of these errors are transient and can immediately retried, others require manual intervention. The error messages and logs of the canister should provide enough context to debug.
Used in:
The successful branch of the result. On subsequent attempts to settle neurons fund participation (for example: due to some later stage of finalization failing and a manual retry is invoked), this branch will be set with the results of the original successful attempt.
Used in:
Used in: ,
Attributes of the Neuron to be created from the SnsNeuronRecipe
The status of the SnsNeuronRecipe's creation within SNS Governance. This field is used as a journal between calls of `finalize`.
The various statuses of creation that a SnsNeuronRecipe can have in an SNS.
Used in:
Unused, here for PB lint purposes.
The Neuron is pending creation and can be claimed in SNS Governance.
The Neuron has been created successfully in SNS Governance.
The Neuron has previously failed to be created in SNS Governance, but can be retried in the future.
The Neuron is invalid and was not created in SNS Governance. This neuron cannot be retried without manual intervention to update its `NeuronParameters`.
Attributes of the Neuron to be created from the SnsNeuronRecipe
Used in:
The memo to be used when calculating the Neuron's staking account in the SNS Ledger. See `nervous_system_common::compute_neuron_staking_subaccount`. The memo is used along with the a principal_id of the "controller" of the neuron. In the case of the decentralization sale, that will either be the PrincipalId of NNS Governance canister for Neurons' Fund investors, or the PrincipalId of the direct investor.
The dissolve delay in seconds that the Neuron will be created with.
The list of NeuronIds that the created Neuron will follow on all SNS proposal actions known to governance at the time. Additional followees and following relations can be added after neuron creation. TODO[NNS1-1589] Due to the dependency cycle, the `swap` canister's protobuf cannot directly depend on SNS Governance NeuronId type. The followees NeuronId's are of a duplicated type, which is converted to SNS governance NeuronId at the time. of claiming.
The `swap` canister smart contract is used to perform a type of single-price auction (SNS/ICP) of one token type SNS for another token type ICP (this is typically ICP, but can be treated as a variable) at a specific date/time in the future. Such a single-price auction is typically used to decentralize an SNS, i.e., to ensure that a sufficient number of governance tokens of the SNS are distributed among different participants. State (lifecycle) diagram for the swap canister's state. ```text sufficient_participation && (swap_due || icp_target_reached) PENDING -------------------> ADOPTED ---------------------> OPEN -----------------------------------------> COMMITTED Swap receives a request The opening delay | | from NNS governance to has elapsed | not sufficient_participation | schedule opening | && (swap_due || icp_target_reached) | v v ABORTED ---------------------------------------> <DELETED> ``` Here `sufficient_participation` means that the minimum number of participants `min_participants` has been reached, each contributing between `min_participant_icp_e8s` and `max_participant_icp_e8s`, and their total contributions add up to at least `min_icp_e8s` and at most `max_icp_e8s`. `icp_target_reached` means that the total amount of ICP contributed is equal to `max_icp_e8s`. (The total amount of ICP contributed should never be greater than `max_icp_e8s`.) The dramatis personae of the `swap` canister are as follows: - The swap canister itself. - The NNS governance canister - which is the only principal that can open the swap. - The governance canister of the SNS to be decentralized. - The ledger canister of the SNS, i.e., the ledger of the token type being sold. - The ICP ledger canister, or more generally of the base currency of the auction. - The root canister of the SNS to control aspects of the SNS not controlled by the SNS governance canister. When the swap canister is initialized, it must be configured with the canister IDs of the other participant canisters. The next step is to provide SNS tokens for the swap. This normally happens when the canister is in the PENDING state, and the amount is validated in the call to `open`. The request to open the swap has to originate from the NNS governance canister. The request specifies the parameters of the swap, i.e., the date/time at which the token swap will take place, the minimal number of participants, the minimum number of base tokens (ICP) of each participant, as well as the minimum and maximum number (reserve and target) of base tokens (ICP) of the swap. Step 0. The canister is created, specifying the initialization parameters, which are henceforth fixed for the lifetime of the canister. Step 1 (State PENDING). The swap canister is loaded with the right amount of SNS tokens. A call to `open` will then transition the canister to the OPEN state. Step 2a. (State ADOPTED). The field `params` is received as an argument to the call to `open` and is henceforth immutable. The amount of SNS token is verified against the SNS ledger. The swap will be opened after an optional delay. The transition to OPEN happens automatically (on the canister heartbeat) when the delay elapses. Step 2a. (State OPEN). The delay has elapsed and the swap is open for participants who can enter into the auction with a number of ICP tokens until either the target amount has been reached or the auction is due, i.e., the date/time of the auction has been reached. The transition to COMMITTED or ABORTED happens automatically (on the canister heartbeat) when the necessary conditions are fulfilled. Step 3a. (State COMMITTED). Tokens are allocated to participants at a single clearing price, i.e., the number of SNS tokens being offered divided by the total number of ICP tokens contributed to the swap. In this state, a call to `finalize` will create SNS neurons for each participant and transfer ICP to the SNS governance canister. The call to `finalize` does not happen automatically (i.e., on the canister heartbeat) so that there is a caller to respond to with potential errors. Step 3b. (State ABORTED). If the parameters of the swap have not been satisfied before the due date/time, the swap is aborted and the ICP tokens transferred back to their respective owners. The swap can also be aborted early if it is determined that the swap cannot possibly succeed, e.g., because the ICP ceiling has been reached and the minimum number of participants has not been. The `swap` canister can be deleted when all tokens registered with the `swap` canister have been disbursed to their rightful owners. The logic of this canister is based on the following principles. * Message fields are never removed. * Integer and enum fields can only have their values increase (with one exception, viz., the timestamp field for the start of a transfer is reset if the transfer fails). Data flow for the Neurons' Fund. - A SNS is created. - Proposal to open a decentralization swap for the SNS is submitted to the NNS. - ProposalToOpenDecentralizationSale - The Neurons' Fund investment amount - The parameters of the decentralization swap (`Params`). - Call to open swap: - Parameters - Neurons' Fund investments - NNS Proposal ID of the NNS proposal to open the swap. - On accept of proposal to open decentralization swap: - Compute the maturity contribution of each Neurons' Fund neuron and deduct this amount from the Neurons' Fund neuron. - The swap is informed about the corresponding amount of ICP (`CfParticipant`) in the call to open. - Call back to NNS governance after the swap is committed or aborted: - On committed swap: - Ask the NNS to mint the right amount of ICP for the SNS corresponding to the Neurons' Fund investment (the NNS governance canister keeps track of the total). - On aborted swap: - Send the information about Neurons' Fund participants (`CfParticipant`) back to NNS governance which will return it to the corresponding neurons. Assign the control of the dapp (now under the SNS control) back to the specified principals. - On reject of proposal to open decentralization swap: - Assign the control of the dapp (now under the SNS control) back to the specified principals.
Used in:
The current lifecycle of the swap.
Specified on creation. That is, always specified and immutable.
Specified in the transition from PENDING to OPEN and immutable thereafter.
Neurons' Fund participation. Specified in the transition from PENDING to OPEN and immutable thereafter.
Empty in the PENDING state. In the OPEN state, new buyers can be added and existing buyers can increase their bids. In the COMMITTED and ABORTED states, the amount cannot be modified, and the transfer timestamps are filled in. The key is the textual representation of the buyer's principal and the value represents the bid.
When the swap is committed, this field is initialized according to the outcome of the swap.
Gets set to whatever value is in the corresponding field of OpenRequest (that field is required at the application level).
A lock stored in Swap state. If set to true, then a finalize_swap call is in progress. In that case, new finalize_swap calls return immediately without doing any real work. The implementation of the lock should result in the lock being released when the finalize_swap method returns. If a lock is not released, upgrades of the Swap canister can release the lock in the post upgrade hook.
The timestamp for the actual opening of the swap, with an optional delay (specified via params.sale_delay_seconds) after the adoption of the swap proposal. Gets set when NNS calls `open` upon the adoption of the swap proposal.
The timestamp for the actual termination of the swap (committed or aborted).
This ticket id counter keeps track of the latest ticket id. Whenever a new ticket is created this counter is incremented. It ensures that ticket ids are unique. The ticket IDs are sequential and next_ticket_id is assigned to a users new ticket upon successfully requesting a new ticket. It is incremented after a user requests a new ticket successfully.
The last time the purge_old_tickets routine was completed.
The next principal bytes that should be checked by the next running purge_old_tickets routine.
Set to true when auto-finalization is attempted. Prevents auto-finalization from being attempted more than once.
Set when auto-finalization finishes. Calling finalize manually has no effect on this parameter.
Amount of contributions from direct participants committed to this SNS so far.
Amount of contributions from the Neurons' Fund committed to this SNS so far.
Used in:
Success means that on this call to finalize, the item in the sweep succeeded.
Failure means that on this call to finalize, the item in the sweep failed but may be successful in the future.
Skipped means that on a previous call to finalize, the item in the sweep was successful.
Invalid means that on this call and all future calls to finalize, this item will not be successful, and will need intervention to succeed.
Global_failures does not map to individual items in the sweep, but number of global failures encountered in the sweep.
A device for ensuring that retrying (direct) participation does not result in multiple participation. Basically, this records a user's intent to participate BEFORE moving any funds. How this is used: before any money is sent, a user's agent must first look for an existing ticket. If one does not exist, then, a new one is created for the current participation that is now being attempted (for the first time). If there is already a ticket, then the new participation must be aborted. The surprise existence of the ticket indicates that there is a pending participation. In this case the user's agent must attempt to perform the same participation as stated in the ticket before doing anything else.
Used in: , , ,
Unique ID of the ticket
The account of the ticket. account.owner is the owner of this ticket.
The user-set amount of the ticket in ICP e8s
The timestamp of creation of this ticket
Used in:
Used in: ,
The amount in e8s equivalent that the participant committed to the Swap, which is held by the swap canister until the swap is committed or aborted.
When the transfer to refund or commit funds starts.
When the transfer to refund or commit succeeds.
The amount that was successfully transferred when swap commits or aborts (minus fees).
The fee charged when transferring from the swap canister;