Skip to content

Commit

Permalink
Sync the SNS rewards status logic calculation with the backend (#5766)
Browse files Browse the repository at this point in the history
# Motivation

The logic for SNS reward status calculation is outdated on the front
end. Although we haven’t received error reports recently, after
discussing with a backend developer, it was suggested to sync the logic.


Presumably, the backend fixes led to the related code changes:

**1. SNS list_proposals reward status filtering does not exclude old
SNS-1 proposals.**

There is a new field is reward_event_end_timestamp_seconds. Older
proposals do not populate this field, since they predate it.
Currently, the correct way to determine whether a proposal is associated
with a reward event is to look at both the new field, as well as the old
one, to wit reward_event_round.

[Added
here.](https://github.com/dfinity/nns-dapp/pull/5766/files#diff-bc794365fb0826c7ec5cc7d9ab15121c6bc9630e990e7bd8751b8b84273601b6R304-R305)

See more in [NNS1-2588](https://dfinity.atlassian.net/browse/NNS1-2588).

**2. NNS proposal votes should not be able to be registered after the
proposal deadline.**

dfinity/ic@9587cc9#diff-0da5ccadff83a3bb673833b806280c8032311d143120522fa59b6e202d7216f9R902

A voter can still cast a ballot in the time between which a proposal’s
deadline is over and the time where the proposal is settled.
This is not expected. It should be checked whether a proposal still
accepts votes (with the method accepts_vote) before a neuron’s vote is
cast.

And the logic from the `accepts_vote` function was added
[here](https://github.com/dfinity/nns-dapp/pull/5766/files#diff-bc794365fb0826c7ec5cc7d9ab15121c6bc9630e990e7bd8751b8b84273601b6R312-R313).

See more in [NNS1-959](https://dfinity.atlassian.net/browse/NNS1-959).

# Changes

- Update the logic and the reference url to the backend code.

# Tests

- Unit test updated.

# Todos

- [ ] Add entry to changelog (if necessary).
Not necessary.

[NNS1-2588]:
https://dfinity.atlassian.net/browse/NNS1-2588?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

[NNS1-959]:
https://dfinity.atlassian.net/browse/NNS1-959?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
  • Loading branch information
mstrasinskis authored Nov 13, 2024
1 parent 14784c3 commit 28e56ae
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 8 deletions.
25 changes: 17 additions & 8 deletions frontend/src/lib/utils/sns-proposals.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,12 @@ import {
SnsProposalRewardStatus,
type SnsPercentage,
} from "@dfinity/sns";
import { fromDefinedNullable, fromNullable, isNullish } from "@dfinity/utils";
import {
fromDefinedNullable,
fromNullable,
isNullish,
nonNullish,
} from "@dfinity/utils";
import { get } from "svelte/store";
import { nowInSeconds } from "./date.utils";
import { keyOfOptional } from "./utils";
Expand Down Expand Up @@ -282,7 +287,7 @@ export const snsDecisionStatus = (
/**
* Returns the status of a proposal based on the data.
*
* Reference: https://github.com/dfinity/ic/blob/226ab04e0984367da356bbe27c90447863d33a27/rs/sns/governance/src/proposal.rs#L735
* Reference: https://github.com/dfinity/ic/blob/bc2c84c5e3dc14bedb7ef9bbe231748886a34a29/rs/sns/governance/src/proposal.rs#L1692-L1706
*
* @param {SnsProposalData} proposal
* @returns {SnsProposalRewardStatus}
Expand All @@ -291,18 +296,22 @@ export const snsRewardStatus = ({
reward_event_round,
wait_for_quiet_state,
is_eligible_for_rewards,
reward_event_end_timestamp_seconds,
proposal_creation_timestamp_seconds,
initial_voting_period_seconds,
}: SnsProposalData): SnsProposalRewardStatus => {
if (reward_event_round > 0n) {
if (
nonNullish(fromNullable(reward_event_end_timestamp_seconds)) ||
reward_event_round > 0n
) {
return SnsProposalRewardStatus.PROPOSAL_REWARD_STATUS_SETTLED;
}

const now = nowInSeconds();
const deadline =
fromNullable(wait_for_quiet_state)?.current_deadline_timestamp_seconds;
if (!deadline) {
// Reference: https://github.com/dfinity/ic/blob/226ab04e0984367da356bbe27c90447863d33a27/rs/sns/governance/src/proposal.rs#L760
throw new Error("Proposal must have a wait_for_quiet_state.");
}
fromNullable(wait_for_quiet_state)?.current_deadline_timestamp_seconds ??
proposal_creation_timestamp_seconds + initial_voting_period_seconds;

if (now < deadline) {
return SnsProposalRewardStatus.PROPOSAL_REWARD_STATUS_ACCEPT_VOTES;
}
Expand Down
25 changes: 25 additions & 0 deletions frontend/src/tests/lib/utils/sns-proposals.utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,17 @@ describe("sns-proposals utils", () => {
);
});

it("should return SETTLED based on reward event end timestamp", () => {
const proposal: SnsProposalData = {
...mockSnsProposal,
reward_event_round: 0n,
reward_event_end_timestamp_seconds: [0n],
};
expect(snsRewardStatus(proposal)).toBe(
SnsProposalRewardStatus.PROPOSAL_REWARD_STATUS_SETTLED
);
});

it("should return ACCEPT_VOTES", () => {
const now = BigInt(nowInSeconds());
const proposal: SnsProposalData = {
Expand All @@ -171,6 +182,20 @@ describe("sns-proposals utils", () => {
);
});

it("should return ACCEPT_VOTES w/o current_deadline_timestamp_seconds ", () => {
const now = BigInt(nowInSeconds());
const proposal: SnsProposalData = {
...mockSnsProposal,
reward_event_round: 0n,
wait_for_quiet_state: [],
proposal_creation_timestamp_seconds: now,
initial_voting_period_seconds: 100n,
};
expect(snsRewardStatus(proposal)).toBe(
SnsProposalRewardStatus.PROPOSAL_REWARD_STATUS_ACCEPT_VOTES
);
});

it("should return READY_TO_SETTLE", () => {
const now = BigInt(nowInSeconds());
const proposal: SnsProposalData = {
Expand Down

0 comments on commit 28e56ae

Please sign in to comment.