fix(governance): fix incorrect validator penalties (#3381)
This commit is contained in:
parent
84068c8081
commit
8d4e4a1228
@ -7,9 +7,10 @@ query PreviousEpoch($epochId: ID) {
|
|||||||
id
|
id
|
||||||
rewardScore {
|
rewardScore {
|
||||||
rawValidatorScore
|
rawValidatorScore
|
||||||
|
performanceScore
|
||||||
}
|
}
|
||||||
rankingScore {
|
rankingScore {
|
||||||
performanceScore
|
stakeScore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ export type PreviousEpochQueryVariables = Types.Exact<{
|
|||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type PreviousEpochQuery = { __typename?: 'Query', epoch: { __typename?: 'Epoch', id: string, validatorsConnection?: { __typename?: 'NodesConnection', edges?: Array<{ __typename?: 'NodeEdge', node: { __typename?: 'Node', id: string, rewardScore?: { __typename?: 'RewardScore', rawValidatorScore: string } | null, rankingScore: { __typename?: 'RankingScore', performanceScore: string } } } | null> | null } | null } };
|
export type PreviousEpochQuery = { __typename?: 'Query', epoch: { __typename?: 'Epoch', id: string, validatorsConnection?: { __typename?: 'NodesConnection', edges?: Array<{ __typename?: 'NodeEdge', node: { __typename?: 'Node', id: string, rewardScore?: { __typename?: 'RewardScore', rawValidatorScore: string, performanceScore: string } | null, rankingScore: { __typename?: 'RankingScore', stakeScore: string } } } | null> | null } | null } };
|
||||||
|
|
||||||
|
|
||||||
export const PreviousEpochDocument = gql`
|
export const PreviousEpochDocument = gql`
|
||||||
@ -21,9 +21,10 @@ export const PreviousEpochDocument = gql`
|
|||||||
id
|
id
|
||||||
rewardScore {
|
rewardScore {
|
||||||
rawValidatorScore
|
rawValidatorScore
|
||||||
|
performanceScore
|
||||||
}
|
}
|
||||||
rankingScore {
|
rankingScore {
|
||||||
performanceScore
|
stakeScore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,9 +81,10 @@ const MOCK_PREVIOUS_EPOCH: PreviousEpochQuery = {
|
|||||||
id: 'ccc022b7e63a4d0a6d3a193c3940c88574060e58a184964c994998d86835a1b4',
|
id: 'ccc022b7e63a4d0a6d3a193c3940c88574060e58a184964c994998d86835a1b4',
|
||||||
rewardScore: {
|
rewardScore: {
|
||||||
rawValidatorScore: '0.25',
|
rawValidatorScore: '0.25',
|
||||||
|
performanceScore: '0.9998677767864936',
|
||||||
},
|
},
|
||||||
rankingScore: {
|
rankingScore: {
|
||||||
performanceScore: '0.9998677767864936',
|
stakeScore: '0.2499583402766206',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -92,9 +93,10 @@ const MOCK_PREVIOUS_EPOCH: PreviousEpochQuery = {
|
|||||||
id: '966438c6bffac737cfb08173ffcb3f393c4692b099ad80cb45a82e2dc0a8cf99',
|
id: '966438c6bffac737cfb08173ffcb3f393c4692b099ad80cb45a82e2dc0a8cf99',
|
||||||
rewardScore: {
|
rewardScore: {
|
||||||
rawValidatorScore: '0.3',
|
rawValidatorScore: '0.3',
|
||||||
|
performanceScore: '1',
|
||||||
},
|
},
|
||||||
rankingScore: {
|
rankingScore: {
|
||||||
performanceScore: '1',
|
stakeScore: '0.25',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -103,9 +105,10 @@ const MOCK_PREVIOUS_EPOCH: PreviousEpochQuery = {
|
|||||||
id: '12c81b738e8051152e1afe44376ec37bca9216466e6d44cdd772194bad0ada81',
|
id: '12c81b738e8051152e1afe44376ec37bca9216466e6d44cdd772194bad0ada81',
|
||||||
rewardScore: {
|
rewardScore: {
|
||||||
rawValidatorScore: '0.35',
|
rawValidatorScore: '0.35',
|
||||||
|
performanceScore: '0.999629748500531',
|
||||||
},
|
},
|
||||||
rankingScore: {
|
rankingScore: {
|
||||||
performanceScore: '0.999629748500531',
|
stakeScore: '0.2312',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -10,7 +10,6 @@ import {
|
|||||||
getFormattedPerformanceScore,
|
getFormattedPerformanceScore,
|
||||||
getLastEpochScoreAndPerformance,
|
getLastEpochScoreAndPerformance,
|
||||||
getNormalisedVotingPower,
|
getNormalisedVotingPower,
|
||||||
getOverstakedAmount,
|
|
||||||
getOverstakingPenalty,
|
getOverstakingPenalty,
|
||||||
getPerformancePenalty,
|
getPerformancePenalty,
|
||||||
getTotalPenalties,
|
getTotalPenalties,
|
||||||
@ -52,7 +51,6 @@ interface CanonisedConsensusNodeProps {
|
|||||||
[ValidatorFields.STAKED_BY_OPERATOR]: string;
|
[ValidatorFields.STAKED_BY_OPERATOR]: string;
|
||||||
[ValidatorFields.PERFORMANCE_SCORE]: string;
|
[ValidatorFields.PERFORMANCE_SCORE]: string;
|
||||||
[ValidatorFields.PERFORMANCE_PENALTY]: string;
|
[ValidatorFields.PERFORMANCE_PENALTY]: string;
|
||||||
[ValidatorFields.OVERSTAKED_AMOUNT]: string;
|
|
||||||
[ValidatorFields.OVERSTAKING_PENALTY]: string;
|
[ValidatorFields.OVERSTAKING_PENALTY]: string;
|
||||||
[ValidatorFields.TOTAL_PENALTIES]: string;
|
[ValidatorFields.TOTAL_PENALTIES]: string;
|
||||||
[ValidatorFields.PENDING_STAKE]: string;
|
[ValidatorFields.PENDING_STAKE]: string;
|
||||||
@ -164,14 +162,11 @@ export const ConsensusValidatorsTable = ({
|
|||||||
pendingUserStake,
|
pendingUserStake,
|
||||||
userStakeShare,
|
userStakeShare,
|
||||||
}) => {
|
}) => {
|
||||||
const { rawValidatorScore, performanceScore } =
|
const {
|
||||||
getLastEpochScoreAndPerformance(previousEpochData, id);
|
rawValidatorScore: previousEpochValidatorScore,
|
||||||
|
performanceScore: previousEpochPerformanceScore,
|
||||||
const overstakedAmount = getOverstakedAmount(
|
stakeScore: previousEpochStakeScore,
|
||||||
rawValidatorScore,
|
} = getLastEpochScoreAndPerformance(previousEpochData, id);
|
||||||
stakedTotal,
|
|
||||||
totalStake
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
@ -184,7 +179,7 @@ export const ConsensusValidatorsTable = ({
|
|||||||
[ValidatorFields.NORMALISED_VOTING_POWER]:
|
[ValidatorFields.NORMALISED_VOTING_POWER]:
|
||||||
getNormalisedVotingPower(votingPower),
|
getNormalisedVotingPower(votingPower),
|
||||||
[ValidatorFields.UNNORMALISED_VOTING_POWER]:
|
[ValidatorFields.UNNORMALISED_VOTING_POWER]:
|
||||||
getUnnormalisedVotingPower(rawValidatorScore),
|
getUnnormalisedVotingPower(previousEpochValidatorScore),
|
||||||
[ValidatorFields.STAKE_SHARE]: stakedTotalPercentage(stakeScore),
|
[ValidatorFields.STAKE_SHARE]: stakedTotalPercentage(stakeScore),
|
||||||
[ValidatorFields.STAKED_BY_DELEGATES]: formatNumber(
|
[ValidatorFields.STAKED_BY_DELEGATES]: formatNumber(
|
||||||
toBigNum(stakedByDelegates, decimals),
|
toBigNum(stakedByDelegates, decimals),
|
||||||
@ -194,18 +189,19 @@ export const ConsensusValidatorsTable = ({
|
|||||||
toBigNum(stakedByOperator, decimals),
|
toBigNum(stakedByOperator, decimals),
|
||||||
2
|
2
|
||||||
),
|
),
|
||||||
[ValidatorFields.PERFORMANCE_SCORE]:
|
[ValidatorFields.PERFORMANCE_SCORE]: getFormattedPerformanceScore(
|
||||||
getFormattedPerformanceScore(performanceScore).toString(),
|
previousEpochPerformanceScore
|
||||||
[ValidatorFields.PERFORMANCE_PENALTY]:
|
).toString(),
|
||||||
getPerformancePenalty(performanceScore),
|
[ValidatorFields.PERFORMANCE_PENALTY]: getPerformancePenalty(
|
||||||
[ValidatorFields.OVERSTAKED_AMOUNT]: overstakedAmount.toString(),
|
previousEpochPerformanceScore
|
||||||
|
),
|
||||||
[ValidatorFields.OVERSTAKING_PENALTY]: getOverstakingPenalty(
|
[ValidatorFields.OVERSTAKING_PENALTY]: getOverstakingPenalty(
|
||||||
overstakedAmount,
|
previousEpochValidatorScore,
|
||||||
totalStake
|
previousEpochStakeScore
|
||||||
),
|
),
|
||||||
[ValidatorFields.TOTAL_PENALTIES]: getTotalPenalties(
|
[ValidatorFields.TOTAL_PENALTIES]: getTotalPenalties(
|
||||||
rawValidatorScore,
|
previousEpochValidatorScore,
|
||||||
performanceScore,
|
previousEpochPerformanceScore,
|
||||||
stakedTotal,
|
stakedTotal,
|
||||||
totalStake
|
totalStake
|
||||||
),
|
),
|
||||||
|
@ -7,7 +7,6 @@ import { BigNumber } from '../../../../lib/bignumber';
|
|||||||
import {
|
import {
|
||||||
getFormattedPerformanceScore,
|
getFormattedPerformanceScore,
|
||||||
getLastEpochScoreAndPerformance,
|
getLastEpochScoreAndPerformance,
|
||||||
getOverstakedAmount,
|
|
||||||
getOverstakingPenalty,
|
getOverstakingPenalty,
|
||||||
getPerformancePenalty,
|
getPerformancePenalty,
|
||||||
getTotalPenalties,
|
getTotalPenalties,
|
||||||
@ -82,21 +81,21 @@ export const StandbyPendingValidatorsTable = ({
|
|||||||
pendingUserStake,
|
pendingUserStake,
|
||||||
userStakeShare,
|
userStakeShare,
|
||||||
}) => {
|
}) => {
|
||||||
const { rawValidatorScore, performanceScore } =
|
const {
|
||||||
getLastEpochScoreAndPerformance(previousEpochData, id);
|
rawValidatorScore: previousEpochValidatorScore,
|
||||||
|
performanceScore: previousEpochPerformanceScore,
|
||||||
|
stakeScore: previousEpochStakeScore,
|
||||||
|
} = getLastEpochScoreAndPerformance(previousEpochData, id);
|
||||||
|
|
||||||
const overstakedAmount = getOverstakedAmount(
|
|
||||||
rawValidatorScore,
|
|
||||||
stakedTotal,
|
|
||||||
totalStake
|
|
||||||
);
|
|
||||||
let individualStakeNeededForPromotion,
|
let individualStakeNeededForPromotion,
|
||||||
individualStakeNeededForPromotionDescription;
|
individualStakeNeededForPromotionDescription;
|
||||||
|
|
||||||
if (stakeNeededForPromotion && performanceScore) {
|
if (stakeNeededForPromotion && previousEpochPerformanceScore) {
|
||||||
const stakedTotalBigNum = new BigNumber(stakedTotal);
|
const stakedTotalBigNum = new BigNumber(stakedTotal);
|
||||||
const stakeNeededBigNum = new BigNumber(stakeNeededForPromotion);
|
const stakeNeededBigNum = new BigNumber(stakeNeededForPromotion);
|
||||||
const performanceScoreBigNum = new BigNumber(performanceScore);
|
const performanceScoreBigNum = new BigNumber(
|
||||||
|
previousEpochPerformanceScore
|
||||||
|
);
|
||||||
|
|
||||||
const calc = stakeNeededBigNum
|
const calc = stakeNeededBigNum
|
||||||
.dividedBy(performanceScoreBigNum)
|
.dividedBy(performanceScoreBigNum)
|
||||||
@ -142,18 +141,19 @@ export const StandbyPendingValidatorsTable = ({
|
|||||||
toBigNum(stakedByOperator, decimals),
|
toBigNum(stakedByOperator, decimals),
|
||||||
2
|
2
|
||||||
),
|
),
|
||||||
[ValidatorFields.PERFORMANCE_SCORE]:
|
[ValidatorFields.PERFORMANCE_SCORE]: getFormattedPerformanceScore(
|
||||||
getFormattedPerformanceScore(performanceScore).toString(),
|
previousEpochPerformanceScore
|
||||||
[ValidatorFields.PERFORMANCE_PENALTY]:
|
).toString(),
|
||||||
getPerformancePenalty(performanceScore),
|
[ValidatorFields.PERFORMANCE_PENALTY]: getPerformancePenalty(
|
||||||
[ValidatorFields.OVERSTAKED_AMOUNT]: overstakedAmount.toString(),
|
previousEpochPerformanceScore
|
||||||
|
),
|
||||||
[ValidatorFields.OVERSTAKING_PENALTY]: getOverstakingPenalty(
|
[ValidatorFields.OVERSTAKING_PENALTY]: getOverstakingPenalty(
|
||||||
overstakedAmount,
|
previousEpochValidatorScore,
|
||||||
totalStake
|
previousEpochStakeScore
|
||||||
),
|
),
|
||||||
[ValidatorFields.TOTAL_PENALTIES]: getTotalPenalties(
|
[ValidatorFields.TOTAL_PENALTIES]: getTotalPenalties(
|
||||||
rawValidatorScore,
|
previousEpochValidatorScore,
|
||||||
performanceScore,
|
previousEpochPerformanceScore,
|
||||||
stakedTotal,
|
stakedTotal,
|
||||||
totalStake
|
totalStake
|
||||||
),
|
),
|
||||||
|
@ -20,7 +20,6 @@ import { SubHeading } from '../../../components/heading';
|
|||||||
import {
|
import {
|
||||||
getLastEpochScoreAndPerformance,
|
getLastEpochScoreAndPerformance,
|
||||||
getNormalisedVotingPower,
|
getNormalisedVotingPower,
|
||||||
getOverstakedAmount,
|
|
||||||
getOverstakingPenalty,
|
getOverstakingPenalty,
|
||||||
getPerformancePenalty,
|
getPerformancePenalty,
|
||||||
getTotalPenalties,
|
getTotalPenalties,
|
||||||
@ -75,15 +74,9 @@ export const ValidatorTable = ({
|
|||||||
|
|
||||||
const stakedOnNode = toBigNum(node.stakedTotal, decimals);
|
const stakedOnNode = toBigNum(node.stakedTotal, decimals);
|
||||||
|
|
||||||
const { rawValidatorScore, performanceScore } =
|
const { rawValidatorScore, performanceScore, stakeScore } =
|
||||||
getLastEpochScoreAndPerformance(previousEpochData, node.id);
|
getLastEpochScoreAndPerformance(previousEpochData, node.id);
|
||||||
|
|
||||||
const overstakedAmount = getOverstakedAmount(
|
|
||||||
rawValidatorScore,
|
|
||||||
stakedTotal,
|
|
||||||
node.stakedTotal
|
|
||||||
);
|
|
||||||
|
|
||||||
const stakePercentage = getStakePercentage(total, stakedOnNode);
|
const stakePercentage = getStakePercentage(total, stakedOnNode);
|
||||||
|
|
||||||
const totalPenaltiesAmount = getTotalPenalties(
|
const totalPenaltiesAmount = getTotalPenalties(
|
||||||
@ -245,7 +238,7 @@ export const ValidatorTable = ({
|
|||||||
|
|
||||||
<Tooltip description={t('OverstakedPenaltyDescription')}>
|
<Tooltip description={t('OverstakedPenaltyDescription')}>
|
||||||
<span data-testid="overstaking-penalty">
|
<span data-testid="overstaking-penalty">
|
||||||
{getOverstakingPenalty(overstakedAmount, node.stakedTotal)}
|
{getOverstakingPenalty(rawValidatorScore, stakeScore)}
|
||||||
</span>
|
</span>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
|
@ -4,7 +4,6 @@ import {
|
|||||||
getNormalisedVotingPower,
|
getNormalisedVotingPower,
|
||||||
getUnnormalisedVotingPower,
|
getUnnormalisedVotingPower,
|
||||||
getOverstakingPenalty,
|
getOverstakingPenalty,
|
||||||
getOverstakedAmount,
|
|
||||||
getFormattedPerformanceScore,
|
getFormattedPerformanceScore,
|
||||||
getPerformancePenalty,
|
getPerformancePenalty,
|
||||||
getTotalPenalties,
|
getTotalPenalties,
|
||||||
@ -22,9 +21,10 @@ describe('getLastEpochScoreAndPerformance', () => {
|
|||||||
id: '0x123',
|
id: '0x123',
|
||||||
rewardScore: {
|
rewardScore: {
|
||||||
rawValidatorScore: '0.25',
|
rawValidatorScore: '0.25',
|
||||||
|
performanceScore: '0.75',
|
||||||
},
|
},
|
||||||
rankingScore: {
|
rankingScore: {
|
||||||
performanceScore: '0.75',
|
stakeScore: '0.25',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -33,9 +33,10 @@ describe('getLastEpochScoreAndPerformance', () => {
|
|||||||
id: '0x234',
|
id: '0x234',
|
||||||
rewardScore: {
|
rewardScore: {
|
||||||
rawValidatorScore: '0.35',
|
rawValidatorScore: '0.35',
|
||||||
|
performanceScore: '0.85',
|
||||||
},
|
},
|
||||||
rankingScore: {
|
rankingScore: {
|
||||||
performanceScore: '0.85',
|
stakeScore: '0.25',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -50,12 +51,14 @@ describe('getLastEpochScoreAndPerformance', () => {
|
|||||||
).toEqual({
|
).toEqual({
|
||||||
rawValidatorScore: '0.25',
|
rawValidatorScore: '0.25',
|
||||||
performanceScore: '0.75',
|
performanceScore: '0.75',
|
||||||
|
stakeScore: '0.25',
|
||||||
});
|
});
|
||||||
expect(
|
expect(
|
||||||
getLastEpochScoreAndPerformance(mockPreviousEpochData, '0x234')
|
getLastEpochScoreAndPerformance(mockPreviousEpochData, '0x234')
|
||||||
).toEqual({
|
).toEqual({
|
||||||
rawValidatorScore: '0.35',
|
rawValidatorScore: '0.35',
|
||||||
performanceScore: '0.85',
|
performanceScore: '0.85',
|
||||||
|
stakeScore: '0.25',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -79,40 +82,34 @@ describe('getUnnormalisedVotingPower', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('getOverstakingPenalty', () => {
|
describe('getOverstakingPenalty', () => {
|
||||||
it('should return the overstaking penalty', () => {
|
it('returns "0%" when both arguments are null or undefined', () => {
|
||||||
expect(
|
expect(getOverstakingPenalty(null, null)).toBe('0%');
|
||||||
getOverstakingPenalty(new BigNumber(100), Number(1000).toString())
|
expect(getOverstakingPenalty(undefined, undefined)).toBe('0%');
|
||||||
).toEqual('10.00%');
|
expect(getOverstakingPenalty(null, undefined)).toBe('0%');
|
||||||
expect(
|
expect(getOverstakingPenalty(undefined, null)).toBe('0%');
|
||||||
getOverstakingPenalty(new BigNumber(500), Number(2000).toString())
|
|
||||||
).toEqual('25.00%');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('getOverstakedAmount', () => {
|
|
||||||
it('should return the overstaked amount', () => {
|
|
||||||
expect(
|
|
||||||
// If a validator score is 0, any amount staked on the node is considered overstaked
|
|
||||||
getOverstakedAmount('0', Number(100).toString(), Number(20).toString())
|
|
||||||
).toEqual(new BigNumber(20));
|
|
||||||
expect(
|
|
||||||
getOverstakedAmount('0.05', Number(100).toString(), Number(20).toString())
|
|
||||||
).toEqual(new BigNumber(15));
|
|
||||||
expect(
|
|
||||||
getOverstakedAmount('0.1', Number(100).toString(), Number(20).toString())
|
|
||||||
).toEqual(new BigNumber(10));
|
|
||||||
expect(
|
|
||||||
getOverstakedAmount('0.15', Number(100).toString(), Number(20).toString())
|
|
||||||
).toEqual(new BigNumber(5));
|
|
||||||
expect(
|
|
||||||
getOverstakedAmount('0.2', Number(100).toString(), Number(20).toString())
|
|
||||||
).toEqual(new BigNumber(0));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return 0 if the overstaked amount is negative', () => {
|
it('returns "0%" when one argument is null or undefined', () => {
|
||||||
expect(
|
expect(getOverstakingPenalty('10', null)).toBe('0%');
|
||||||
getOverstakedAmount('0.8', Number(100).toString(), Number(20).toString())
|
expect(getOverstakingPenalty(null, '20')).toBe('0%');
|
||||||
).toEqual(new BigNumber(0));
|
expect(getOverstakingPenalty('10', undefined)).toBe('0%');
|
||||||
|
expect(getOverstakingPenalty(undefined, '20')).toBe('0%');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns "0%" when validatorScore or stakeScore is zero', () => {
|
||||||
|
expect(getOverstakingPenalty('0', '20')).toBe('0%');
|
||||||
|
expect(getOverstakingPenalty('10', '0')).toBe('0%');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns the correct overstaking penalty', () => {
|
||||||
|
expect(getOverstakingPenalty('0.18', '0.2')).toBe('10.00%');
|
||||||
|
expect(getOverstakingPenalty('0.2', '0.2')).toBe('0.00%');
|
||||||
|
expect(getOverstakingPenalty('0.04', '0.2')).toBe('80.00%');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles string numbers with decimals', () => {
|
||||||
|
expect(getOverstakingPenalty('7.5', '15')).toBe('50.00%');
|
||||||
|
expect(getOverstakingPenalty('12.5', '25')).toBe('50.00%');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -15,7 +15,8 @@ export const getLastEpochScoreAndPerformance = (
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
rawValidatorScore: validator?.rewardScore?.rawValidatorScore,
|
rawValidatorScore: validator?.rewardScore?.rawValidatorScore,
|
||||||
performanceScore: validator?.rankingScore?.performanceScore,
|
performanceScore: validator?.rewardScore?.performanceScore,
|
||||||
|
stakeScore: validator?.rankingScore?.stakeScore,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -42,31 +43,26 @@ export const getPerformancePenalty = (performanceScore?: string) =>
|
|||||||
2
|
2
|
||||||
);
|
);
|
||||||
|
|
||||||
export const getOverstakedAmount = (
|
|
||||||
validatorScore: string | null | undefined,
|
|
||||||
totalStake: string,
|
|
||||||
stakedOnNode: string
|
|
||||||
) => {
|
|
||||||
const toReturn = validatorScore
|
|
||||||
? new BigNumber(stakedOnNode).minus(
|
|
||||||
new BigNumber(validatorScore).times(new BigNumber(totalStake))
|
|
||||||
)
|
|
||||||
: new BigNumber(0);
|
|
||||||
|
|
||||||
return toReturn.isNegative() ? new BigNumber(0) : toReturn;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getOverstakingPenalty = (
|
export const getOverstakingPenalty = (
|
||||||
overstakedAmount: BigNumber,
|
validatorScore: string | null | undefined,
|
||||||
stakedOnNode: string
|
stakeScore: string | null | undefined
|
||||||
) => {
|
) => {
|
||||||
|
if (!validatorScore || !stakeScore) {
|
||||||
|
return '0%';
|
||||||
|
}
|
||||||
|
|
||||||
// avoid division by zero
|
// avoid division by zero
|
||||||
if (new BigNumber(stakedOnNode).isZero() || overstakedAmount.isZero()) {
|
if (
|
||||||
return '0';
|
new BigNumber(validatorScore).isZero() ||
|
||||||
|
new BigNumber(stakeScore).isZero()
|
||||||
|
) {
|
||||||
|
return '0%';
|
||||||
}
|
}
|
||||||
|
|
||||||
return formatNumberPercentage(
|
return formatNumberPercentage(
|
||||||
overstakedAmount.dividedBy(new BigNumber(stakedOnNode)).times(100),
|
new BigNumber(1)
|
||||||
|
.minus(new BigNumber(validatorScore).dividedBy(new BigNumber(stakeScore)))
|
||||||
|
.times(100),
|
||||||
2
|
2
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user