-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
boostedValue
should be added to permanentTotalSupply
for permanently locked tokens
#11
Comments
alcueca marked the issue as primary issue |
Hi, thanks for your submission. Indeed, after refactoring and changes, this point, although known, was missed in the new code duplicate #6 , or #6 is a duplicate of #11 It is difficult to understand the severity of this issue, it seems to be Overseverity. If we go with the worst-case scenario, the last user/users will not be able to unlock the permanent lock on their veNFTs, which will lead them to some additional temporary lock until the problem is resolved, as they would have to wait 182 days for full unlocking anyway Thank you for your participation |
alcueca changed the severity to 2 (Med Risk) |
alcueca marked the issue as duplicate of #6 |
alcueca marked the issue as satisfactory |
alcueca marked the issue as selected for report |
@alcueca Thanks for your judging. File: contracts\core\VotingEscrowUpgradeableV2.sol
532: function _checkpoint(uint256 tokenId_, LockedBalance memory oldLocked_, LockedBalance memory newLocked_) internal {
[...]
616:@> last_point.permanent = LibVotingEscrowUtils.toInt128(permanentTotalSupply); File: contracts\core\VotingEscrowUpgradeableV2.sol
647: function _balanceOfNFT(uint256 tokenId_, uint256 timestamp_) internal view returns (uint256 balance) {
649: if (pointEpoch > 0) {
650: Point memory lastPoint = nftPointHistory[tokenId_][pointEpoch];
651: if (lastPoint.permanent > 0) {
652:@> return LibVotingEscrowUtils.toUint256(lastPoint.permanent); |
This was not pointed out in the original submission, but it is right. |
alcueca changed the severity to 3 (High Risk) |
In the balanceOfNFT calculation, data regarding the permanentTotalSupply is not used, and the impact of not accounting boostedValue in permanentTotalSupply is limited only to the calculation of the total voting power. This does not affect on votes proccesing, but only the outcome (votingPowerTotalSupply()). The voting power for a user's veNFT will still be calculated correctly. This statement most likely arose because similar structures and pieces of code are used for the general voting power calculation and for the user. However, last_point in _checkpoint is from supplyPointsHistory, whereas in balanceOfNFT, nftPointHistory is used. |
hey @c4-judge I believe there is some wrong assumption in this issue tl;dr
However, and the value of u_new.permanent = permanent;
nftPointHistory[tokenId_][nftStates[tokenId_].pointEpoch] = u_new;
} Which is acutely only this amount here The impact is more like this QA (nb: not dupl) last user can't call |
There is a confunsion for two variables and I agree there is no incorrect calculation of voting power by the |
I'm not sure if we can call this denial-of-service, because only the last permanent-lock is affected by losing his locked FNX tokens! |
I think the last permanent lock being affected reasonably often merits a medium severity. Thanks @KupiaSecAdmin for retracting your previous statement about |
Sorry if my input might be too late for this but maybe this could be helpful regarding the acutal impact of this. I actually described the impact @Ch-301 mentioned in my original finding here: #6 Although, it's not always the last withdrawal that's gonna have a problem.
Someone creates a new permanent lock, let's say the amount is 200 and they receive 20 boosted FNX:
Now, let's say that someone suddenly changes their mind and call
And after this, both lock A and lock B can't be unlocked from permanent lock because it would fail from underflow of permanentTotalSupply |
@nnez Yeah, we can create scenarios with 3,4.. locks can't be unlocked from permanent lock because of this issue (the more preconditions required will lead to lower the probability). So, as @c4-judge mentions here the medium severity is fair.
Please, @C4-Staff make sure to update the Label here if the judge confirms the medium severity. |
Per request from the judge @alcueca, updating the severity of this issue to |
Lines of code
https://github.com/code-423n4/2024-09-fenix-finance/blob/main/contracts/core/VotingEscrowUpgradeableV2.sol#L470
Vulnerability details
Impact
Unlocking tokens from the permanent locking can be DoSed.
Proof of Concept
In the
VotingEscrowUpgradeableV2._processLockChange
function,boostedValue
is added to the token's locked amount at L465. However,boostedValue
is not added topermanentTotalSupply
for permanently locked tokens at L470.In the
unlockPermanent
function, the token's locked amount is subtracted frompermanentTotalSupply
at L219.As a result, calling this function may be reverted by the underflow.
Let's consider the following scenario:
< veBoostCached.getMinLockedTimeForBoost
).permanentTotalSupply
= 100 + 100 = 200.>= veBoostCached.getMinFNXAmountForBoost
), and_boostFNXPercentage
is 1000 (10%):boostedValue
: 100permanentTotalSupply
: 200 + 1000 = 1200permanentTotalSupply
= 1200 - 1200 = 0.permanentTotalSupply
is 0.Tools Used
Manual Review
Recommended Mitigation Steps
It is recommended to change the code in the
VotingEscrowUpgradeableV2._processLockChange
function as following:Let me know if you need further assistance!
Assessed type
DoS
The text was updated successfully, but these errors were encountered: