Maintaining SNS Proposal Ballot Records

For a Decentralized Autonomous Organization, the public voting record fills essentially the same central role as the token transaction archive does for a cryptocurrency token. It is the artifact that imbues the whole system with trust, via its verifiability.

The more important and valuable the token, the more important it is that its entire transaction history can be verified. The Bitcoin block wars were fought over this principle, and the “small blockers” won, maintaining that BTC would be constrained in how valuable it could become if the full transaction chain could not be independently verified with reasonable means.

Correspondingly, for a DAO to maintain its credibility and value its entire vote record must be independently verifiable.

Currently, the SNS voting record is destroyed when rewards are distributed. While it can be argued that the votes have been tallied correctly using publicly verifiable code, and thus the overall integrity of the voting chain can be verified, the voting history can no longer be indexed for double-checking the integrity of the votes for a given user.

In all, the voting record of an SNS is today not really independently verifiable with reasonable means, and that is a serious problem in that it constrains how credible and valuable an SNS can become.

It is not a lot of data we’re talking about. The full voting history for a proposal, until it is wiped, is available via a call to get_proposal, which can only return responses smaller than 4MB, so presumably we’re mostly talking about sizes under 4MB required per proposal to save the full voting history.

Note that by saving all the votes for each proposal, also saving the votes for each neuron becomes redundant, since this information can relatively easily be indexed from the voting history in the proposals.

I believe this issue is of general concern, but for the Sneed DAO it is of central importance, because to enable non-inflationary voting rewards (we don’t mint rewards) we need to see the voting history to be able to distribute rewards from the DAO’s earned revenue.

Not having full voting history retained is turning into a blocking issue for the DAO, preventing us from implementing a rewards distribution system with the robustness expected from blockchain applications.

It can be noted that when planning and implementing our solution, work that was ongoing for over a year and had reached the beta stage, the Sneed DAO votes were in fact kept in the proposals. Calling get_proposal on Sneed proposals up to prop #126 will return full ballot histories. We were not even aware that this was a peculiarity, and that other SNSes did not see their full voting history. We thought our assumption that a public DAO on the blockchain would retain its full voting history would be rock solid.

We have since puzzled together that the following must have happened. The votes are cleared when rewards are minted and distributed for a proposal. Sneed, unlike most SNSes, has no (minted) rewards, so up until proposal #126, this code was not invoked for Sneed DAO, and we got to keep our vote history in the proposals.

But after proposal #126, someone must have noticed this “glitch” and fixed it - breaking the premise for Sneed’s rewards distribution system in doing so.

We propose that one of the following options to solve this be considered:

  1. Restoring the pre-proposal #126 behaviour, where votes are not cleared for SNSes with no rewards. This would solve the situation for Sneed, but not benefit other SNSes, so better would be:
  2. Allow SNSes to opt in for saving the ballots in the proposals. Yes this may cost a bit more cycles, but the SNS could opt in to bear that cost if they deem a full voting history worth it for the positive impact on their credibility.
  3. Just go ahead and store all the ballots for all the proposals. It is, frankly, what could be expected from a blockchain DAO, and at a few MB per proposal, it seems at odds with the ICP value proposition if these data sizes could not be comfortably handled.

But just in case my math is bad and size requirements for storing all the ballots for the proposals are problematic, the same approach as for the SNS token ledger could be used: ballots could be exported (as rewards are distributed, when they are currently wiped) to an archive canister (with the capacity to grow to a set of archive canisters) and then another indexer canister could tally up votes per neuron.

This would scale and allow for the kind of rigor that should be associated with a blockchain DAO, but it would presumably take a while to implement (even with Caffeine helping), and Sneed DAO needs to address this issue quickly. We thus hope that even if a more robust solution with archive and index canisters is deemed the appropriate long term solution, that one of the solutions 1,2 or 3 could be considered in the interim.

Sneed DAO remains dedicated to building the best fully community operated DAO we possibly can, and any help with rectifying this situation would mean the world to our members, who have been patiently awaiting their non-inflationary rewards for over a year.

In support of option #1 it could be noted that for SNSes with rewards, the voting record can in principle be derived from the rewards themselves, so wiping the votes there is more ok. However, when wiping the votes for an SNS with no rewards, doing so in fact destroys information irrevocably, and it could be argued that “fixing this” after proposal #126 actually introduced an information destroying bug.

Thank you for your kind and patient consideration.

For DAOs like Sneed, verifiable voting history is as critical as a transaction ledger is to a cryptocurrency. Currently, SNS wipes voting records when distributing rewards. For Sneed DAO, which distributes non-inflationary rewards, this breaks our system by destroying essential data.

Until proposal #126, Sneed retained ballots because we didn’t mint rewards. This changed, likely unintentionally, and now blocks our reward system.

We propose:

  1. Restore old behavior for SNSes without rewards.
  2. Allow opt-in to retain ballots.
  3. Retain ballots for all SNSes by default.
  4. Archive ballots to scalable canisters like the ledger system.

This data is small (~<4MB/proposal) and essential to DAO integrity. Quick action is needed to avoid long-term harm to Sneed DAO’s functionality and trust.

Thank you.

In all seriousness, I will cross post this methodology to save votes failing to create a nns wide change:

Thank you for raising this concern. I agree that it is a problem that ballot history is not stored after the end of the voting period. Even the NNS doesn’t store proposal history beyond 100 proposals. I have had many instances where I would like to see proposal history for both SNS and NNS proposals and it does seem this information should be stored indefinitely, or at least for a timespan measured in years.

Wouldn’t this require that the state (DD, Age, stake, etc) of every participating neuron is recorded? I presume voting power is deleted when the vote data is deleted. Also, voting rewards only indicate if a vote was cast, not if it was a yes or no vote, which I would think is the important part for storing ballot history.

Hi, and thank you for the support!

Yes, I do agree with you that the votes should just be kept for all the SNSes, rewards or not - and I have to admit I have not fully thought through (or tested) working backwards from rewards to determine cast VP (since it is not a relevant option for us.) It might not even work, which would indeed add further weight to the argument that the votes should be kept. I mostly wanted to point out that even if that does work, it wouldn’t work for Sneed DAO since we have no rewards.

Hi @Snassy-icp,

Thanks for clearly describing the issue in a way that everyone can understand.

Some context:

  1. Since the beginning, the SNS framework did not guarantee that ballots would be retained forever.

  2. The change you’ve observed was proposal and adopted by the NNS about a year ago; see the Do not special case 0 voting reward rate commit here.

  3. This code had been installed onto the Sneed SNS Governance around the time proposal 126 was adopted (September 1, 2024), which also corresponds to your claim.

    May I ask, how come you’ve only noticed the change now?

  4. The above-mentioned change made it so that even SNSs that do not distribute voting rewards would ensure their proposals are ultimately processed, after which (according to the smart contract) the ballots are cleared. I’ve checked with the Governance team and can confirm that this is the intended behavior.

That being said, the team acknowledges the request to make ballots more accessible and for a longer time, which AFAIK has been voices a few times by the community already. Please note that coming up with the right solution here is not trivial, so we would have to wait until more urgent priorities that we’re currently working on are addressed before we can pick up this work.

For now, could you please clarify how the ballots data is being used by Sneed? Possibly, the problem could be mitigated by sending out more frequent requests to SNS Governance.

@Snassy-icp,

Internet Computer is not your average blockchain. It’s a new kind of computing platform — a sovereign layer that allows software to run without firewalls, databases, or Amazon Web Services.

Now, imagine a DAO — a real one. Not some janky multisig script. A fully autonomous, tamperproof governance organism, living entirely on-chain. For that to work, its lifeblood — the voting record — must be as immutable and verifiable as a Bitcoin ledger. Anything less, and we’re just LARPing decentralization.

But right now? The SNS voting history gets wiped when rewards are minted. Gone. Poof. That’s like deleting Bitcoin transactions after every halving. It breaks trust. It breaks composability. It breaks the very idea of a sovereign protocol that runs without centralized infrastructure.

And this isn’t just about ideology — it’s practical. For DAOs like Sneed that don’t mint new rewards, the ability to track votes is mission critical. Without that, they can’t distribute rewards from earned revenue. This isn’t theory — their system worked up to proposal #126. After that? Someone “fixed” it and unknowingly broke everything. That’s not fixing. That’s introducing an information-destroying bug.

We must fix this. Not in some future roadmap. Now.

There are clear paths forward:

Restore the old behavior for DAOs that don’t mint rewards. Easy fix, minimal effort.

Let DAOs opt in to store full voting history. They’ll gladly pay a few more cycles for that sweet, tamperproof transparency.

Or — and this is what a blockchain designed to replace Web2 should do — just store all ballots. Period. This is the Internet Computer, after all. If we can’t store a few MB per proposal, we might as well pack up and go home.

And for the long-term, archive canisters and indexers can handle scale. We’ve done it with ledgers. We can do it with votes. But let’s not leave DAOs like Sneed in limbo while we wait.

The Internet Computer is about trust, verifiability, permanence — software that runs forever. Let’s make sure our DAOs embody those principles. Let’s stop wiping history. Let’s start building the future of governance — on-chain, unstoppable, and open for all to verify.

But after we finish self writing internet with caffeine ai.

Hi @aterga,

Please keep in mind that making voting history more visible could lead to more voting collusion between big players as well as chances that smaller neurons could end being punished in case they vote against whales.

So while I agree that more transparency is usually desirable, this is one of the few cases where it could backfire in a big way.

Hi @aterga,

In the realm of the Internet Computer — where the self-writing internet is not a dream but a deployed reality — data is no longer transient. It lives forever through orthogonal persistence, the holy grail of decentralized computation. Here, code and state evolve as one, unshackled from traditional infrastructure, untethered from Amazon or Azure.

But eternal memory cuts both ways.

Making voting history fully visible, forever etched into enhanced orthogonal persistence, might seem like the ultimate act of transparency — and on a blockchain that governs itself, that’s usually a virtue. But in this case, we risk turning an immutable ledger into a ledger of intimidation.

Whales, empowered by perfect on-chain foresight, could begin aligning strategies in real-time. They could punish ideological deviation, silence dissent, and weaponize immutable memory. Smaller neurons, already running on lean cycles, may start self-censoring — not because the DAO told them to, but because the self-writing internet remembers everything.

And this memory doesn’t rot. It doesn’t get archived. It’s enhanced orthogonal persistence — state and logic fused in perpetuity. It’s a blessing for trustless computation, but a potential curse for democratic governance.

So while we strive for integrity in all layers — logic, consensus, memory — we must also recognize when total transparency introduces centralized pressure vectors through decentralized means.

We’re not just building dApps here — we’re architecting autonomous civilizations. Protocols that evolve without human oversight, governance that outlives its creators. The voting layer must be sacred and sovereign — and free from manipulation, even by those who would do so in the light of public verification.

Let’s proceed with care. The self-writing internet should empower its participants — not expose them to coercion cloaked in clarity.

Hi @aterga ,

Thank you for your detailed reply! It seems our observations and timelines agree, I will thus consider what happened established, thank you for your help in investigating this!

As to why we did not notice the change until now:

The votes were to be used as one component in Sneed’s sophisticated Recursive Liquidity Loop (RLL), an ambitious, automatic, trustless setup where DAO revenue circulates and is piped into an 8 year ICP Neuron, to Treasury, to Buybacks, to Burns - and, crucially, to reward voting members without having to mint any rewards, keeping the Sneed token strictly deflationary.

Building this whole setup has been an ongoing effort for over a year, and involves a close partnership with Neutrinite DAO, which supplies the Neuron Vectors for collecting maturity, Exchange Vectors for buybacks, and Splitter Vectors for revenue allocation. All of this is very cutting edge, and the supporting Vectors have only recently reached the maturity required to hook all this together.

In fall of last year, the component that will distribute a portion of the revenue (from our 8y Neuron maturity, from fees to Sneed’s LP positions, as well as revenue from ventures such as SneedLock and Swaprunner) to our voting members was ready for beta testing, and we ran a very successful beta test where Sneed DAO members were able to claim some initial rewards that were exactly proportional to their voting history up until that point. NB: This distribution component is not a Vector, and is developed entirely by Sneed.

As the beta test ran smoothly, our attention then turned to the remaining, vector based components of the RLL system. We have since been working closely with NTN to get it all up and running, and we are very pleased to say that this vector setup is now fully functional.

So the time now came to turn back to the distribution component and give it the final polishes that were needed to bring it out of beta and complete the final, central piece of the grand RLL puzzle that had been about 1.5 years in the making. However, now when testing the same things that had run so smoothly during the beta in the fall of 2024, suddenly they didn’t work at all. The investigation soon revealed the cause: all the ballots were gone from all new proposals made after our beta test had concluded.

So this is really unfortunate and concerning for us, and we would really appreciate any help in restoring the behavior to what we tested against in the fall of 2024. While we do understand the need to only make changes very carefully to the SNS voting code, as far as we can understand everything worked fine before this change to clear votes of reward-less SNSes as well, so hopefully reverting to the behavior we had before that should have limited and predictable impact.

To clarify the way ballots are being used: When Sneed DAO gets new revenue from its revenue sources (8y neuron, LP positions, dApps like SneedLock and Swaprunner), some of it is sent for distribution to voting members. This distribution component works as follows:

  1. Import any new proposals and cache them locally (ballots and all)
  2. Index the ballots in the locally cached proposals to determine every neuron’s total Voting Power cast in a given reward period
  3. Distribute available funds according to that cast VP in the period.

Once voting has ended on a proposal, it will be counted in this indexing, and should not need to be downloaded into the cache again, since the ballots should now remain stable (voting has closed).

Now, note that as long as there is a reasonably long time window between A) the voting closes, and B) The rewards are distributed (so the ballots are cleared), we will be fine. If we have a few days there to ensure we download and cache all the votes after the voting closes and before the votes are cleared, we don’t run the risk of losing any votes, but if that time window is short, we do run such a risk. It should be added that, long term, DAO members should not have to rely on trusting our cache of their votes, they should be able to see them directly in the SNS APIs, but for now this would solve our urgent issue.

Hope this helps to clarify the issue. All of Sneed DAO’s members are very grateful for all your support and help in resolving this for us, and we look so much forward to installing the final voter reward distribution piece of our Flagship RLL system!

Thank you again for your time and attention!

Hi @vavram ,

This is a very valid point you raise, and speaks in favor of allowing some configurability of ballot retention for each SNS.

In general, in democratic societies, it is a centrally important feature - not a bug - that it is impossible for a voter to verify their own vote. That is, they should be able to verify that their vote was counted, but not what they voted for.

The reason is that this removes any realistic way for a strongman to force you to vote their way, since there is no way to prove if you did or if you didn’t.

On the other hand, in economic clubs such as public companies, shareholder votes are in general not anonymous - in this context, transparency and accountability is valued higher than voter anonymity (even if there may be ways to vote anonymously.)

I believe that a setting to let each DAO decide if they are more like a democracy or more like a company is appropriate, but I do believe that for an SNS like Sneed DAO, it does make sense to take the more transparent approach, and that given traditional blockchain ethos of transparency and verifiability, a DAO should probably have to motivate why it would like to diverge from this default approach.

It could be noted here that for Sneed DAO’s purposes, we don’t actually need to know what the members voted for, just how much VP they used to vote! So longer term the door may be open for some sophisticated DAO settings (Show and keep ballots but hide what they voted for) that would allow a best-of-both-worlds compromise.

As long as the association between voting power and neuron id can be made, then collusion and threatening/punishing smaller neurons is made possible. Not sure how you can keep ballots while avoiding that, @Snassy-icp.

Sorry for being unclear.

“As long as the association between voting power and neuron id can be made, then collusion and threatening/punishing smaller neurons is made possible.”

I agree with you. That’s why I would also understand if some SNS DAOs would want to opt not to show this information at all, not even for the period of time up until rewards are distributed (the current case.)

But the thing I am focused at right now is not revealing new information, but retaining information that has been revealed, for DAOs where it does make sense to keep votes open, such as Sneed DAO.

Hey @Snassy-icp,

Thanks for writing up this issue. I agree that it imposes significant limitations on what is supposed to be a flexible framework for building DAOs. It’s a shame @aterga didn’t suggest a solution after your follow up responses.

I’ve now run into this exact same issue myself, as I’m working on launching several SNSs that have non-inflationary reward dynamics where voters are still rewarded for their participation. Something that I think may be a more robust solution to this problem (particularly given that get_proposal isn’t paginated, which is a separate blocking limitation that assumes a limited number of DAO participants), is to investigate working with the frameworks’ maturity system rather than fighting against it. Accrued maturity basically gives you a single figure that describes a neurons entitlement to rewards, which can factor in their stake, age bonus and governance participation automatically based on SNS configuration.

The only issue then is that the maturity can be spawned which leads to inflation, but I think this can be disabled.

ic/rs/sns/governance/proto/ic_sns_governance/pb/v1/governance.proto at 42413a1c7dbabc98ae3abc6124a9b96d3c0985fe · dfinity/ic

  // The principal has permission to merge the neuron's maturity into
  // the neuron's stake.
  NEURON_PERMISSION_TYPE_MERGE_MATURITY = 7;

  // The principal has permission to disburse the neuron's maturity to a
  // given ledger account.
  NEURON_PERMISSION_TYPE_DISBURSE_MATURITY = 8;

  // The principal has permission to stake the neuron's maturity.
  NEURON_PERMISSION_TYPE_STAKE_MATURITY = 9;

I believe that these 3 permissions can be configured as not granted to owners of newly staked neurons (by raising a manage_nervous_system_parameters proposal that sets neuron_claimer_permissions - ic/rs/sns/governance/proto/ic_sns_governance/pb/v1/governance.proto at 42413a1c7dbabc98ae3abc6124a9b96d3c0985fe · dfinity/ic). The same also needs to be done on neuron_grantable_permissions (to make sure nobody can later grant these permissions). In principle this should prevent the neuron owner from being able to disburse any maturity, though maturity will be accruing based on their governance participation. Periodically sampling the maturity of neurons to establish how much their maturity has grown relative to one another then gives you the proportions of revenue rewards that should be allocated to each neuron.

I’m planning to test this locally soon.

Other thoughts:

Ideally it would be good to be able to reset maturity to zero after every sample...

(to avoid having to diff against the prior sample and to keep the state tidy), but this would require a protocol principal to have the above permissions on every neuron (such that it can spawn the maturity to a burn address). I’m not aware of a way of automatically setting up an additional principal on newly claimed neurons though, and requiring every user to do this setup themselves would be more hassle than it’s worth.

For SNS DAOs that need this approach but already have users who have claimed neurons...

those owners will have permission to revoke some of their own permissions. The trouble is that the NNS dapp doesn’t expose that functionality (last time I checked anyway - cc @yhabib). However, as a one-off migration, it would be possible to instruct users to press F12 while signed into the NNS dapp and paste some JS into the dev console and execute it, which is an approach that can be used to arbitrarily alter permissions on neurons they own. The DAO would just need to ‘bless’ some JS so that users can copy it out of a motion proposal or something and consider it trusted. You could make neurons who haven’t done this exempt from rewards or something, and then only once all neurons have done it you could raise another proposal to set up maturity rewards (still non-inflationary though because nobody can disburse the maturity that’s accruing).


@yhabib, would you consider adding functionality to the NNS dapp to allow users to alter permissions/principals on their neurons?

At the moment the only thing a user can do is add a hotkey, which for SNSs is implemented as adding a principal to the neuron with permissions to vote and permission to raise proposals. Ideally a user should be able to select which permissions they assign to the principal they add. This is functionality that could be hidden until the user types CTRL + k, much like some of the other advanced features. The only permission a user should probably remain unable to allocate to another principal is NEURON_PERMISSION_TYPE_MANAGE_PRINCIPALS (this is what grants them master control over the neuron and who gets to do what with it).

Additionally, it would be extremely useful to allow users to revoke permissions on their own principal for the neuron. The reasons for this are explained above. The only permission they should be unable to revoke from their own principal is NEURON_PERMISSION_TYPE_MANAGE_PRINCIPALS (to ensure they can always undo their changes, provided the DAO itself continues to allow specific permissions as grantable).

At the moment the SNS framework is setup with a very flexible permissions system that no user can practically use, and as this thread points out, that’s a massive blocker which makes the SNS completely inflexible despite it being designed for flexibility via the permissions system.

Just an FYI - Sneedhub exposes these permissions for people who choose to hold their neurons there. (I would show a screenshot here but they are disabled: https://www.pasteboard.co/dkoG-ou1Sriq.png)

Granted, most users will hold neurons on their NNS PID and not their Sneedhub one. Sneedhub also has a solution for this but it is somewhat unsavory. The Sneedhub “SNS Jailbreak” tool will create a script that users can run from the browser console on while on the NNS site to add their Sneedhub PID as a full controller (enabling them to leverage the extra Sneedhub functionality). This is of course a bit of a scary thing to do for folks - running javascript they likely do not understand is not a safe action. You can have an LLM review it for safety concerns but it would be nice for the NNS to expose some of this functionality more directly.

In the meantime, for those of you with an iron stomach, this is the jailbreak tool: https://app.sneeddao.com/tools/sns_jailbreak

v1 of an ic-query minor slice, if anybody cares to provide feedback

# ic-query 0.26 Design: SNS Maturity Reward Evidence

## Status

- Status: planned for 0.26.0

- Last reviewed: 2026-08-02

- Scope: read-only SNS neuron permission evidence, maturity checkpoints, and

local reward deltas

## Goal

Support SNS DAOs that use Governance maturity as a non-inflationary measure of

reward entitlement. The new surface must let an operator prove whether

maturity conversion is disabled by the effective permission state, collect a

complete reward-round-aligned maturity checkpoint, and compare two checkpoints

without enumerating proposal ballots.

The slice remains reporting-only. It does not sign identities, call

`manage_neuron`, submit proposals, alter permissions, reset maturity, transfer

revenue, or generate JavaScript for execution in another application’s browser

context.

## Protocol Facts And Policy

SNS Governance currently defines these neuron permission codes:

| Code | Permission |

| —: | — |

| 0 | `Unspecified` |

| 1 | `ConfigureDissolveState` |

| 2 | `ManagePrincipals` |

| 3 | `SubmitProposal` |

| 4 | `Vote` |

| 5 | `Disburse` |

| 6 | `Split` |

| 7 | `MergeMaturity` |

| 8 | `DisburseMaturity` |

| 9 | `StakeMaturity` |

| 10 | `ManageVotingPermission` |

Codes 7, 8, and 9 are the prohibited maturity-conversion permissions for this

design. A checkpoint satisfies the global non-inflation policy only when:

- `neuron_claimer_permissions` excludes 7, 8, and 9;

- `neuron_grantable_permissions` excludes 7, 8, and 9;

- every current principal permission entry on every neuron excludes 7, 8, and

9; and

- every neuron has an empty pending maturity-disbursement collection.

The first two checks govern new claims and future grants. They do not revoke a

permission already held by a principal, so a parameter-only audit is not

sufficient for an existing SNS. The full paged neuron collection is required.

`ManagePrincipals`, `Vote`, and `SubmitProposal` are required claimer

permissions in the current Governance implementation. Whether

`ManagePrincipals` should be grantable to another principal is a separate

control-transfer policy. The report exposes that fact as a warning but does not

classify it as maturity inflation.

Governance authorizes `ChangeAutoStakeMaturity` through

`ConfigureDissolveState`, not `StakeMaturity`. Reward distribution adds new

maturity to staked maturity when auto-stake is enabled and to unstaked maturity

otherwise. The stable reward score for one neuron is therefore:

```text

reward_score_e8s_equivalent =

maturity_e8s_equivalent

+ staked_maturity_e8s_equivalent.unwrap_or(0)

```

Changing auto-stake moves future accrual between those components and does not

invalidate the combined score. A pending maturity disbursement is preserved as

separate evidence and makes the checkpoint ineligible; it is not silently

added back into the payout score.

There is no native operation that resets maturity to zero as pure accounting.

Merge, stake, and disburse operations consume or reclassify maturity and can

eventually create additional SNS-token stake or liquid supply. This design uses

immutable checkpoint deltas instead of reset behavior.

## Existing Surface And Hard Boundary

The schema-2 `SnsNeuronRow` continues to represent the fixed-size fields used

by normal bounded lists and complete neuron caches. It is not expanded with

permissions, followees, or pending disbursements, and the existing neuron cache

schema does not advance in this slice.

The reward workflow uses a separate explicit row and report because it needs

variable-size permission and pending-disbursement evidence. This preserves the

0.25 rule that ordinary `sns neuron list` and `sns neuron refresh` do not grow

their response, cache, or rendering contract implicitly.

## CLI Surface

The intended command surface is:

```bash

icq sns neuron info <id|root-principal>

icq sns reward checkpoint <id|root-principal>

icq sns reward diff <before-checkpoint.json> <after-checkpoint.json>

```

All live commands accept the existing explicit SNS source endpoint and global

mainnet network identity. Text is a human-facing summary. `–json` retains raw

permission codes, principals, maturity values, event fields, timestamps, and

policy findings.

`reward diff` is local-only. It must reject network and source-endpoint options

rather than accepting an option that appears capable of making a live call.

## Neuron Detail

`sns neuron info` calls native Governance `get_neuron` for one exact neuron id.

It preserves:

- every principal and raw permission code, with a derived current permission

name when known;

- unstaked and staked maturity;

- the auto-stake setting;

- pending maturity disbursements, including raw amount and timestamps;

- fixed-size neuron state already represented by `SnsNeuronRow`; and

- legacy and topic followees as native detail evidence.

Unknown future permission codes remain visible and receive an `unknown` label.

Missing principals and malformed ids remain typed source-data failures. The

report is live-only and does not read or write the complete neuron cache.

Including targeted discovery, one detail report makes three client queries:

one SNS-W inventory query, one selected-SNS metadata query, and one Governance

`get_neuron` query. SNS neurons are publicly readable under the current native

contract, so the built-in source remains anonymous and does not introduce

identity-file handling.

## Reward Checkpoint Collection

`sns reward checkpoint` performs this ordered collection:

1. resolve exactly one deployed SNS through targeted discovery;

2. read Governance nervous-system parameters;

3. read `get_latest_reward_event`;

4. exhaust `list_neurons` with the native maximum page size of 100;

5. read nervous-system parameters again; and

6. read `get_latest_reward_event` again.

For `N` neuron pages, this makes `N + 6` client queries including targeted

discovery. It does not call `get_proposal`, enumerate ballots, fan out with one

`get_neuron` call per row, query a ledger, or inspect transaction history.

The before and after parameter responses must agree on the claimer and

grantable permission lists. The before and after reward events must identify

the same reward round, event timestamp, and distributed amount. A mismatch is

a typed unstable-checkpoint failure; no successful checkpoint is emitted.

An optional diagnostic page cap may stop collection, but capped collection is

incomplete and cannot produce a checkpoint. Page cursors, row uniqueness, SNS

identity, and API exhaustion follow the existing complete neuron refresh

validation rules.

Each checkpoint row contains:

- neuron id and creation timestamp;

- unstaked, staked, and combined maturity;

- auto-stake state;

- every current principal permission entry;

- every pending maturity disbursement; and

- row-level policy findings.

The checkpoint summary contains the full parameter permission lists, both

bracketing reward-event responses, page and row counts, collection start and

end timestamps, aggregate maturity totals, policy finding counts, and an

overall `non_inflationary_policy_satisfied` boolean.

The report always states `point_in_time_guaranteed: false`. Stable bracketing

proves that the observed reward round and relevant global parameters did not

change during the walk. Governance exposes no collection version proving that

all neuron rows came from one instant, and principals may still change neuron

state between pages.

## Checkpoint Publication

The first slice does not add another implicit cache or overwrite the existing

complete neuron snapshot. A checkpoint is a versioned report emitted to stdout;

an operator persists JSON explicitly, for example:

```bash

icq sns reward checkpoint 1 --json > reward-checkpoint-42.json

```

This keeps history retention, filesystem naming, and backup policy visible to

the caller. A later append-only checkpoint store must define collision,

retention, and content-integrity behavior before writing beneath the shared

cache root.

## Local Reward Diff

`sns reward diff` strictly loads two current checkpoint schemas and requires

matching network, Root principal, Governance principal, and SNS identity. The

after checkpoint must have a later reward-event position than the before

checkpoint. Both checkpoints must have completed collection and satisfied the

non-inflationary policy.

Rows are joined by full neuron id. For each row:

```text

reward_delta_e8s_equivalent =

after.reward_score_e8s_equivalent

- before.reward_score_e8s_equivalent

```

The diff preserves raw integer values and reports:

- positive, zero, and negative deltas;

- neurons created after the earlier checkpoint, using zero as their earlier

score only when the timestamps support that classification;

- neurons missing from the later checkpoint;

- permission or pending-disbursement policy changes; and

- the total positive delta used as the allocation denominator.

A negative delta, unexplained missing neuron, target mismatch, policy failure,

or arithmetic overflow makes the allocation invalid. It remains visible as

typed evidence rather than being clamped to zero.

The report produces per-neuron integer numerator weights and a shared integer

denominator. It does not infer a beneficiary or transfer account. An SNS neuron

may contain several principals, and its permission list does not define one

canonical owner. A payout system must use a separately authenticated beneficiary

registry or a claim mechanism.

## Permission Remediation And Operational Sequence

For a new SNS, operators configure both claimer and grantable permission lists

without codes 7, 8, and 9 before neurons are claimed.

For an existing SNS, the safe sequence is external to `ic-query`:

1. adopt the parameter change that removes 7, 8, and 9 from future claimer and

grantable permissions;

2. have authorized users remove 7, 8, and 9 from every current principal entry

on every neuron;

3. wait for every already-pending maturity disbursement to finalize;

4. use a complete checkpoint to prove the policy and establish the baseline;

5. collect another checkpoint after a later settled reward round; and

6. use the local diff as input to an independently authorized revenue payout

process.

Changing global grantability prevents removed maturity permissions from being

granted again under the current parameters, but a later Governance proposal

can change those parameters. Every checkpoint therefore repeats the global and

per-neuron audit.

Permission removal itself is intentionally not automated here. Native

Governance permits a caller with `ManagePrincipals` to remove its own

permissions and even to remove the last permission entry, permanently locking

the neuron. An identity-aware wallet or frontend should render the exact

`RemoveNeuronPermissions` request, require informed confirmation, and protect

the last `ManagePrincipals` holder. `ic-query` reports the before and after

state only.

## Public Library Boundaries

- `SnsNeuronSource` owns one exact native detail lookup.

- `SnsRewardSource` owns nervous-system parameters, latest reward event, and

paged reward-neuron collection for one resolved SNS.

- `SnsNeuronDetailReport`, `SnsRewardCheckpointReport`,

`SnsRewardCheckpointRow`, permission and pending-disbursement DTOs, and

`SnsRewardDiffReport` remain usable without default features.

- Live builders, local checkpoint loading, and source traits remain behind

`host`.

- Report builders validate custom-source evidence with the same target,

ordering, bracketing, permission, and arithmetic rules as the built-in

adapter.

Reusable permission-code decoding belongs in the SNS report module. CLI

parsing and dispatch remain in `ic-query-cli`; network calls, report assembly,

local checkpoint reads, and rendering remain in the SNS report owners.

## Validation And Tests

Focused fixture tests cover:

- every known permission code and an unknown future code;

- prohibited claimer, grantable, and current-principal permissions;

- pending maturity disbursements;

- auto-staked and unstaked combined maturity;

- reward-event and parameter changes across a paged walk;

- duplicate, overlapping, malformed, capped, and non-exhausted pages;

- valid new-neuron deltas, negative deltas, and missing neurons;

- checkpoint schema, target, network, and event-order mismatches;

- exact integer aggregate and denominator arithmetic; and

- local-only diff behavior with no live source calls.

Unit tests use fixture sources and temporary files. No test depends on a live

SNS, an identity, a signed update, or exact full human-readable output unless

that text is the command contract.

## Non-Goals

- signed `manage_neuron` calls or identity storage;

- proposal submission or parameter mutation;

- browser-console jailbreak scripts;

- maturity reset, burn, merge, stake, or disbursement;

- treasury transfers or automatic payouts;

- beneficiary inference from neuron permissions;

- proposal-ballot collection; and

- a claim or Merkle-distribution canister.

## Official Interfaces

- [SNS Governance Candid interface](https://github.com/dfinity/ic/blob/master/rs/sns/governance/canister/governance.did)

- [SNS Governance neuron and permission protobuf](https://github.com/dfinity/ic/blob/master/rs/sns/governance/proto/ic_sns_governance/pb/v1/governance.proto)

- [SNS Governance implementation](https://github.com/dfinity/ic/blob/master/rs/sns/governance/src/governance.rs)

- [SNS settings](https://docs.internetcomputer.org/references/sns-settings/)

- [SNS neurons](https://learn.internetcomputer.org/hc/en-us/articles/34084687583252-Neurons)

Having looked into this further, it seems to be possible to push back the settlement of proposals arbitrarily by increasing round_duration_seconds to a value that’s higher than inital_voting_period_seconds, then the ballot data should be retained after the proposals voting period (until round_duration_seconds elapses). I believe this directly addresses the OPs issue. ← this approach is imperfect and has issues that are discussed in the thread linked in the post below

That being said, there are many other reasons why configuring permissions on SNS neurons would be very helpful and unlock a lot of latent functionality. As @XanderBrendon mentions, it really comes down to the UI through which a users has chosen to stake. I think the NNS dapp should support users in adjusting permissions on their neurons.

Just came across this which is very related:

SNS Governance feature proposal: show the neuron reward portion of each reward event so that SNSs can pay stakeholders in proportion to the voting participation - Developers - Internet Computer Developer Forum