Omniscia Evergon Labs Audit
PostPurchaseStakeFacetStorage Manual Review Findings
PostPurchaseStakeFacetStorage Manual Review Findings
PPF-01M: Inexistent Handling of Downward Rounded Fractions
| Type | Severity | Location |
|---|---|---|
| Mathematical Operations | ![]() | PostPurchaseStakeFacetStorage.sol: • I-1: L90 • I-2: L97 |
Description:
The PostPurchaseStakeFacetStorage::handlePostPurchasePhase function will not handle any division truncation that may occur when calculating the number of input packets for the staking campaign in the Evergon Labs staking system.
Impact:
Any rounded-down fractions will be locked in the FractionalisationDiamond as they are not transferred outward.
Example:
71function handlePostPurchasePhase(72 Layout storage l,73 uint256 campaignId,74 uint256 amountOfFractions,75 address msg_sender,76 bytes calldata data77) internal {78 uint256 nftId = abi.decode(data, (uint256)); // Staking Position NFT ID:: If 0 then is stake, if not then is restake79
80 CampaignInfo storage campaignInfoLocal = l.campaignInfo[campaignId];81
82 IERC1155(GeneralStorage.layout().infoForId[campaignId].fractionsContract).setApprovalForAll(83 campaignInfoLocal.stakingContract,84 true85 );86
87 if (nftId == 0) {88 IStakingSkeleton(campaignInfoLocal.stakingContract).stakeBeneficiary(89 campaignInfoLocal.stakingCampaignId,90 amountOfFractions / campaignInfoLocal.amountOfFractionsPerInputPacket, // number of input packets91 0, // timeLock period is 0 for now92 msg_sender93 );94 } else {95 IStakingSkeleton(campaignInfoLocal.stakingContract).restakeBeneficiary(96 nftId,97 amountOfFractions / campaignInfoLocal.amountOfFractionsPerInputPacket, // number of input packets98 0, // timeLock period is 0 for now99 msg_sender100 );101 }102}Recommendation:
We advise any remainder to be transferred to the user using a similar approach to the ReturnFungAndSemiFungFractionsFacet and ReturnFungAndSemiFungFractionsOmnichainFacet functions, ensuring that fraction units post-purchase are not lost.
Alleviation (71cda4ccfdcfa25fb96a4565f1f8143b350dd246):
The code was updated to mandate that the amountOfFractions defined is wholly divisible by the amountOfFractionsPerInputPacket, preventing the truncation scenario defined from manifesting.
