| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- // SPDX-License-Identifier: Apache-2.0
- pragma solidity ^0.8.0;
- import "./AbstractPyth.sol";
- import "./PythStructs.sol";
- import "./PythErrors.sol";
- contract MockPyth is AbstractPyth {
- mapping(bytes32 => PythStructs.PriceFeed) priceFeeds;
- uint singleUpdateFeeInWei;
- uint validTimePeriod;
- constructor(uint _validTimePeriod, uint _singleUpdateFeeInWei) {
- singleUpdateFeeInWei = _singleUpdateFeeInWei;
- validTimePeriod = _validTimePeriod;
- }
- function queryPriceFeed(
- bytes32 id
- ) public view override returns (PythStructs.PriceFeed memory priceFeed) {
- if (priceFeeds[id].id == 0) revert PythErrors.PriceFeedNotFound();
- return priceFeeds[id];
- }
- function priceFeedExists(bytes32 id) public view override returns (bool) {
- return (priceFeeds[id].id != 0);
- }
- function getValidTimePeriod() public view override returns (uint) {
- return validTimePeriod;
- }
- // Takes an array of encoded price feeds and stores them.
- // You can create this data either by calling createPriceFeedUpdateData or
- // by using web3.js or ethers abi utilities.
- // @note: The updateData expected here is different from the one used in the main contract.
- // In particular, the expected format is:
- // [
- // abi.encode(
- // PythStructs.PriceFeed(
- // bytes32 id,
- // PythStructs.Price price,
- // PythStructs.Price emaPrice
- // ),
- // uint64 prevPublishTime
- // )
- // ]
- function updatePriceFeeds(
- bytes[] calldata updateData
- ) public payable override {
- uint requiredFee = getUpdateFee(updateData);
- if (msg.value < requiredFee) revert PythErrors.InsufficientFee();
- for (uint i = 0; i < updateData.length; i++) {
- PythStructs.PriceFeed memory priceFeed = abi.decode(
- updateData[i],
- (PythStructs.PriceFeed)
- );
- uint lastPublishTime = priceFeeds[priceFeed.id].price.publishTime;
- if (lastPublishTime < priceFeed.price.publishTime) {
- // Price information is more recent than the existing price information.
- priceFeeds[priceFeed.id] = priceFeed;
- emit PriceFeedUpdate(
- priceFeed.id,
- uint64(priceFeed.price.publishTime),
- priceFeed.price.price,
- priceFeed.price.conf
- );
- }
- }
- }
- function getUpdateFee(
- bytes[] calldata updateData
- ) public view override returns (uint feeAmount) {
- return singleUpdateFeeInWei * updateData.length;
- }
- function parsePriceFeedUpdatesInternal(
- bytes[] calldata updateData,
- bytes32[] calldata priceIds,
- uint64 minPublishTime,
- uint64 maxPublishTime,
- bool unique
- ) internal returns (PythStructs.PriceFeed[] memory feeds) {
- uint requiredFee = getUpdateFee(updateData);
- if (msg.value < requiredFee) revert PythErrors.InsufficientFee();
- feeds = new PythStructs.PriceFeed[](priceIds.length);
- for (uint i = 0; i < priceIds.length; i++) {
- for (uint j = 0; j < updateData.length; j++) {
- uint64 prevPublishTime;
- (feeds[i], prevPublishTime) = abi.decode(
- updateData[j],
- (PythStructs.PriceFeed, uint64)
- );
- uint publishTime = feeds[i].price.publishTime;
- if (priceFeeds[feeds[i].id].price.publishTime < publishTime) {
- priceFeeds[feeds[i].id] = feeds[i];
- emit PriceFeedUpdate(
- feeds[i].id,
- uint64(publishTime),
- feeds[i].price.price,
- feeds[i].price.conf
- );
- }
- if (feeds[i].id == priceIds[i]) {
- if (
- minPublishTime <= publishTime &&
- publishTime <= maxPublishTime &&
- (!unique || prevPublishTime < minPublishTime)
- ) {
- break;
- } else {
- feeds[i].id = 0;
- }
- }
- }
- if (feeds[i].id != priceIds[i])
- revert PythErrors.PriceFeedNotFoundWithinRange();
- }
- }
- function parsePriceFeedUpdates(
- bytes[] calldata updateData,
- bytes32[] calldata priceIds,
- uint64 minPublishTime,
- uint64 maxPublishTime
- ) external payable override returns (PythStructs.PriceFeed[] memory feeds) {
- return
- parsePriceFeedUpdatesInternal(
- updateData,
- priceIds,
- minPublishTime,
- maxPublishTime,
- false
- );
- }
- function parsePriceFeedUpdatesUnique(
- bytes[] calldata updateData,
- bytes32[] calldata priceIds,
- uint64 minPublishTime,
- uint64 maxPublishTime
- ) external payable override returns (PythStructs.PriceFeed[] memory feeds) {
- return
- parsePriceFeedUpdatesInternal(
- updateData,
- priceIds,
- minPublishTime,
- maxPublishTime,
- true
- );
- }
- function createPriceFeedUpdateData(
- bytes32 id,
- int64 price,
- uint64 conf,
- int32 expo,
- int64 emaPrice,
- uint64 emaConf,
- uint64 publishTime,
- uint64 prevPublishTime
- ) public pure returns (bytes memory priceFeedData) {
- PythStructs.PriceFeed memory priceFeed;
- priceFeed.id = id;
- priceFeed.price.price = price;
- priceFeed.price.conf = conf;
- priceFeed.price.expo = expo;
- priceFeed.price.publishTime = publishTime;
- priceFeed.emaPrice.price = emaPrice;
- priceFeed.emaPrice.conf = emaConf;
- priceFeed.emaPrice.expo = expo;
- priceFeed.emaPrice.publishTime = publishTime;
- priceFeedData = abi.encode(priceFeed, prevPublishTime);
- }
- }
|