Context
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.
Problem
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
Dissolved
state. This allowed for a neuron to be able to be disbursed at any time, and ifincrease_dissolve_delay
was called, it would retain its age, thus giving it voting power it should not have had. update_stake
, which is called byrefresh_neuron
, was not taking Neuron’sDissolveState
into 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.
Solution
The solution to the two problems is as follows:
- No longer use the timestamp in
WhenDissolvedTimestampSeconds(ts)
to set theaging_since_timestamp_seconds
field duringincrease_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 setaging_since_timestamp_seconds
tou64::MAX
when the neuron is in aWhenDissolvedTimestampSeconds
state.
Link to proposal: Proposal: 123485 - ICP Dashboard