diff --git a/src/components/v2v3/V2V3Project/ProjectDashboard/components/TokensPanel/components/ReservedTokensSubPanel.tsx b/src/components/v2v3/V2V3Project/ProjectDashboard/components/TokensPanel/components/ReservedTokensSubPanel.tsx
index c07d576d2c..dd52a9614f 100644
--- a/src/components/v2v3/V2V3Project/ProjectDashboard/components/TokensPanel/components/ReservedTokensSubPanel.tsx
+++ b/src/components/v2v3/V2V3Project/ProjectDashboard/components/TokensPanel/components/ReservedTokensSubPanel.tsx
@@ -54,7 +54,9 @@ export const ReservedTokensSubPanel = ({
items: kebabMenuItems,
}}
>
- {reservedList?.length ? (
+ {reservedTokens ||
+ reservedRate ||
+ (reservedList && reservedList.length > 1) ? (
<>
{reservedList
diff --git a/src/components/v2v3/V2V3Project/ProjectDashboard/components/TokensPanel/hooks/useReservedTokensSubPanel.test.ts b/src/components/v2v3/V2V3Project/ProjectDashboard/components/TokensPanel/hooks/useReservedTokensSubPanel.test.ts
index 4f77eef565..f9b1f30387 100644
--- a/src/components/v2v3/V2V3Project/ProjectDashboard/components/TokensPanel/hooks/useReservedTokensSubPanel.test.ts
+++ b/src/components/v2v3/V2V3Project/ProjectDashboard/components/TokensPanel/hooks/useReservedTokensSubPanel.test.ts
@@ -18,6 +18,7 @@ describe('useReservedTokensSubPanel', () => {
projectId: 1,
}
const DefaultProjectContext = {
+ projectOwnerAddress: '0x0000000000000000000000000000000000000000',
fundingCycleMetadata: {
reservedRate: 10000,
},
@@ -52,6 +53,11 @@ describe('useReservedTokensSubPanel', () => {
it('returns sorted reservedList when reservedTokensSplits is defined', () => {
const { result } = renderHook(useReservedTokensSubPanel)
expect(result.current.reservedList).toEqual([
+ {
+ projectId: 1,
+ address: '0x0000000000000000000000000000000000000000',
+ percent: '97%',
+ },
{
projectId: undefined,
address: '0x456',
diff --git a/src/components/v2v3/V2V3Project/ProjectDashboard/components/TokensPanel/hooks/useReservedTokensSubPanel.ts b/src/components/v2v3/V2V3Project/ProjectDashboard/components/TokensPanel/hooks/useReservedTokensSubPanel.ts
index 0c5b71dd08..4ddb02c602 100644
--- a/src/components/v2v3/V2V3Project/ProjectDashboard/components/TokensPanel/hooks/useReservedTokensSubPanel.ts
+++ b/src/components/v2v3/V2V3Project/ProjectDashboard/components/TokensPanel/hooks/useReservedTokensSubPanel.ts
@@ -2,6 +2,7 @@ import {
useProjectContext,
useProjectMetadata,
} from 'components/v2v3/V2V3Project/ProjectDashboard/hooks'
+import { ONE_BILLION } from 'constants/numbers'
import { BigNumber } from 'ethers'
import { useProjectReservedTokens } from 'hooks/v2v3/contractReader/ProjectReservedTokens'
import { useMemo } from 'react'
@@ -10,9 +11,12 @@ import { formatAmount } from 'utils/format/formatAmount'
import { fromWad } from 'utils/format/formatNumber'
import { formatReservedRate, formatSplitPercent } from 'utils/v2v3/math'
+const ONE_BILLION_BIG = BigNumber.from(ONE_BILLION)
+
export const useReservedTokensSubPanel = () => {
const { projectId } = useProjectMetadata()
- const { fundingCycleMetadata, reservedTokensSplits } = useProjectContext()
+ const { fundingCycleMetadata, reservedTokensSplits, projectOwnerAddress } =
+ useProjectContext()
const reservedRateWad = fundingCycleMetadata?.reservedRate
const { data: reservedTokensWad } = useProjectReservedTokens({
@@ -21,20 +25,60 @@ export const useReservedTokensSubPanel = () => {
})
const reservedList = useMemo(() => {
- if (!reservedTokensSplits) return undefined
- return reservedTokensSplits
+ if (!projectOwnerAddress || !projectId || !reservedTokensSplits) return
+ // If there aren't explicitly defined splits, all reserved tokens go to this project.
+ if (reservedTokensSplits?.length === 0)
+ return [
+ {
+ projectId,
+ address: projectOwnerAddress!,
+ percent: `${formatSplitPercent(ONE_BILLION_BIG)}%`,
+ },
+ ]
+
+ // If the splits don't add up to 100%, remaining tokens go to this project.
+ let splitsPercentTotal = BigNumber.from(0)
+ const processedSplits = reservedTokensSplits
.sort((a, b) => Number(b.percent) - Number(a.percent))
.map(split => {
assert(split.beneficiary, 'Beneficiary must be defined')
+ const splitPercent = BigNumber.from(split.percent)
+ splitsPercentTotal = splitsPercentTotal.add(splitPercent)
+
return {
projectId: split.projectId
? BigNumber.from(split.projectId).toNumber()
: undefined,
address: split.beneficiary!,
- percent: `${formatSplitPercent(BigNumber.from(split.percent))}%`,
+ percent: `${formatSplitPercent(splitPercent)}%`,
}
})
- }, [reservedTokensSplits])
+
+ const remainingPercentage = ONE_BILLION_BIG.sub(splitsPercentTotal)
+
+ // Check if this project is already one of the splits.
+ if (!remainingPercentage.isZero()) {
+ const projectSplitIndex = processedSplits.findIndex(
+ v => v.projectId === projectId,
+ )
+ if (projectSplitIndex != -1)
+ // If it is, increase its split percentage to bring the total to 100%.
+ processedSplits[projectSplitIndex].percent = `${formatSplitPercent(
+ remainingPercentage.add(
+ reservedTokensSplits[projectSplitIndex].percent,
+ ),
+ )}%`
+ // If it isn't, add a split at the beginning which brings the total percentage to 100%.
+ else
+ processedSplits.unshift({
+ projectId,
+ address: projectOwnerAddress!,
+ percent: `${formatSplitPercent(remainingPercentage)}%`,
+ })
+ }
+
+ return processedSplits
+ }, [reservedTokensSplits, projectOwnerAddress, projectId])
const reservedRate = useMemo(() => {
if (!reservedRateWad) return undefined