Skip to content

Commit 4626a38

Browse files
authored
Merge pull request #2305 from Giveth/fix_allocated_giv_value
Fix allocated giv value
2 parents c47e3d0 + 86e0742 commit 4626a38

2 files changed

Lines changed: 60 additions & 15 deletions

File tree

src/resolvers/donationResolver.test.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ import { addOrUpdatePowerSnapshotBalances } from '../repositories/powerBalanceSn
6363
import { findPowerSnapshots } from '../repositories/powerSnapshotRepository';
6464
import { ChainType } from '../types/network';
6565
import { getDefaultSolanaChainId } from '../services/chains';
66+
import { calculateGivbackFactorByRank } from '../services/givbackService';
6667
import {
6768
DRAFT_DONATION_STATUS,
6869
DraftDonation,
@@ -2247,13 +2248,15 @@ function createDonationTestCases() {
22472248
where: { id: saveDonationResponse.data.data.createDonation },
22482249
});
22492250

2250-
// because this project is rank1
2251-
assert.equal(
2252-
donation?.givbackFactor,
2253-
Number(process.env.GIVBACK_MAX_FACTOR),
2254-
);
2251+
const expectedGivbackFactor = calculateGivbackFactorByRank({
2252+
projectRank: donation?.projectRank,
2253+
bottomRank: donation?.bottomRankInRound || 1,
2254+
minGivFactor: Number(process.env.GIVBACK_MIN_FACTOR),
2255+
maxGivFactor: Number(process.env.GIVBACK_MAX_FACTOR),
2256+
});
2257+
assert.equal(donation?.givbackFactor, expectedGivbackFactor);
22552258
assert.equal(donation?.powerRound, roundNumber);
2256-
assert.equal(donation?.projectRank, 1);
2259+
assert.isAtLeast(donation?.projectRank || 0, 1);
22572260
});
22582261
it('should create GIV donation for giveth project on mainnet successfully', async () => {
22592262
const project = await saveProjectDirectlyToDb(createProjectData());

src/services/givbackService.ts

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,41 @@ import {
44
getBottomGivbackRank,
55
} from '../repositories/projectGivbackViewRepository';
66

7+
export const calculateGivbackFactorByRank = (params: {
8+
projectRank?: number;
9+
bottomRank: number;
10+
minGivFactor: number;
11+
maxGivFactor: number;
12+
}): number => {
13+
const { projectRank, bottomRank, minGivFactor, maxGivFactor } = params;
14+
15+
// Keep configured bounds stable even if env values are swapped.
16+
const minFactor = Math.min(minGivFactor, maxGivFactor);
17+
const maxFactor = Math.max(minGivFactor, maxGivFactor);
18+
19+
const parsedBottomRank = Number(bottomRank);
20+
const parsedProjectRank = Number(projectRank);
21+
22+
// With no ranking spread (or invalid bottom rank), avoid division by zero.
23+
// If project has a rank (rank 1 in this case), keep top project on max factor.
24+
if (!Number.isFinite(parsedBottomRank) || parsedBottomRank <= 1) {
25+
return Number.isFinite(parsedProjectRank) && parsedProjectRank > 0
26+
? maxFactor
27+
: minFactor;
28+
}
29+
30+
// When rank is missing/invalid, default to bottom rank -> minimum factor.
31+
const normalizedRank =
32+
Number.isFinite(parsedProjectRank) && parsedProjectRank > 0
33+
? parsedProjectRank
34+
: parsedBottomRank;
35+
36+
const step = (maxFactor - minFactor) / (parsedBottomRank - 1);
37+
const rawFactor = maxFactor - (normalizedRank - 1) * step;
38+
const boundedFactor = Math.max(minFactor, Math.min(maxFactor, rawFactor));
39+
return Number.isFinite(boundedFactor) ? boundedFactor : minFactor;
40+
};
41+
742
export const calculateGivbackFactor = async (
843
projectId: number,
944
): Promise<{
@@ -12,24 +47,31 @@ export const calculateGivbackFactor = async (
1247
projectRank?: number;
1348
powerRound: number;
1449
}> => {
15-
const minGivFactor = Number(process.env.GIVBACK_MIN_FACTOR);
16-
const maxGivFactor = Number(process.env.GIVBACK_MAX_FACTOR);
50+
const minGivFactorRaw = Number(process.env.GIVBACK_MIN_FACTOR);
51+
const maxGivFactorRaw = Number(process.env.GIVBACK_MAX_FACTOR);
52+
const minGivFactor = Number.isFinite(minGivFactorRaw) ? minGivFactorRaw : 0;
53+
const maxGivFactor = Number.isFinite(maxGivFactorRaw)
54+
? maxGivFactorRaw
55+
: minGivFactor;
56+
1757
const [projectGivbackRankView, bottomRank, powerRound] = await Promise.all([
1858
findProjectGivbackRankViewByProjectId(projectId),
1959
getBottomGivbackRank(),
2060
getPowerRound(),
2161
]);
2262

23-
const eachRoundImpact = (maxGivFactor - minGivFactor) / (bottomRank - 1);
24-
const givbackFactor = projectGivbackRankView?.powerRank
25-
? minGivFactor +
26-
eachRoundImpact * (bottomRank - projectGivbackRankView?.powerRank)
27-
: minGivFactor;
63+
const givbackFactor = calculateGivbackFactorByRank({
64+
projectRank: projectGivbackRankView?.powerRank,
65+
bottomRank,
66+
minGivFactor,
67+
maxGivFactor,
68+
});
2869

2970
return {
30-
givbackFactor: givbackFactor || 0,
71+
givbackFactor,
3172
projectRank: projectGivbackRankView?.powerRank,
32-
bottomRankInRound: bottomRank,
73+
bottomRankInRound:
74+
Number.isFinite(bottomRank) && bottomRank > 0 ? bottomRank : 1,
3375
powerRound: powerRound?.round as number,
3476
};
3577
};

0 commit comments

Comments
 (0)