|
| 1 | +// SPDX-License-Identifier: LicenseRef-DCL-1.0 |
| 2 | +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd |
| 3 | +pragma solidity =0.8.25; |
| 4 | + |
| 5 | +import {PriceOracleV2} from "../../abstract/PriceOracleV2.sol"; |
| 6 | +import {IPyth} from "pyth-sdk/IPyth.sol"; |
| 7 | +import {PythStructs} from "pyth-sdk/PythStructs.sol"; |
| 8 | +import {LibDecimalFloat, Float} from "rain.math.float/lib/LibDecimalFloat.sol"; |
| 9 | + |
| 10 | +error NonPositivePrice(int256 price); |
| 11 | + |
| 12 | +contract PythOracle is PriceOracleV2 { |
| 13 | + bytes32 public immutable I_PRICE_FEED_ID; |
| 14 | + uint256 public immutable I_STALE_AFTER; |
| 15 | + IPyth public immutable I_PYTH_CONTRACT; |
| 16 | + |
| 17 | + function _price() internal virtual override returns (uint256) { |
| 18 | + PythStructs.Price memory price = I_PYTH_CONTRACT.getPriceNoOlderThan(I_PRICE_FEED_ID, I_STALE_AFTER); |
| 19 | + int256 conservativePrice = int256(price.price) - int256(uint256(price.conf)); |
| 20 | + if (conservativePrice <= 0) { |
| 21 | + revert NonPositivePrice(price.price); |
| 22 | + } |
| 23 | + // It is safe to pack lossless here because the price data uses only |
| 24 | + // 64 bits while we have 224 bits for a packed signed coefficient, and |
| 25 | + // the exponent bit size is the same for both. |
| 26 | + Float conservativePriceFloat = LibDecimalFloat.packLossless(conservativePrice, price.expo); |
| 27 | + // We ignore precision loss here, truncating towards zero. |
| 28 | + (uint256 price18,) = LibDecimalFloat.toFixedDecimalLossy(conservativePriceFloat, 18); |
| 29 | + return price18; |
| 30 | + } |
| 31 | +} |
0 commit comments