Feature request: Expose Maturity-Modulation Payout Estimate via New estimated_icp_payout_e8s Neuron Field

When you spawn maturity on an SNS and NNS neuron, it is subject to maturity modulation. The conversion from maturity to ICP (or SNS tokens) is ±5% and is based on the 30-day moving average ICP/Cycles conversion rate. The purpose of this feature is laid out in the wiki as:

The modulation function gives an incentive for users to disburse maturity when the ICP/Cycles conversion rate has been increasing over time and to hold back when the ICP has been decreasing recently.

The problem, is that the data the user needs in order for them to make an informed decision on the right time for them to spawn their maturity is not exposed anywhere on the NNS UI or the governance canister API. There is only a small chart hidden away on the ICP dashboard. Here is a screenshot of when I open the Disburse Maturity modal on one of my NNS UI SNS neurons:

It simply links to the above wiki which might appear a bit jarring to the general investor / user about how they might calculate this modulation information.

My feature request is to please add a new field on the Neuron object so that UI’s and canisters can use it to give an estimate on the maturity received after the 7 day spawning period. The new field (or fields) can work something like this:

Field name   : estimated_icp_payout_e8s
Field type   : Nat64
Refresh      : once per UTC day, right after the maturity-modulation update
Definition   : maturity_e8s × ( 1 + (w2 + w3 + w4) / 4 )

and

Field name   : partial_modulation_bps
Field type   : Int32
Refresh      : once per UTC day, right after the maturity-modulation update
Definition   : 10000 × ( (w2 + w3 + w4) / 4 )

The last week (w1) can only shift the final rate by ±1.25 %. The preview already captures up to 3.75 % of any positive modulation, so users can see most of the potential gain before they decide to spawn.

Benefits of this is that I can start providing some maturity modulation optimisation features in canisters without calling a bunch of different API’s. Users on the NNS UI can make some informed maturity spawning decisions. I think this can benefit everyone (and even the ICP tokenomics) if the information is exposed in a helpful way for both canisters and UI’s. Right now there is no reason for the incentive to play out as intended by the design - because the information is not readily available to users and canisters in a clear way.

I’ll leave the exact implementation details to the team, but essentially getting this information onto each Neuron object is what I need. Tagging a few folks for feedback and thoughts on this, in case I missed something.

@bjoernek @jasonzhu @lara

7 Likes

Yes please, this would be great to optimise the returns of cICP, and any automated Neuron wrapper.

1 Like

Hi both,

thanks for the feedback!
I am not sure yet if it is the best solution to put that info in the neuron and update it often or if this could rather be something that is just collected when a user calls the API and returned. But you’re right, we can check that when we get to it.

We are actually looking into a similar question regarding how such information can be made more visible on the NNS dapp.
I suggest that we first gather a bit more information where we want to go there as we could then maybe cover both use cases under one solution (e.g., one API).

1 Like

For me, it would be more beneficial if the information is attached to each neuron - even if it’s the same (partial_bps solution) across the neurons. However, I realise that only works if it can be just collected at time of get_neuron.

Thanks for the response Lara, looking forward to hearing more.

Right, but I wonder if we could just populate the field and return it in get_neuron right when someone calls get_neuron (rather than regularly updating the information in the internal information about a neuron). This would still save space!

Thanks for the response Lara, looking forward to hearing more.

You’re welcome!

Based on my scans through the gov code, it looks like it’s stored in the heap, and updated in the periodic tasks. So I think we can do it easily and just populate a new field.