You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A malicious or careless admin will brick new trades and cause reverts for market participants by setting an excessively large basePrice or liquidityParameter.
Root Cause
The contract imposes a minimum check (liquidity >= 100) but no large upper bound on:
basePrice in MarketConfig
liquidityParameter in MarketConfig
When these values are set to extreme numbers (e.g., near 2^200or higher), the internal math in _calcCost() or _calcVotePrice() (which calls mulDiv(...) or multiplies with liquidityParameter) can overflow or revert due to 512-bit intermediate multiplication not fitting into 256-bit final results.
Impact
Such overflow or revert breaks any user trade (buy/sell), effectively causing a Denial of Service for that market. If this config is used widely (e.g., as the default), it could disrupt many or all newly created markets.
Root Cause
In ReputationMarket.sol, adding or modifying a market config is done via:
function addMarketConfig(
uint256liquidity,
uint256basePrice,
uint256creationCost
) public onlyAdmin whenNotPaused returns (uint256)
{
// Check minimums, but no large upper boundif (liquidity <100) revertInvalidMarketConfigOption("Min liquidity not met");
// basePrice only checks if (basePrice >= MINIMUM_BASE_PRICE)// ...
marketConfigs.push(MarketConfig({
liquidity: liquidity,
basePrice: basePrice,
creationCost: creationCost
}));
// ...
}
No code enforces that basePrice * costRatio < 2^256, nor that liquidityParameter * lnValUnwrapped < 2^256. A single ill-advised config can produce unbounded multiplication, triggering reverts in:
1-Admin calls addMarketConfig() (or an equivalent function that modifies existing configs) with very large basePrice or liquidity.
2-The newly created or updated config is used by createMarketWithConfig(...).
External Pre-conditions
1-A user or the admin then attempts to create a new market (or references the existing config) using that extreme basePrice or liquidityParameter.
2-After market creation, any attempt to buyVotes(), sellVotes(), or retrieve getVotePrice() triggers an internal multiplication that can revert due to overflow.
Admin or a user uses this config via createMarketWithConfig(indexOfMaliciousConfig).
Now liquidityParameter = 2^210 for that market.
3-User Tries to Trade:
_calcCost() or _calcVotePrice() attempts mulDiv(...) or (lnValUnwrapped * liquidityParameter).
The 512-bit intermediate result is beyond 256-bit range → reverts.
4-Denial of Service:
No trades can succeed. Anyone interacting with that market hits a revert.
(Similarly, if basePrice is extremely large, the final multiplication in _calcVotePrice() or _calcCost() can overflow.)
Impact
Affected Party: Any participant in that newly created market (including the admin themselves if they try to deposit or withdraw).
Result: The market is effectively bricked—no buy or sell can proceed.
Denial of Service: If this is the default or a commonly used config, it can block a large set of new markets.
PoC
// SPDX-License-Identifier: MITpragma solidity^0.8.26;
import"forge-std/Test.sol";
import"../src/ReputationMarket.sol";
contractOverflowTestisTest {
ReputationMarket rm;
address admin =address(0xA1);
function setUp() public {
vm.startPrank(admin);
rm =newReputationMarket();
// Hypothetical initialization
vm.stopPrank();
}
function testOverflowInLiquidityParameter() public {
vm.startPrank(admin);
// Add a config with extremely large liquidityParameter
rm.addMarketConfig(
type(uint256).max /2, // e.g. near 2^255 1 ether,
0.5 ether
);
// This is index 3 if 3 default configs existed// Create a market with that config
vm.deal(admin, 1 ether);
rm.createMarketWithConfigAdmin(admin, 3);
vm.stopPrank();
// Now user tries to trade
vm.deal(address(this), 10 ether);
// Expect revert when we do buyVotes or getVotePrice
vm.expectRevert();
rm.buyVotes{value: 1ether}(12345, true, 10, 1);
// This reverts due to overflow in `_calcCost()` or `_calcVotePrice()`.
}
}
Mitigation
1-Impose Safe Upper Bounds
For example, require basePrice <= 10^18 or some protocol-chosen max.
Similarly, require liquidity <= 10^12 (or whichever safe range ensures no overflow).
2-Use Safe Casting / Overflow Checks
If extremely large values are desired, incorporate advanced math that gracefully handles 512-bit intermediate results (though mulDiv attempts this, you still can easily revert if the final is above 2^256-1).
3-Designate “Admin Approval”
Only let a specialized admin or multi-sig add new configs, with code or governance gating that checks the numeric ranges.
4-Explicit “Check for Overflow”
For example, if (lnValUnwrapped > 0) then require liquidityParameter < (type(uint256).max / lnValUnwrapped) in _calcCost() if the design must be extremely flexible.
The text was updated successfully, but these errors were encountered:
Sparkly Ruby Rabbit
High
Massive basePrice or liquidityParameter Overflows
Summary
A malicious or careless admin will brick new trades and cause reverts for market participants by setting an excessively large basePrice or liquidityParameter.
Root Cause
The contract imposes a minimum check (liquidity >= 100) but no large upper bound on:
When these values are set to extreme numbers (e.g., near 2^200or higher), the internal math in
_calcCost()
or_calcVotePrice()
(which calls mulDiv(...) or multiplies with liquidityParameter) can overflow or revert due to 512-bit intermediate multiplication not fitting into 256-bit final results.Impact
Such overflow or revert breaks any user trade (buy/sell), effectively causing a Denial of Service for that market. If this config is used widely (e.g., as the default), it could disrupt many or all newly created markets.
Root Cause
In ReputationMarket.sol, adding or modifying a market config is done via:
No code enforces that basePrice * costRatio < 2^256, nor that liquidityParameter * lnValUnwrapped < 2^256. A single ill-advised config can produce unbounded multiplication, triggering reverts in:
_calcCost():
costResult = lnValUnwrapped * liquidityParameter;
_calcVotePrice():
return odds.mulDiv(market.basePrice, 1e18, roundingMode);
Internal Pre-conditions
1-Admin calls addMarketConfig() (or an equivalent function that modifies existing configs) with very large basePrice or liquidity.
2-The newly created or updated config is used by createMarketWithConfig(...).
External Pre-conditions
1-A user or the admin then attempts to create a new market (or references the existing config) using that extreme basePrice or liquidityParameter.
2-After market creation, any attempt to buyVotes(), sellVotes(), or retrieve getVotePrice() triggers an internal multiplication that can revert due to overflow.
Attack Path
1-Malicious Admin:
2-Market Creation:
3-User Tries to Trade:
4-Denial of Service:
No trades can succeed. Anyone interacting with that market hits a revert.
(Similarly, if basePrice is extremely large, the final multiplication in _calcVotePrice() or _calcCost() can overflow.)
Impact
Affected Party: Any participant in that newly created market (including the admin themselves if they try to deposit or withdraw).
Result: The market is effectively bricked—no buy or sell can proceed.
Denial of Service: If this is the default or a commonly used config, it can block a large set of new markets.
PoC
Mitigation
1-Impose Safe Upper Bounds
For example, require basePrice <= 10^18 or some protocol-chosen max.
Similarly, require liquidity <= 10^12 (or whichever safe range ensures no overflow).
2-Use Safe Casting / Overflow Checks
If extremely large values are desired, incorporate advanced math that gracefully handles 512-bit intermediate results (though mulDiv attempts this, you still can easily revert if the final is above 2^256-1).
3-Designate “Admin Approval”
Only let a specialized admin or multi-sig add new configs, with code or governance gating that checks the numeric ranges.
4-Explicit “Check for Overflow”
For example, if (lnValUnwrapped > 0) then require liquidityParameter < (type(uint256).max / lnValUnwrapped) in _calcCost() if the design must be extremely flexible.
The text was updated successfully, but these errors were encountered: