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
The Seer Protocol's MarketFactory contract creates prediction markets linked to Reality.eth questions. The askRealityQuestion function is responsible for submitting these questions to Reality.eth.
The askRealityQuestion function uses a user-provided openingTime parameter when creating or reusing Reality.eth questions. However, it doesn't validate this parameter against the current block timestamp, potentially allowing the creation of markets with questions that open in the past.
Markets could be created with questions that are immediately open for answering, potentially leading to rapid and unexpected resolutions.
Malicious actors could exploit this to create markets that resolve quickly based on past events, taking advantage of information asymmetry.
The integrity of the prediction market system could be compromised, as markets might not provide a fair opportunity for all participants to engage.
Scenario
A user creates a market with an openingTime set to a past timestamp.
The Reality.eth question is immediately open for answering.
The user or an accomplice quickly provides an answer to the question.
The market resolves based on this answer before most participants are aware of its existence.
Probability
High. This issue can be easily triggered by any user creating a market, either accidentally or intentionally.
Fix
Implement a check in the askRealityQuestion function to ensure the openingTime is in the future:
function askRealityQuestion(
stringmemoryencodedQuestion,
uint256templateId,
uint32openingTime,
uint256minBond
) internalreturns (bytes32) {
require(openingTime >block.timestamp, "Opening time must be in the future");
// Rest of the function remains the same
...
}
Consider adding an upper bound to the openingTime as well, to prevent markets from being created too far in the future.
Poc
describe("askRealityQuestion vulnerability",function(){it("allows creation of markets with questions opening in the past",asyncfunction(){constpastOpeningTime=awaittime.latest()-3600;// 1 hour in the pastconstfutureOpeningTime=awaittime.latest()+3600;// 1 hour in the future// Create a market with a past opening time (this should ideally fail, but currently doesn't)awaitexpect(marketFactory.createCategoricalMarket({
...categoricalMarketParams,openingTime: pastOpeningTime,})).to.emit(marketFactory,"NewMarket");// Create a market with a future opening time (this should succeed)awaitexpect(marketFactory.createCategoricalMarket({
...categoricalMarketParams,openingTime: futureOpeningTime,})).to.emit(marketFactory,"NewMarket");// Check that both markets were createdexpect(awaitmarketFactory.marketCount()).to.equal(2);// Get the created marketsconstmarkets=awaitmarketFactory.allMarkets();constpastMarket=awaitethers.getContractAt("Market",markets[0]);constfutureMarket=awaitethers.getContractAt("Market",markets[1]);// Check the opening times of the created questionsconstpastQuestionId=(awaitpastMarket.questionsIds())[0];constfutureQuestionId=(awaitfutureMarket.questionsIds())[0];constpastQuestionOpeningTime=awaitrealitio.getOpeningTS(pastQuestionId);constfutureQuestionOpeningTime=awaitrealitio.getOpeningTS(futureQuestionId);// Both should be in the past and future respectivelyexpect(pastQuestionOpeningTime).to.be.lt(awaittime.latest());expect(futureQuestionOpeningTime).to.be.gt(awaittime.latest());// Demonstrate that the past market can be answered immediatelyconstanswerer=(awaitethers.getSigners())[1];awaitrealitio.connect(answerer).submitAnswer(pastQuestionId,ethers.encodeBytes32String("1"),// Assuming "1" is a valid answer0,// Current bond{value: ethers.parseEther(MIN_BOND)});// Check that the answer was acceptedconstlastAnswerTime=awaitrealitio.getAnswerTimestamp(pastQuestionId);expect(lastAnswerTime).to.be.gt(0);});});
This test does the following:
It creates two markets: one with an opening time in the past and one in the future.
It verifies that both markets are created successfully (which demonstrates the bug, as the past market should ideally fail).
It checks the actual opening times of the Reality.eth questions for both markets.
It demonstrates that the market with the past opening time can be answered immediately, which shouldn't be possible in a properly functioning system.
The text was updated successfully, but these errors were encountered:
Github username: --
Twitter username: --
Submission hash (on-chain): 0x4dc4a8bee494100f2103fb12adc9d2fb24a785ccbc5ec3e15d4a2e88f907c52c
Severity: medium
Description:
Details
The Seer Protocol's
MarketFactory
contract creates prediction markets linked to Reality.eth questions. TheaskRealityQuestion
function is responsible for submitting these questions to Reality.eth.The
askRealityQuestion
function uses a user-providedopeningTime
parameter when creating or reusing Reality.eth questions. However, it doesn't validate this parameter against the current block timestamp, potentially allowing the creation of markets with questions that open in the past.Code Snippet
Impact
Scenario
openingTime
set to a past timestamp.Probability
High. This issue can be easily triggered by any user creating a market, either accidentally or intentionally.
Fix
Implement a check in the
askRealityQuestion
function to ensure theopeningTime
is in the future:Consider adding an upper bound to the openingTime as well, to prevent markets from being created too far in the future.
Poc
This test does the following:
The text was updated successfully, but these errors were encountered: