Missing duplicate prevention in setSubscription allows multiple subscriptions per vault
setSubscription accepts repeat calls for the same vaultId, creating duplicate entries in vaultOwnerSubscriptions while the underlying setAccess overwrites only the latest, breaking get and delete semantics.
Description
The setSubscription function lacks validation to prevent creating multiple subscription entries for the same vault ID. When called multiple times with the same vaultId, the function creates duplicate entries in the vaultOwnerSubscriptions array while overwriting the access control settings, violating the expected behavior that each vault should have only one subscription.
Vulnerable Scenario:
The following steps help understand the issue:
- Alice calls
setSubscription("vault-123", 100, 3600, ...)to create a subscription. - Alice later calls
setSubscription("vault-123", 200, 7200, ...)with different parameters for the same vault. - The function creates a second entry in
vaultOwnerSubscriptions[alice]with the same vault ID. - The underlying
setAccess()overwrites the previous access control settings, making only the latest parameters active. getVaultOwnerSubscriptions()returns duplicate entries for the same vault.deleteSubscription()only removes the first matching entry, leaving orphaned duplicates.
Impact
Breaks the expected one-subscription-per-vault behavior, causing operational issues where vault owners can accidentally create multiple subscription entries for the same content, leading to UI confusion and incomplete deletion of subscription data.
Recommendation
Use a mapping to check for existing duplicates:
mapping(address => mapping(string => bool)) private hasSubscription;function setSubscription(string calldata vaultId, ...) external {require(!hasSubscription[msg.sender][vaultId], "Subscription exists");hasSubscription[msg.sender][vaultId] = true;// ... rest of logic}
Resolution
Ipal Network: Confirmed. An alternative solution has been implemented to prevent the creation of duplicate subscription entries for the same vault ID.
Zealynx: Partially Fixed: Duplicate prevention implemented correctly, but the solution adds update logic to the create function instead of separating concerns into distinct setSubscription (create) and updateSubscription (update) functions, making the code harder to maintain and reason about.
UPDATE: Fixed.

