On the evening of Sunday, July 9th, a neuron was reported with an impossibly large age. This indicated an issue with some logic related to aging and merging neurons.
During the investigation, the team discovered two additional issues with regard to aging.
- A dissolved neuron that originally had a positive dissolve delay was able to age in a
Dissolvedstate. This allowed for a neuron to be able to be disbursed at any time, and if
increase_dissolve_delaywas called, it would retain its age, thus giving it voting power it should not have had.
update_stake, which is called by
refresh_neuron, was not taking Neuron’s
DissolveStateinto account, which allowed a dissolved neuron to get an age bonus when stake was added to a dissolved or a dissolving neuron.
These allowed a neuron (that went from
NotDissolving to a
Dissolved state) to retain an age bonus after
refresh_neuron is called. As a result of this, a neuron was able, in these circumstances, to get more voting power than is justified based on the time its stake was in a NotDissolving state with a positive dissolve delay.
This constituted a security risk to the fair governance of the NNS.
The solution to the two problems is as follows:
- No longer use the timestamp in
WhenDissolvedTimestampSeconds(ts)to set the
increase_dissolve_delay, but instead to set it to the current time (as done, e.g., when transitioning from other equivalently dissolved neuron states to “NotDissolving”).
- Check the dissolve state of the neuron in
update_stake, and set
u64::MAXwhen the neuron is in a
Link to proposal: Proposal: 123485 - ICP Dashboard