Fun Crepe Lobster
High
Improper validation of market configuration parameters will cause fund drainage vulnerability for the protocol as malicious or compromised admins will create markets with insufficient collateralization through parameter manipulation.
In ReputationMarket.sol:L242-L246 the validation checks for market configuration parameters do not ensure proper collateralization ratio between creation cost and maximum possible market liability.
- Admin needs to call addMarketConfig() to set liquidity to be exactly 100
- Admin needs to set basePrice to be exactly MINIMUM_BASE_PRICE
- Admin needs to set creationCost to be less than maxVotes * basePrice
- Market needs to be active (not paused)
- Admin account needs to be compromised or malicious
- Network gas cost need to be low enough for profitable exploitation
- Malicious admin adds new market config with minimum allowed parameters
- Admin sets extremely low creation cost relative to potential market size
- Users create markets with minimal collateralization
- Users can buy maximum votes allowed by LMSR formula
- Protocol becomes undercollateralized
The protocol suffers an approximate loss of up to (maxVotes * basePrice - creationCost) ETH per market. In the demonstrated configuration, markets require only 0.01 ETH collateral but can accumulate 1 ETH in liabilities.
pragma solidity 0.8.26;
import {ReputationMarket} from "./ReputationMarket.sol"; import {Test} from "forge-std/Test.sol";
contract MarketConfigExploit is Test { ReputationMarket public market; address public admin = address(0x1); address public user = address(0x2);
function setUp() public {
// Deploy and setup market
market = new ReputationMarket();
market.initialize(
address(this), // owner
admin, // admin
address(0), // signer
address(0), // verifier
address(this) // contract manager
);
// Fund user
vm.deal(user, 1 ether);
}
function testConfigurationExploit() public {
// Step 1: Admin adds dangerous config
vm.startPrank(admin);
uint256 minLiquidity = 100;
uint256 minBasePrice = market.MINIMUM_BASE_PRICE();
uint256 lowCreationCost = 0.01 ether;
uint256 configIndex = market.addMarketConfig(
minLiquidity,
minBasePrice,
lowCreationCost
);
// Step 2: Create market with minimal collateral
vm.startPrank(user);
market.createMarketWithConfig{value: lowCreationCost}(configIndex);
// Calculate maximum market liability
uint256 maxVotes = minLiquidity * 133; // LMSR limit
uint256 maxLiability = maxVotes * minBasePrice;
console.log("Market parameters:");
console.log("Creation cost:", lowCreationCost);
console.log("Max liability:", maxLiability);
console.log("Collateralization ratio:", (lowCreationCost * 100) / maxLiability, "%");
// Verify undercollateralization
assertTrue(maxLiability > lowCreationCost,
"Market should be undercollateralized");
}
}
function addMarketConfig( uint256 liquidity, uint256 basePrice, uint256 creationCost ) public onlyAdmin whenNotPaused returns (uint256) { // Existing checks...
// Calculate maximum market liability
uint256 maxVotes = liquidity * 133; // LMSR limit
uint256 maxLiability = maxVotes * basePrice;
// Require minimum 150% collateralization
require(
creationCost * 100 >= maxLiability * 150,
"Insufficient collateralization ratio"
);
// Rest of the function...
}