code-423n4 / 2024-07-traitforge-findings

1 stars 0 forks source link

Aging will be too slow #867

Closed howlbot-integration[bot] closed 2 months ago

howlbot-integration[bot] commented 2 months ago

Lines of code

https://github.com/code-423n4/2024-07-traitforge/blob/main/contracts/NukeFund/NukeFund.sol#L166

Vulnerability details

Impact

The docs explain how some NFTs will age to their full potential (claiming 50% of the nuke fund) in 30 days and others in 600 days. However, that's not the case because the current aging implementation is too slow.

Proof of Concept

calculateAge calculates the age of an NFT. calculateNukeFactor multiplies that age by defaultNukeFactorIncrease and combines it with initialNukeFactor to get the finalNukeFactor. The age should account for 25% of the Nuke factor (best case).

uint256 initialNukeFactor = entropy / 40;

// (age * 250 / 1e5) + (entropy / 40)
//       25%         +      25%
uint256 finalNukeFactor = ((adjustedAge * defaultNukeFactorIncrease) / MAX_DENOMINATOR) + initialNukeFactor;

In the docs, it is described that NFTs should mature between 30 and 600 days. We take the best-case scenario: 25% of the nuke factor is made by age and performanceFactor = 9 (our highest possible value).

Also, ageMultiplier would be 1. It's used only for testing, as stated by the sponsor:

pickpeak1024 — 08/01/2024 12:58 PM what is the value of agemultiplier @ManPeach.0x

ManPeach.0x — 08/01/2024 1:00 PM Ignore it. It will be removed as it was used for testing

calculateAge will calculate an age of 73972.

// 30
uint256 daysOld = (block.timestamp - nftContract.getTokenCreationTimestamp(tokenId)) / 60 / 60 / 24;
uint256 performanceFactor = nftContract.getTokenEntropy(tokenId) % 10;

// 30 * 9 * 1e5 * 1 / 365 = 73972
uint256 age = (daysOld * performanceFactor * MAX_DENOMINATOR * ageMultiplier) / 365;
return age;

When used inside calculateNukeFactor, it will return 184 + initialNukeFactor.

uint256 entropy = nftContract.getTokenEntropy(tokenId);
uint256 adjustedAge = calculateAge(tokenId);

uint256 initialNukeFactor = entropy / 40;

// 73972 * 250 / 1e5 + initialNukeFactor = 184 + initialNukeFactor
uint256 finalNukeFactor = ((adjustedAge * defaultNukeFactorIncrease) / MAX_DENOMINATOR) + initialNukeFactor;

Finally, when used inside nuke to calculate our portion of the nuke funds, it will return 0.184% of our fund. However, we should have expected 25% of the fund (not accounting initialNukeFactor).

uint256 finalNukeFactor = calculateNukeFactor(tokenId);

// fund * 184 / 1e5 = 0.184%
uint256 potentialClaimAmount = (fund * finalNukeFactor) / MAX_DENOMINATOR;
uint256 maxAllowedClaimAmount = fund / maxAllowedClaimDivisor;

Tools Used

Manual review

Recommended Mitigation Steps

Adjust the aging math to match the docs.

Assessed type

Error

c4-judge commented 2 months ago

koolexcrypto changed the severity to 2 (Med Risk)