#37276 [SC-Medium] Redstone's price feed is used incorrectly.
Submitted on Dec 1st 2024 at 11:03:07 UTC by @jasonxiale for IOP | Fluid Protocol
Report ID: #37276
Report Type: Smart Contract
Report severity: Medium
Target: https://github.com/Hydrogen-Labs/fluid-protocol/tree/main/contracts/oracle-contract/src/main.sw
Impacts:
Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield
Description
Brief/Intro
In current implementation for oracle-contract.get_price, while function is_pyth_price_stale_or_outside_confidence return true in main.sw#L88, Redstone price feed will be used.
However there is a flaw when using Redstone price feed that might lead stale price being used.
Vulnerability Details
According to oracle-contract.get_price, when redstone is used, redstone.read_timestamp will be used as the price 's publish timestamp.
And redstone.read_timestamp will be checked against with current_time in main.sw#L107
The issue is that redstone.read_timestamp uses Unix timestamp, but Fule's timestamp function returns TAI64 format timestamp
Quoting from timestamp's implementation
From above code, we can see that timestamp() returns [The TAI64 timestamp of the current block.] (https://github.com/FuelLabs/sway/blob/6d9065b8d762a39eb475562426a2d4ed17d92d00/sway-lib-std/src/block.sw#L47)
According to redstone_adapter.read_timestamp, the function uses
storage.timestampas return value.And
storage.timestampis written by redstone_adapter.sw#L139 inredstone_adapter.overwrite_pricesfunction.redstone_adapter.overwrite_pricesis called byredstone_adapter.write_pricesin redstone_adapter.sw#L96Now we'll check how
timestampis returned in redstone_adapter.sw#L95In redstone_adapter.process_payload, a
configvar is created withconfig.block_timestampset toget_unix_timestamp()get_unix_timestamp() is defined as:
From here, we know that config.block_timestamp is UNIX time.
Back to
redstone_adapter.process_payload, in redstone_adapter.sw#L150,process_inputis called, andprocess_inputis defined in processor.process_input.
In processor.sw#L32,
timestampis returned byconfig.validate_timestampsfunction.config.validate_timestampsis defined in config_validation.sw#L27-L43
In config_validation.sw#L28-L29, the payload's timestamp and self.block_timestamp(which is UNIX timestamp) are passed to
validate_timestampfunction.According to validate_timestamp's implemention, we can get see that
payload's timestampin step9 should be UNIX timestamp format.
Impact Details
As I described above, when is_pyth_price_stale_or_outside_confidence returns true, Redstone can't work as expected.
References
Add any relevant links to documentation or code
Proof of Concept
Proof of Concept
The following POC is used to demonstrate that when is_pyth_price_stale_or_outside_confidence returns true, Redstone's oracle will be used.
Please put the following patch in contracts/oracle-contract/tests/authorization.rs and run
Last updated
Was this helpful?