//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;
abstract contract AbstractProxy {
fallback() external payable {
_forward();
}
receive() external payable {
_forward();
}
function _forward() internal {
address implementation = _getImplementation();
// solhint-disable-next-line no-inline-assembly
assembly {
calldatacopy(0, 0, calldatasize())
let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
returndatacopy(0, 0, returndatasize())
switch result
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
function _getImplementation() internal view virtual returns (address);
}
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;
import "./SafeCast.sol";
/**
* @title Utility library used to represent "decimals" (fixed point numbers) with integers, with two different levels of precision.
*
* They are represented by N * UNIT, where UNIT is the number of decimals of precision in the representation.
*
* Examples:
* 1) Given UNIT = 100
* then if A = 50, A represents the decimal 0.50
* 2) Given UNIT = 1000000000000000000
* then if A = 500000000000000000, A represents the decimal 0.500000000000000000
*
* Note: An accompanying naming convention of the postfix "D<Precision>" is helpful with this utility. I.e. if a variable "myValue" represents a low resolution decimal, it should be named "myValueD18", and if it was a high resolution decimal "myValueD27". While scaling, intermediate precision decimals like "myValue45" could arise. Non-decimals should have no postfix, i.e. just "myValue".
*
* Important: Multiplication and division operations are currently not supported for high precision decimals. Using these operations on them will yield incorrect results and fail silently.
*/
library DecimalMath {
using SafeCastU256 for uint256;
using SafeCastI256 for int256;
// solhint-disable numcast/safe-cast
// Numbers representing 1.0 (low precision).
uint256 public constant UNIT = 1e18;
int256 public constant UNIT_INT = int256(UNIT);
uint128 public constant UNIT_UINT128 = uint128(UNIT);
int128 public constant UNIT_INT128 = int128(UNIT_INT);
// Numbers representing 1.0 (high precision).
uint256 public constant UNIT_PRECISE = 1e27;
int256 public constant UNIT_PRECISE_INT = int256(UNIT_PRECISE);
int128 public constant UNIT_PRECISE_INT128 = int128(UNIT_PRECISE_INT);
// Precision scaling, (used to scale down/up from one precision to the other).
uint256 public constant PRECISION_FACTOR = 9; // 27 - 18 = 9 :)
// solhint-enable numcast/safe-cast
// -----------------
// uint256
// -----------------
/**
* @dev Multiplies two low precision decimals.
*
* Since the two numbers are assumed to be fixed point numbers,
* (x * UNIT) * (y * UNIT) = x * y * UNIT ^ 2,
* the result is divided by UNIT to remove double scaling.
*/
function mulDecimal(uint256 x, uint256 y) internal pure returns (uint256 z) {
return (x * y) / UNIT;
}
/**
* @dev Divides two low precision decimals.
*
* Since the two numbers are assumed to be fixed point numbers,
* (x * UNIT) / (y * UNIT) = x / y (Decimal representation is lost),
* x is first scaled up to end up with a decimal representation.
*/
function divDecimal(uint256 x, uint256 y) internal pure returns (uint256 z) {
return (x * UNIT) / y;
}
/**
* @dev Scales up a value.
*
* E.g. if value is not a decimal, a scale up by 18 makes it a low precision decimal.
* If value is a low precision decimal, a scale up by 9 makes it a high precision decimal.
*/
function upscale(uint256 x, uint256 factor) internal pure returns (uint256) {
return x * 10 ** factor;
}
/**
* @dev Scales down a value.
*
* E.g. if value is a high precision decimal, a scale down by 9 makes it a low precision decimal.
* If value is a low precision decimal, a scale down by 9 makes it a regular integer.
*
* Scaling down a regular integer would not make sense.
*/
function downscale(uint256 x, uint256 factor) internal pure returns (uint256) {
return x / 10 ** factor;
}
// -----------------
// uint128
// -----------------
// Note: Overloading doesn't seem to work for similar types, i.e. int256 and int128, uint256 and uint128, etc, so explicitly naming the functions differently here.
/**
* @dev See mulDecimal for uint256.
*/
function mulDecimalUint128(uint128 x, uint128 y) internal pure returns (uint128) {
return (x * y) / UNIT_UINT128;
}
/**
* @dev See divDecimal for uint256.
*/
function divDecimalUint128(uint128 x, uint128 y) internal pure returns (uint128) {
return (x * UNIT_UINT128) / y;
}
/**
* @dev See upscale for uint256.
*/
function upscaleUint128(uint128 x, uint256 factor) internal pure returns (uint128) {
return x * (10 ** factor).to128();
}
/**
* @dev See downscale for uint256.
*/
function downscaleUint128(uint128 x, uint256 factor) internal pure returns (uint128) {
return x / (10 ** factor).to128();
}
// -----------------
// int256
// -----------------
/**
* @dev See mulDecimal for uint256.
*/
function mulDecimal(int256 x, int256 y) internal pure returns (int256) {
return (x * y) / UNIT_INT;
}
/**
* @dev See divDecimal for uint256.
*/
function divDecimal(int256 x, int256 y) internal pure returns (int256) {
return (x * UNIT_INT) / y;
}
/**
* @dev See upscale for uint256.
*/
function upscale(int256 x, uint256 factor) internal pure returns (int256) {
return x * (10 ** factor).toInt();
}
/**
* @dev See downscale for uint256.
*/
function downscale(int256 x, uint256 factor) internal pure returns (int256) {
return x / (10 ** factor).toInt();
}
// -----------------
// int128
// -----------------
/**
* @dev See mulDecimal for uint256.
*/
function mulDecimalInt128(int128 x, int128 y) internal pure returns (int128) {
return (x * y) / UNIT_INT128;
}
/**
* @dev See divDecimal for uint256.
*/
function divDecimalInt128(int128 x, int128 y) internal pure returns (int128) {
return (x * UNIT_INT128) / y;
}
/**
* @dev See upscale for uint256.
*/
function upscaleInt128(int128 x, uint256 factor) internal pure returns (int128) {
return x * ((10 ** factor).toInt()).to128();
}
/**
* @dev See downscale for uint256.
*/
function downscaleInt128(int128 x, uint256 factor) internal pure returns (int128) {
return x / ((10 ** factor).toInt().to128());
}
}
pragma solidity >=0.8.11 <0.9.0;
interface IERC7412 {
error FeeRequired(uint256 amount);
error OracleDataRequired(address oracleContract, bytes oracleQuery);
function oracleId() external view returns (bytes32 oracleId);
function fulfillOracleQuery(bytes calldata signedOffchainData) external payable;
}
// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.11 <0.9.0;
/// @title Consume prices from the Pyth Network (https://pyth.network/).
/// @dev Please refer to the guidance at https://docs.pyth.network/consumers/best-practices for how to consume prices safely.
/// @author Pyth Data Association
interface IPyth {
/// @dev Emitted when an update for price feed with `id` is processed successfully.
/// @param id The Pyth Price Feed ID.
/// @param fresh True if the price update is more recent and stored.
/// @param chainId ID of the source chain that the batch price update containing this price.
/// This value comes from Wormhole, and you can find the corresponding chains at https://docs.wormholenetwork.com/wormhole/contracts.
/// @param sequenceNumber Sequence number of the batch price update containing this price.
/// @param lastPublishTime Publish time of the previously stored price.
/// @param publishTime Publish time of the given price update.
/// @param price Price of the given price update.
/// @param conf Confidence interval of the given price update.
event PriceFeedUpdate(
bytes32 indexed id,
bool indexed fresh,
uint16 chainId,
uint64 sequenceNumber,
uint256 lastPublishTime,
uint256 publishTime,
int64 price,
uint64 conf
);
/// @dev Emitted when a batch price update is processed successfully.
/// @param chainId ID of the source chain that the batch price update comes from.
/// @param sequenceNumber Sequence number of the batch price update.
/// @param batchSize Number of prices within the batch price update.
/// @param freshPricesInBatch Number of prices that were more recent and were stored.
event BatchPriceFeedUpdate(
uint16 chainId,
uint64 sequenceNumber,
uint256 batchSize,
uint256 freshPricesInBatch
);
/// @dev Emitted when a call to `updatePriceFeeds` is processed successfully.
/// @param sender Sender of the call (`msg.sender`).
/// @param batchCount Number of batches that this function processed.
/// @param fee Amount of paid fee for updating the prices.
event UpdatePriceFeeds(address indexed sender, uint256 batchCount, uint256 fee);
/// @notice Returns the period (in seconds) that a price feed is considered valid since its publish time
function getValidTimePeriod() external view returns (uint256 validTimePeriod);
/// @notice Returns the price and confidence interval.
/// @dev Reverts if the price has not been updated within the last `getValidTimePeriod()` seconds.
/// @param id The Pyth Price Feed ID of which to fetch the price and confidence interval.
/// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.
function getPrice(bytes32 id) external view returns (PythStructs.Price memory price);
/// @notice Returns the exponentially-weighted moving average price and confidence interval.
/// @dev Reverts if the EMA price is not available.
/// @param id The Pyth Price Feed ID of which to fetch the EMA price and confidence interval.
/// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.
function getEmaPrice(bytes32 id) external view returns (PythStructs.Price memory price);
/// @notice Returns the price of a price feed without any sanity checks.
/// @dev This function returns the most recent price update in this contract without any recency checks.
/// This function is unsafe as the returned price update may be arbitrarily far in the past.
///
/// Users of this function should check the `publishTime` in the price to ensure that the returned price is
/// sufficiently recent for their application. If you are considering using this function, it may be
/// safer / easier to use either `getPrice` or `getPriceNoOlderThan`.
/// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.
function getPriceUnsafe(bytes32 id) external view returns (PythStructs.Price memory price);
/// @notice Returns the price that is no older than `age` seconds of the current time.
/// @dev This function is a sanity-checked version of `getPriceUnsafe` which is useful in
/// applications that require a sufficiently-recent price. Reverts if the price wasn't updated sufficiently
/// recently.
/// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.
function getPriceNoOlderThan(
bytes32 id,
uint256 age
) external view returns (PythStructs.Price memory price);
/// @notice Returns the exponentially-weighted moving average price of a price feed without any sanity checks.
/// @dev This function returns the same price as `getEmaPrice` in the case where the price is available.
/// However, if the price is not recent this function returns the latest available price.
///
/// The returned price can be from arbitrarily far in the past; this function makes no guarantees that
/// the returned price is recent or useful for any particular application.
///
/// Users of this function should check the `publishTime` in the price to ensure that the returned price is
/// sufficiently recent for their application. If you are considering using this function, it may be
/// safer / easier to use either `getEmaPrice` or `getEmaPriceNoOlderThan`.
/// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.
function getEmaPriceUnsafe(bytes32 id) external view returns (PythStructs.Price memory price);
/// @notice Returns the exponentially-weighted moving average price that is no older than `age` seconds
/// of the current time.
/// @dev This function is a sanity-checked version of `getEmaPriceUnsafe` which is useful in
/// applications that require a sufficiently-recent price. Reverts if the price wasn't updated sufficiently
/// recently.
/// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.
function getEmaPriceNoOlderThan(
bytes32 id,
uint256 age
) external view returns (PythStructs.Price memory price);
/// @notice Update price feeds with given update messages.
/// This method requires the caller to pay a fee in wei; the required fee can be computed by calling
/// `getUpdateFee` with the length of the `updateData` array.
/// Prices will be updated if they are more recent than the current stored prices.
/// The call will succeed even if the update is not the most recent.
/// @dev Reverts if the transferred fee is not sufficient or the updateData is invalid.
/// @param updateData Array of price update data.
function updatePriceFeeds(bytes[] calldata updateData) external payable;
/// @notice Wrapper around updatePriceFeeds that rejects fast if a price update is not necessary. A price update is
/// necessary if the current on-chain publishTime is older than the given publishTime. It relies solely on the
/// given `publishTimes` for the price feeds and does not read the actual price update publish time within `updateData`.
///
/// This method requires the caller to pay a fee in wei; the required fee can be computed by calling
/// `getUpdateFee` with the length of the `updateData` array.
///
/// `priceIds` and `publishTimes` are two arrays with the same size that correspond to senders known publishTime
/// of each priceId when calling this method. If all of price feeds within `priceIds` have updated and have
/// a newer or equal publish time than the given publish time, it will reject the transaction to save gas.
/// Otherwise, it calls updatePriceFeeds method to update the prices.
///
/// @dev Reverts if update is not needed or the transferred fee is not sufficient or the updateData is invalid.
/// @param updateData Array of price update data.
/// @param priceIds Array of price ids.
/// @param publishTimes Array of publishTimes. `publishTimes[i]` corresponds to known `publishTime` of `priceIds[i]`
function updatePriceFeedsIfNecessary(
bytes[] calldata updateData,
bytes32[] calldata priceIds,
uint64[] calldata publishTimes
) external payable;
/// @notice Returns the required fee to update an array of price updates.
/// @param updateData Array of price update data.
/// @return feeAmount The required fee in Wei.
function getUpdateFee(bytes[] calldata updateData) external view returns (uint256 feeAmount);
/// @notice Similar to `parsePriceFeedUpdates` but ensures the updates returned are
/// the first updates published in minPublishTime. That is, if there are multiple updates for a given timestamp,
/// this method will return the first update.
///
///
/// @dev Reverts if the transferred fee is not sufficient or the updateData is invalid or there is
/// no update for any of the given `priceIds` within the given time range and uniqueness condition.
/// @param updateData Array of price update data.
/// @param priceIds Array of price ids.
/// @param minPublishTime minimum acceptable publishTime for the given `priceIds`.
/// @param maxPublishTime maximum acceptable publishTime for the given `priceIds`.
/// @return priceFeeds Array of the price feeds corresponding to the given `priceIds` (with the same order).
function parsePriceFeedUpdatesUnique(
bytes[] calldata updateData,
bytes32[] calldata priceIds,
uint64 minPublishTime,
uint64 maxPublishTime
) external payable returns (PythStructs.PriceFeed[] memory priceFeeds);
}
contract PythStructs {
// A price with a degree of uncertainty, represented as a price +- a confidence interval.
//
// The confidence interval roughly corresponds to the standard error of a normal distribution.
// Both the price and confidence are stored in a fixed-point numeric representation,
// `x * (10^expo)`, where `expo` is the exponent.
//
// Please refer to the documentation at https://docs.pyth.network/consumers/best-practices for how
// to how this price safely.
struct Price {
// Price
int64 price;
// Confidence interval around the price
uint64 conf;
// Price exponent
int32 expo;
// Unix timestamp describing when the price was published
uint256 publishTime;
}
// PriceFeed represents a current aggregate price from pyth publisher feeds.
struct PriceFeed {
// The price ID.
bytes32 id;
// Latest available price
Price price;
// Latest available exponentially-weighted moving average price
Price emaPrice;
}
}
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;
import {PythStructs, IPyth} from "@synthetixio/oracle-manager/contracts/interfaces/external/IPyth.sol";
/**
* @title Benchmark price storage for a specific price id.
*/
library Price {
struct Data {
/**
* @dev The price mapping for timestamps
*/
mapping(uint64 => PythStructs.Price) benchmarkPrices;
}
function load(bytes32 priceId) internal pure returns (Data storage price) {
bytes32 s = keccak256(abi.encode("io.synthetix.pyth-erc7412-wrapper.price", priceId));
assembly {
price.slot := s
}
}
}
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;
import {DecimalMath} from "@synthetixio/core-contracts/contracts/utils/DecimalMath.sol";
import {SafeCastI256} from "@synthetixio/core-contracts/contracts/utils/SafeCast.sol";
import {AbstractProxy} from "@synthetixio/core-contracts/contracts/proxy/AbstractProxy.sol";
import {PythStructs, IPyth} from "@synthetixio/oracle-manager/contracts/interfaces/external/IPyth.sol";
import {IERC7412} from "./interfaces/IERC7412.sol";
import {Price} from "./storage/Price.sol";
contract PythERC7412Wrapper is IERC7412, AbstractProxy {
using DecimalMath for int64;
using SafeCastI256 for int256;
int256 private constant PRECISION = 18;
error NotSupported(uint8 updateType);
address public immutable pythAddress;
constructor(address _pythAddress) {
pythAddress = _pythAddress;
}
function _getImplementation() internal view override returns (address) {
return pythAddress;
}
function oracleId() external pure returns (bytes32) {
return bytes32("PYTH");
}
function getBenchmarkPrice(
bytes32 priceId,
uint64 requestedTime
) external view returns (int256) {
PythStructs.Price memory priceData = Price.load(priceId).benchmarkPrices[requestedTime];
if (priceData.price > 0) {
return _getScaledPrice(priceData.price, priceData.expo);
}
revert OracleDataRequired(
// solhint-disable-next-line numcast/safe-cast
address(this),
abi.encode(
// solhint-disable-next-line numcast/safe-cast
uint8(2), // PythQuery::Benchmark tag
// solhint-disable-next-line numcast/safe-cast
uint64(requestedTime),
[priceId]
)
);
}
function getLatestPrice(
bytes32 priceId,
uint256 stalenessTolerance
) external view returns (int256) {
IPyth pyth = IPyth(pythAddress);
PythStructs.Price memory pythData = pyth.getPriceUnsafe(priceId);
if (block.timestamp <= stalenessTolerance + pythData.publishTime) {
return _getScaledPrice(pythData.price, pythData.expo);
}
//price too stale
revert OracleDataRequired(
address(this),
abi.encode(
// solhint-disable-next-line numcast/safe-cast
uint8(1),
// solhint-disable-next-line numcast/safe-cast
uint64(stalenessTolerance),
[priceId]
)
);
}
function fulfillOracleQuery(bytes memory signedOffchainData) external payable {
IPyth pyth = IPyth(pythAddress);
uint8 updateType = abi.decode(signedOffchainData, (uint8));
if (updateType == 1) {
(
uint8 _updateType,
uint64 stalenessTolerance,
bytes32[] memory priceIds,
bytes[] memory updateData
) = abi.decode(signedOffchainData, (uint8, uint64, bytes32[], bytes[]));
// solhint-disable-next-line numcast/safe-cast
uint64 minAcceptedPublishTime = uint64(block.timestamp) - stalenessTolerance;
uint64[] memory publishTimes = new uint64[](priceIds.length);
for (uint256 i = 0; i < priceIds.length; i++) {
publishTimes[i] = minAcceptedPublishTime;
}
try
pyth.updatePriceFeedsIfNecessary{value: msg.value}(
updateData,
priceIds,
publishTimes
)
{} catch (bytes memory reason) {
if (_isFeeRequired(reason)) {
revert FeeRequired(pyth.getUpdateFee(updateData));
} else {
uint256 len = reason.length;
assembly {
revert(add(reason, 0x20), len)
}
}
}
} else if (updateType == 2) {
(
uint8 _updateType,
uint64 timestamp,
bytes32[] memory priceIds,
bytes[] memory updateData
) = abi.decode(signedOffchainData, (uint8, uint64, bytes32[], bytes[]));
try
pyth.parsePriceFeedUpdatesUnique{value: msg.value}(
updateData,
priceIds,
timestamp,
type(uint64).max
)
returns (PythStructs.PriceFeed[] memory priceFeeds) {
for (uint256 i = 0; i < priceFeeds.length; i++) {
Price.load(priceIds[i]).benchmarkPrices[timestamp] = priceFeeds[i].price;
}
} catch (bytes memory reason) {
if (_isFeeRequired(reason)) {
revert FeeRequired(pyth.getUpdateFee(updateData));
} else {
uint256 len = reason.length;
assembly {
revert(add(reason, 0x20), len)
}
}
}
} else {
revert NotSupported(updateType);
}
}
function _isFeeRequired(bytes memory reason) private pure returns (bool) {
return
reason.length == 4 &&
reason[0] == 0x02 &&
reason[1] == 0x5d &&
reason[2] == 0xbd &&
reason[3] == 0xd4;
}
/**
* @dev gets scaled price. Borrowed from PythNode.sol.
*/
function _getScaledPrice(int64 price, int32 expo) private pure returns (int256) {
int256 factor = PRECISION + expo;
return factor > 0 ? price.upscale(factor.toUint()) : price.downscale((-factor).toUint());
}
}
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;
/**
* Utilities that convert numeric types avoiding silent overflows.
*/
import "./SafeCast/SafeCastU32.sol";
import "./SafeCast/SafeCastI32.sol";
import "./SafeCast/SafeCastI24.sol";
import "./SafeCast/SafeCastU56.sol";
import "./SafeCast/SafeCastI56.sol";
import "./SafeCast/SafeCastU64.sol";
import "./SafeCast/SafeCastI64.sol";
import "./SafeCast/SafeCastI128.sol";
import "./SafeCast/SafeCastI256.sol";
import "./SafeCast/SafeCastU128.sol";
import "./SafeCast/SafeCastU160.sol";
import "./SafeCast/SafeCastU256.sol";
import "./SafeCast/SafeCastAddress.sol";
import "./SafeCast/SafeCastBytes32.sol";
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;
/**
* @title See SafeCast.sol.
*/
library SafeCastAddress {
function toBytes32(address x) internal pure returns (bytes32) {
return bytes32(uint256(uint160(x)));
}
}
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;
/**
* @title See SafeCast.sol.
*/
library SafeCastBytes32 {
function toAddress(bytes32 x) internal pure returns (address) {
return address(uint160(uint256(x)));
}
function toUint(bytes32 x) internal pure returns (uint) {
return uint(x);
}
}
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;
/**
* @title See SafeCast.sol.
*/
library SafeCastI128 {
error OverflowInt128ToUint128();
error OverflowInt128ToInt32();
function toUint(int128 x) internal pure returns (uint128) {
// ----------------<==============o==============>-----------------
// ----------------xxxxxxxxxxxxxxxo===============>----------------
if (x < 0) {
revert OverflowInt128ToUint128();
}
return uint128(x);
}
function to256(int128 x) internal pure returns (int256) {
return int256(x);
}
function to32(int128 x) internal pure returns (int32) {
// ----------------<==============o==============>-----------------
// ----------------xxxxxxxxxxxx<==o==>xxxxxxxxxxxx-----------------
if (x < int256(type(int32).min) || x > int256(type(int32).max)) {
revert OverflowInt128ToInt32();
}
return int32(x);
}
function zero() internal pure returns (int128) {
return int128(0);
}
}
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;
/**
* @title See SafeCast.sol.
*/
library SafeCastI24 {
function to256(int24 x) internal pure returns (int256) {
return int256(x);
}
}
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;
/**
* @title See SafeCast.sol.
*/
library SafeCastI256 {
error OverflowInt256ToUint256();
error OverflowInt256ToInt128();
error OverflowInt256ToInt24();
function to128(int256 x) internal pure returns (int128) {
// ----<==========================o===========================>----
// ----xxxxxxxxxxxx<==============o==============>xxxxxxxxxxxxx----
if (x < int256(type(int128).min) || x > int256(type(int128).max)) {
revert OverflowInt256ToInt128();
}
return int128(x);
}
function to24(int256 x) internal pure returns (int24) {
// ----<==========================o===========================>----
// ----xxxxxxxxxxxxxxxxxxxx<======o=======>xxxxxxxxxxxxxxxxxxxx----
if (x < int256(type(int24).min) || x > int256(type(int24).max)) {
revert OverflowInt256ToInt24();
}
return int24(x);
}
function toUint(int256 x) internal pure returns (uint256) {
// ----<==========================o===========================>----
// ----xxxxxxxxxxxxxxxxxxxxxxxxxxxo===============================>
if (x < 0) {
revert OverflowInt256ToUint256();
}
return uint256(x);
}
function zero() internal pure returns (int256) {
return int256(0);
}
}
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;
/**
* @title See SafeCast.sol.
*/
library SafeCastI32 {
error OverflowInt32ToUint32();
function toUint(int32 x) internal pure returns (uint32) {
// ----------------------<========o========>----------------------
// ----------------------xxxxxxxxxo=========>----------------------
if (x < 0) {
revert OverflowInt32ToUint32();
}
return uint32(x);
}
}
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;
/**
* @title See SafeCast.sol.
*/
library SafeCastI56 {
error OverflowInt56ToInt24();
function to24(int56 x) internal pure returns (int24) {
// ----------------------<========o========>-----------------------
// ----------------------xxx<=====o=====>xxx-----------------------
if (x < int256(type(int24).min) || x > int256(type(int24).max)) {
revert OverflowInt56ToInt24();
}
return int24(x);
}
}
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;
/**
* @title See SafeCast.sol.
*/
library SafeCastI64 {
error OverflowInt64ToUint64();
function toUint(int64 x) internal pure returns (uint64) {
// ----------------------<========o========>----------------------
// ----------------------xxxxxxxxxo=========>----------------------
if (x < 0) {
revert OverflowInt64ToUint64();
}
return uint64(x);
}
}
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;
/**
* @title See SafeCast.sol.
*/
library SafeCastU128 {
error OverflowUint128ToInt128();
function to256(uint128 x) internal pure returns (uint256) {
return uint256(x);
}
function toInt(uint128 x) internal pure returns (int128) {
// -------------------------------o===============>----------------
// ----------------<==============o==============>x----------------
if (x > uint128(type(int128).max)) {
revert OverflowUint128ToInt128();
}
return int128(x);
}
function toBytes32(uint128 x) internal pure returns (bytes32) {
return bytes32(uint256(x));
}
}
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;
/**
* @title See SafeCast.sol.
*/
library SafeCastU160 {
function to256(uint160 x) internal pure returns (uint256) {
return uint256(x);
}
}
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;
/**
* @title See SafeCast.sol.
*/
library SafeCastU256 {
error OverflowUint256ToUint128();
error OverflowUint256ToInt256();
error OverflowUint256ToUint64();
error OverflowUint256ToUint32();
error OverflowUint256ToUint160();
function to128(uint256 x) internal pure returns (uint128) {
// -------------------------------o===============================>
// -------------------------------o===============>xxxxxxxxxxxxxxxx
if (x > type(uint128).max) {
revert OverflowUint256ToUint128();
}
return uint128(x);
}
function to64(uint256 x) internal pure returns (uint64) {
// -------------------------------o===============================>
// -------------------------------o======>xxxxxxxxxxxxxxxxxxxxxxxxx
if (x > type(uint64).max) {
revert OverflowUint256ToUint64();
}
return uint64(x);
}
function to32(uint256 x) internal pure returns (uint32) {
// -------------------------------o===============================>
// -------------------------------o===>xxxxxxxxxxxxxxxxxxxxxxxxxxxx
if (x > type(uint32).max) {
revert OverflowUint256ToUint32();
}
return uint32(x);
}
function to160(uint256 x) internal pure returns (uint160) {
// -------------------------------o===============================>
// -------------------------------o==================>xxxxxxxxxxxxx
if (x > type(uint160).max) {
revert OverflowUint256ToUint160();
}
return uint160(x);
}
function toBytes32(uint256 x) internal pure returns (bytes32) {
return bytes32(x);
}
function toInt(uint256 x) internal pure returns (int256) {
// -------------------------------o===============================>
// ----<==========================o===========================>xxxx
if (x > uint256(type(int256).max)) {
revert OverflowUint256ToInt256();
}
return int256(x);
}
}
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;
/**
* @title See SafeCast.sol.
*/
library SafeCastU32 {
error OverflowUint32ToInt32();
function toInt(uint32 x) internal pure returns (int32) {
// -------------------------------o=========>----------------------
// ----------------------<========o========>x----------------------
if (x > uint32(type(int32).max)) {
revert OverflowUint32ToInt32();
}
return int32(x);
}
function to256(uint32 x) internal pure returns (uint256) {
return uint256(x);
}
function to56(uint32 x) internal pure returns (uint56) {
return uint56(x);
}
}
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;
/**
* @title See SafeCast.sol.
*/
library SafeCastU56 {
error OverflowUint56ToInt56();
function toInt(uint56 x) internal pure returns (int56) {
// -------------------------------o=========>----------------------
// ----------------------<========o========>x----------------------
if (x > uint56(type(int56).max)) {
revert OverflowUint56ToInt56();
}
return int56(x);
}
}
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;
/**
* @title See SafeCast.sol.
*/
library SafeCastU64 {
error OverflowUint64ToInt64();
function toInt(uint64 x) internal pure returns (int64) {
// -------------------------------o=========>----------------------
// ----------------------<========o========>x----------------------
if (x > uint64(type(int64).max)) {
revert OverflowUint64ToInt64();
}
return int64(x);
}
function to256(uint64 x) internal pure returns (uint256) {
return uint256(x);
}
}
{
"compilationTarget": {
"contracts/PythERC7412Wrapper.sol": "PythERC7412Wrapper"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_pythAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeeRequired","type":"error"},{"inputs":[{"internalType":"uint8","name":"updateType","type":"uint8"}],"name":"NotSupported","type":"error"},{"inputs":[{"internalType":"address","name":"oracleContract","type":"address"},{"internalType":"bytes","name":"oracleQuery","type":"bytes"}],"name":"OracleDataRequired","type":"error"},{"inputs":[],"name":"OverflowInt256ToUint256","type":"error"},{"inputs":[],"name":"OverflowUint256ToInt256","type":"error"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"bytes","name":"signedOffchainData","type":"bytes"}],"name":"fulfillOracleQuery","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"priceId","type":"bytes32"},{"internalType":"uint64","name":"requestedTime","type":"uint64"}],"name":"getBenchmarkPrice","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"priceId","type":"bytes32"},{"internalType":"uint256","name":"stalenessTolerance","type":"uint256"}],"name":"getLatestPrice","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oracleId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"pythAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]