Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tall Daisy Mammoth - Vulnerability in buyVotes Function #153

Open
sherlock-admin2 opened this issue Dec 30, 2024 · 0 comments
Open

Tall Daisy Mammoth - Vulnerability in buyVotes Function #153

sherlock-admin2 opened this issue Dec 30, 2024 · 0 comments

Comments

@sherlock-admin2
Copy link

Tall Daisy Mammoth

Medium

Vulnerability in buyVotes Function

Summary

The buyVotes function is vulnerable to a potential Denial of Service (DoS) vector caused by inefficient handling of vote purchasing calculations.

Root Cause

While Loop with Decrementing Votes:
If the user cannot afford the maxVotesToBuy, the function iteratively decrements the currentVotesToBuy value and recalculates the total cost using _calculateBuy until the vote cost matches the funds provided (msg.value).
In cases where maxVotesToBuy is significantly high, and the provided funds are insufficient to purchase even one vote, the loop will execute until currentVotesToBuy reaches zero.

Gas Exhaustion Risk:
When a user sets maxVotesToBuy to a large value and provides insufficient funds to buy even a single vote, the while loop continues decrementing until it runs out of gas, causing the transaction to revert.

Internal Pre-conditions

No response

External Pre-conditions

No response

Attack Path

No response

Impact

User may spend too much gas and got his transaction reverted

No response

PoC

    function test_buyVotes_revert_outofgas() public {
        uint256 liquidity = 1e58;
        uint256 basePrice = 0.0001 ether; // MINIMUM_BASE_PRICE
        uint256 creationCost = 10 ether;

        // add new market confing with higher liquidity
        vm.prank(admin);
        reputationMarket.addMarketConfig(liquidity, basePrice, creationCost);

        // create userB market
        vm.prank(owner);
        profile.inviteAddress(address(userB));
        vm.prank(address(userB));
        profile.createProfile(DEFAULT.profileId);
        (,,,uint256 profileId) = profile.profileStatusByAddress(address(userB));
        vm.prank(admin);
        reputationMarket.setUserAllowedToCreateMarket(profileId, true);
        vm.prank(address(userB));
        reputationMarket.createMarketWithConfig{value: creationCost}(profileId);

        uint256 amountVotesToBuy = 1e48;
        vm.assume(amountVotesToBuy <= 133 * liquidity);
        vm.deal(address(userA), basePrice * amountVotesToBuy);
        vm.prank(address(userA));
        reputationMarket.buyVotes{value: basePrice}(profileId, true, amountVotesToBuy, 10);
    }
    │   │   ├─ [13309] LMSR::getCost{value: 100000000000000}(1, 1, 999999999999999999999999999999999999999999956388 [9.999e47], 1, 10000000000000000000000000000000000000000000000000000000000 [1e58]) [delegatecall]
    │   │   │   └─ ← [Return] 499999950000000000000000000000000000000000000000000000000000000000 [4.999e65]
    │   │   ├─ [8231] LMSR::getCost{value: 100000000000000}(1, 1, 999999999999999999999999999999999999999999956387 [9.999e47], 1, 10000000000000000000000000000000000000000000000000000000000 [1e58]) [delegatecall]
    │   │   │   └─ ← [OutOfGas] EvmError: OutOfGas
    │   │   └─ ← [Revert] EvmError: Revert
    │   └─ ← [Revert] EvmError: Revert
    └─ ← [Revert] EvmError: Revert

No response

Mitigation

Implement a better optimal buy vote calculation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant