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
If markets.liquidityParameter * markets.basePrice % 1e18 != 0, the cost can be a non-integer value.
At this point, the rounding mode is used.
External pre-conditions
N/A
Attack Path
Buy TRUST voting rights one at a time n times, then sell all these voting rights at once.
Alternatively, buy nDISTRUST voting rights at once and then sell each vote one at a time for n times.
Impact
In Details:
What properties/invariants do you want to hold even if breaking them has a low/unknown impact?
The contract must never pay out the initial liquidity deposited as part of trading. The only way to access those funds is to graduate the market.
However, the initial liquidity could be Paided.
PoC
1017: function _calcCost(
Market memorymarket,
boolisPositive,
boolisBuy,
uint256amount
) privatepurereturns (uint256cost) {
// cost ratio is a unitless ratio of N / 1e18uint256[] memory voteDelta =newuint256[](2);
// convert boolean input into market state changeif (isBuy) {
if (isPositive) {
voteDelta[0] = market.votes[TRUST] + amount;
voteDelta[1] = market.votes[DISTRUST];
} else {
voteDelta[0] = market.votes[TRUST];
voteDelta[1] = market.votes[DISTRUST] + amount;
}
} else {
if (isPositive) {
voteDelta[0] = market.votes[TRUST] - amount;
voteDelta[1] = market.votes[DISTRUST];
} else {
voteDelta[0] = market.votes[TRUST];
voteDelta[1] = market.votes[DISTRUST] - amount;
}
}
int256 costRatio = LMSR.getCost(
market.votes[TRUST],
market.votes[DISTRUST],
1047: voteDelta[0],
1048: voteDelta[1],
market.liquidityParameter
);
uint256 positiveCostRatio = costRatio >0?uint256(costRatio) : uint256(costRatio *-1);
// multiply cost ratio by base price to get cost; divide by 1e18 to apply ratio
cost = positiveCostRatio.mulDiv(
market.basePrice,
1e18,
1057: isPositive ? Math.Rounding.Floor : Math.Rounding.Ceil
);
}
Let's examine how the initial liquidity is Paided.
Assume: liquidity := 1000, basePrice := 0.01e18 + 3e14, votes[0] := votes[1] := 1 and marketFunds = 0.2e18.
Buy TRUST voting rights one at a time n times, then sell all these voting rights at once.
Also, buy nDISTRUST votes and sell each of these votes n times.
Regarding this n: n := 2 : marketFunds = 199999999999999999 n := 3 : marketFunds = 199999999999999998 n := 4 : marketFunds = 199999999999999997 n := 5 : marketFunds = 199999999999999996 n := 6 : marketFunds = 199999999999999996 n := 7 : marketFunds = 199999999999999995 n := 8 : marketFunds = 199999999999999994 n := 9 : marketFunds = 199999999999999992
Magnificent Tortilla Eel
High
Initial Liquidity Could Be Paided.
Summary
There is an unsafe rounding mode in
ReputationMarket::L1057
.Root Cause
https://github.com/sherlock-audit/2024-12-ethos-update/blob/main/ethos/packages/contracts/contracts/ReputationMarket.sol#L1057
In the
_calcCost()
function, the cost is rounded down forTRUST
and rounded up forDISTRUST
.If there are more times purchases than sales for
TRUST
, or fewer times purchases than sales forDISTRUST
, themarketFunds
can be consumed.This occurs because there are more additions when rounding down and more subtractions when rounding up.
Internal pre-conditions
markets.liquidityParameter * markets.basePrice % 1e18 != 0
If
markets.liquidityParameter * markets.basePrice % 1e18 != 0
, thecost
can be a non-integer value.At this point, the rounding mode is used.
External pre-conditions
N/A
Attack Path
TRUST
voting rights one at a timen
times, then sell all these voting rights at once.n
DISTRUST
voting rights at once and then sell each vote one at a time forn
times.Impact
In Details:
However, the initial liquidity could be Paided.
PoC
Let's examine how the initial liquidity is Paided.
Assume:
liquidity := 1000
,basePrice := 0.01e18 + 3e14
,votes[0] := votes[1] := 1
andmarketFunds = 0.2e18
.Buy
TRUST
voting rights one at a timen
times, then sell all these voting rights at once.Also, buy
n
DISTRUST
votes and sell each of these votesn
times.Regarding this
n
:n := 2 : marketFunds = 199999999999999999
n := 3 : marketFunds = 199999999999999998
n := 4 : marketFunds = 199999999999999997
n := 5 : marketFunds = 199999999999999996
n := 6 : marketFunds = 199999999999999996
n := 7 : marketFunds = 199999999999999995
n := 8 : marketFunds = 199999999999999994
n := 9 : marketFunds = 199999999999999992
Here is the Python code used for testing:
Mitigation
The text was updated successfully, but these errors were encountered: