Skip to content

Latest commit

 

History

History
95 lines (61 loc) · 5.54 KB

File metadata and controls

95 lines (61 loc) · 5.54 KB

Narrow Lipstick Moose

Medium

Market Configuration ID Changes and Unintended Market Creation

Summary

This issue arises from the dynamic nature of the market configuration system in the createMarketWithConfig function. The user selects the market configuration based on an ID (index) of an existing market configuration. However, when a configuration is removed from the list, the IDs of subsequent configurations are shifted, potentially causing the user to accidentally select a different configuration than intended.

When creating a market, users specify the marketConfigIndex they wish to use. The function then passes this index to _createMarket, which uses the provided index to select one of the predefined configurations (e.g., Default, Deluxe, Premium tiers). However, the marketConfigs array is mutable, meaning configurations can be added, modified, or removed at any time by admins.

If an admin removes a market configuration from the marketConfigs array, it will cause all the following configurations to shift their index values. Therefore, if a user specified a configuration ID, say 1 (which may refer to the second configuration), but the configuration with ID 0 is removed, then the configuration the user actually wants may no longer correspond to their chosen index.

In summary, if the user specified marketConfigIndex = 1 with the intent of creating a market from the second configuration (e.g., Deluxe), but an admin removed the first configuration (ID 0), the second configuration will now be shifted to ID 0, and the user will create the market for the wrong configuration.

Root Cause

This is the createMarketWithConfig function at https://github.com/sherlock-audit/2024-12-ethos-update/blob/main/ethos/packages/contracts/contracts/ReputationMarket.sol#L284-L296

  function createMarketWithConfig(uint256 marketConfigIndex) public payable whenNotPaused {
    uint256 senderProfileId = _getProfileIdForAddress(msg.sender);

    // Verify sender can create market
    if (enforceCreationAllowList && !creationAllowedProfileIds[senderProfileId])
      revert MarketCreationUnauthorized(
        MarketCreationErrorCode.PROFILE_NOT_AUTHORIZED,
        msg.sender,
        senderProfileId
      );

    _createMarket(senderProfileId, msg.sender, marketConfigIndex);
  }

The marketConfigs array is mutable, and when an element is removed, it causes the subsequent elements to shift their indices. This change directly affects the user’s selection if the configuration they want is not the last one. Users specify the configuration by index, not by a unique identifier or any other stable reference, which means this approach fails to account for the potential dynamic modification of configurations.

Internal Pre-conditions

No response

External Pre-conditions

No response

Attack Path

  • There are three available market configurations: IDs 0, 1, and 2, each corresponding to different tiers.
  • A user wants to create a market using the Deluxe configuration (marketConfigIndex = 1).
  • An admin removes the configuration with ID 0 (e.g., Default).
  • This removal shifts the indexes of the remaining configurations, so the Deluxe configuration now becomes 0, and the Premium configuration becomes 1.
  • The user, still attempting to create a market with marketConfigIndex = 1, actually creates a market with the Premium configuration.
  • The user is thus unintentionally creating a market for a different tier than intended, and once the market is created, they cannot change it (since users can only create one market).

Impact

  • Users may unknowingly create a market with the wrong configuration if an admin removes a market configuration that causes indices to shift.
  • Also most importantly, since markets are one-time creations per profile, the user cannot correct their selection if the wrong market configuration is chosen.

PoC

Example Walkthrough

Let's illustrate this with a concrete example. Suppose the current configurations look like this:

MarketConfig Index Market Tier
0 Default
1 Deluxe
2 Premium

Step 1: User's Action

The user intends to create a market using the Deluxe configuration. They choose the configuration with index 1 (the second option) when calling createMarketWithConfig(1).

Step 2: Admin Modifies Configurations

While the user is submitting their request, an admin removes the configuration at index 0 (Default), which shifts the remaining configurations:

MarketConfig Index Market Tier
0 Deluxe
1 Premium

Now, after the removal of the configuration with index 0, the configuration with index 1 (Premium) becomes the second configuration.

Step 3: Unexpected Result

Since the user originally selected marketConfigIndex = 1, this now points to the Premium configuration instead of the Deluxe configuration, which the user originally wanted.

As a result, a market for the Premium configuration is created, not the Deluxe market the user intended. Since markets are typically a one-time creation per profile, the user can no longer create the market they wanted.

Mitigation

Allow users to refer to configurations by a stable identifier, such as a configId rather than relying on index positions in an array. This way, users would always select the correct configuration, regardless of its position in the list.