hats-finance / SeeR-PM-0x899bc13919880db76edf4ccd72bdfa5dfa666fb7

1 stars 0 forks source link

Unsafe Typecasting of `bytes32` to `uint256` in `RealityProxy` Contract Functions #97

Open hats-bug-reporter[bot] opened 2 months ago

hats-bug-reporter[bot] commented 2 months ago

Github username: -- Twitter username: -- Submission hash (on-chain): 0xef04b377079f2ac4740ba2549be458b0a7bbc4315561b505d860fabdec066521 Severity: medium

Description: Description\ The RealityProxy contract integrates with Reality.eth to resolve market outcomes, utilizing the resultForOnceSettled function from Reality.eth. This function returns results as bytes32 values. However, in multiple functions across the RealityProxy contract, these bytes32 values are directly cast to uint256 without validation. This practice introduces the risk of unsafe typecasting, which can lead to unintended outcomes, especially when Reality.eth returns a value that is inappropriate for casting to uint256.

This issue arises in several key functions that rely on the results of Reality.eth to make market resolution decisions:

Affected Functions:

resolveCategoricalMarket

uint256 answer = uint256(realitio.resultForOnceSettled(questionsIds[0]));

This function casts a bytes32 value from Reality.eth to uint256 to determine the market outcome. If Reality.eth returns an invalid value, such as bytes32(-1) or 0xffff...ffff, the typecasting may lead to unintended behavior or market misresolution.

resolveMultiCategoricalMarket

uint256 answer = uint256(realitio.resultForOnceSettled(questionsIds[0]));

Similar to the resolveCategoricalMarket function, this one casts bytes32 values into uint256 to compute payouts across multiple outcomes. If an invalid value is returned from Reality.eth, this could result in incorrect payouts or the marking of invalid results.

resolveScalarMarket

uint256 answer = uint256(realitio.resultForOnceSettled(questionsIds[0]));

This function computes market outcomes based on scalar values. Unsafe casting could cause the bounds checks (low, high) to fail, potentially resulting in incorrect resolution or invalid outcomes.

resolveMultiScalarMarket

payouts[i] = uint256(realitio.resultForOnceSettled(questionsIds[i]));

This function deals with multiple scalar outcomes, and unsafe casting from bytes32 to uint256 across multiple question IDs increases the likelihood of payout errors or market resolution failures.

Lets say if Reality.eth returns an answer as bytes32(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (as may happen if a data provider responds with int256(-1)), casting this to uint256 would result in a very large positive integer, which could be interpreted as a valid outcome when it shouldn’t be. This could lead to unintended market resolution and potentially incorrect fund distribution.

Impact\ The outcome of markets could be incorrectly calculated based on invalid or out-of-bounds values, leading to incorrect decisions. Unintended results from Reality.eth might trigger incorrect payouts to market participants, including scenarios where collateral or rewards are distributed incorrectly. If an incorrect or invalid market resolution occurs due to unsafe typecasting, it may lead to significant financial implications, such as incorrect fund distribution. Attackers or unintended data inputs from Reality.eth could trigger the casting of unsafe values (like int256(-1)) to uint256, leading to unforeseen vulnerabilities in the contract's behavior.

Recommendation\ Implement checks to ensure that the bytes32 value returned by Reality.eth is within an expected and safe range before casting it to uint256. Specifically, ensure that invalid values like bytes32(0xffff...ffff) or other unexpected values are handled appropriately. For cases where the returned bytes32 value is outside the expected range, ensure that the contract defaults to safe behavior, such as marking the market as unresolved or invalidating the result rather than continuing with faulty logic.

greenlucid commented 2 months ago

They're handled, check the code

clesaege commented 2 months ago

The invalid outcome is always handled by the code. If you believe that there is a place where it is not, you'd need to point to it and the specific resulting issue.