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

Petite Rosewood Whale - price can reach zero in imbalanced markets, can cause issues #135

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

Comments

@sherlock-admin2
Copy link

Petite Rosewood Whale

Medium

price can reach zero in imbalanced markets, can cause issues

Summary

Due to precision loss and how LMSR works, if the difference between the amount of outstanding shares is big enough, one of the share prices can hit zero. If a price hits zero within markets that use LMSR, under normal conditions this would mean that no shares would be sold, creating a deadlock. However ReputationMarket will keep giving free shares to users without any fees. Although there is no total value loss, because shares can be bought for free and the price can later increase due to market activity, this creates a potential profit with no downside. Also buying these shares will cost no fees.

Root Cause

Allowing users to buy shares for free
https://github.com/sherlock-audit/2024-12-ethos-update/blob/c3a2b007d0ddfcb476f300f8b766808f0e3e2dfd/ethos/packages/contracts/contracts/ReputationMarket.sol#L440-L497

Internal Pre-conditions

  1. Outstanding shares of one of the votes is much greater than the other such that one of the shares is priced at zero

External Pre-conditions

No response

Attack Path

  1. User buys shares that are priced at zero
  2. If the other shares are sold or more shares that were priced at zero are bought, user can sell these shares that were bought for free

Impact

Users are able to trade risk free, also without paying fees.

PoC

Note that this test will fail because gas costs are not taken into consideration, but on the output you can see only the gas costs were paid.

  it('should let user buy shares for free', async () => {
    const billionEth = ethers.parseEther('1000000000');
    const maxVotes = 133000n - 1n;

    // Buy many distrust votes to push trust price down
    await userA.buyVotes({
      votesToBuy: maxVotes,
      buyAmount: billionEth,
      isPositive: false,
    });

    const balanceBefore = await ethers.provider.getBalance(userA.signer.address);

    const trustPrice = await reputationMarket.getVotePrice(DEFAULT.profileId, true);
    expect(Number(trustPrice)).to.equal(0);

    await userA.buyVotes({
      votesToBuy: 80000n,
      isPositive: true,
    });

    const balanceAfter = await ethers.provider.getBalance(userA.signer.address);

    // this will fail as gas costs are not taken for consideration
    expect(balanceAfter).to.equal(balanceBefore, 'Balance did not decrease after buying votes');
  });

Mitigation

Do not let users buy shares when price hits 0.

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