Omniscia Evergon Labs Audit
PurchaseSkeleton Manual Review Findings
PurchaseSkeleton Manual Review Findings
PSN-01M: Incompatible Integration of Fractionalized EIP-1155 ODC Implementation
| Type | Severity | Location |
|---|---|---|
| Logical Fault | ![]() | PurchaseSkeleton.sol:L58-L62 |
Description:
The PurchaseSkeleton::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:
38function purchase(39 uint256 campaignId,40 uint256 amountOfFractions,41 bytes calldata discountOperationData,42 bytes calldata postPurchaseData,43 uint32 chainId44) external payable onlyExternalDelegateCall {45 IPurchaseStateFacet(address(this)).checkPurchaseState(campaignId);46 IPurchaseTimeFacet(address(this)).checkPurchaseTimes(campaignId);47
48 address account = ERC2771RecipientStorage.layout()._msgSender();49 IPurchaseEligibilityFacet(address(this)).checkPurchaserEligibility(campaignId, account, amountOfFractions);50 IPurchaseAmountFacet(address(this)).checkPurchaseAmounts(campaignId, amountOfFractions, account);51 uint256 discountPercentage = IPurchaseDiscountFacet(address(this)).getDiscount(52 campaignId,53 amountOfFractions,54 account,55 discountOperationData56 );57 IDoPurchaseFacet(address(this)).doPurchase(campaignId, account, amountOfFractions, discountPercentage);58 if (GeneralStorage.layout().infoForId[campaignId].isMinting) {59 // Mint to the diamond and then transfers etc will be handled by postPurchase60 // Always mint id 0 if semi fungible. All other ids are used only for vesting in current version.61 ISemiFungibleAndFungibleFractionTransferFacet(address(this)).mintFractions(campaignId, address(this), 0, amountOfFractions);62 }63 IPostPurchaseFacet(address(this)).handlePostPurchasePhase{value: msg.value}(64 campaignId,65 amountOfFractions,66 chainId,67 account,68 postPurchaseData69 );70
71 emit FractionsPurchased(campaignId, account, amountOfFractions);72}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.
