Omniscia Evergon Labs Audit

PurchaseSkeletonNID Manual Review Findings

PurchaseSkeletonNID Manual Review Findings

PSI-01M: Incompatible Integration of Fractionalized EIP-1155 ODC Implementation

Description:

The PurchaseSkeletonNID::purchase function integrates with the Evergon Labs ODC fractionalized EIP-1155 implementation to permit a mint-on-purchase approach.

This approach is inherently insecure as the first purchaser of a campaign will be able to directly interact with the FractionERC1155DataManager::fullyUnlockWrappedAssets to acquire the underlying assets, effectively stealing all wrapped funds of a campaign for the price of a single fraction.

Impact:

It is possible to fully unwrap the underlying assets of a fractionalized EIP-1155 implementation by directly interacting with the FractionERC1155DataManager, effectively acquiring all wrapped funds for the price of a single fraction.

Example:

packages/contracts/contracts/skeletonFacets/NID/PurchaseSkeletonNID.sol
56function purchase(
57 uint256 campaignId,
58 uint256 amountOfFractions,
59 bytes calldata discountOperationData,
60 bytes calldata postPurchaseData,
61 uint32 chainId
62) external payable onlyExternalDelegateCall requireTxDataAuth {
63 IPurchaseStateFacet(address(this)).checkPurchaseState(campaignId);
64 IPurchaseTimeFacet(address(this)).checkPurchaseTimes(campaignId);
65
66 address account = ERC2771RecipientStorage.layout()._msgSender();
67 IPurchaseAmountFacet(address(this)).checkPurchaseAmounts(campaignId, amountOfFractions, account);
68 uint256 discountPercentage = IPurchaseDiscountFacet(address(this)).getDiscount(
69 campaignId,
70 amountOfFractions,
71 account,
72 discountOperationData
73 );
74 IDoPurchaseFacet(address(this)).doPurchase(campaignId, account, amountOfFractions, discountPercentage);
75 if (GeneralStorage.layout().infoForId[campaignId].isMinting) {
76 // Mint to the diamond and then transfers etc will be handled by postPurchase
77 // Always mint id 0 if semi fungible. All other ids are used only for vesting in current version.
78 ISemiFungibleAndFungibleFractionTransferFacet(address(this)).mintFractions(campaignId, address(this), 0, amountOfFractions);
79 }
80 IPostPurchaseFacet(address(this)).handlePostPurchasePhase{value: msg.value}(
81 campaignId,
82 amountOfFractions,
83 chainId,
84 account,
85 postPurchaseData
86 );
87
88 emit FractionsPurchased(campaignId, account, amountOfFractions);
89}

Recommendation:

We advise the system's integration to be revised, potentially by updating either the FractionERC1155DataManager itself in the ODC repository or removing support for mint-on-purchase configurations.

Alleviation (71cda4ccfdcfa25fb96a4565f1f8143b350dd246):

The Evergon Labs team evaluated this exhibit and proceeded to update the ODC implementations to permit the deployment of an EIP-1155 fraction to define whether user unlocks are enabled.

This mechanism permits user unlocks to be disabled and thus the system to be compatible with a mint-on-purchase approach as the callback will not be able to extract funds at will.