Skip to content
This repository was archived by the owner on May 6, 2025. It is now read-only.

Update the SDK for downstream optimizations #32

Merged
merged 8 commits into from
Nov 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions AbstractPyth.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,33 +16,33 @@ abstract contract AbstractPyth is IPyth {

function getValidTimePeriod() public view virtual override returns (uint validTimePeriod);

function getPrice(bytes32 id) external view override returns (PythStructs.Price memory price) {
function getPrice(bytes32 id) external virtual view override returns (PythStructs.Price memory price) {
return getPriceNoOlderThan(id, getValidTimePeriod());
}

function getEmaPrice(bytes32 id) external view override returns (PythStructs.Price memory price) {
function getEmaPrice(bytes32 id) external virtual view override returns (PythStructs.Price memory price) {
return getEmaPriceNoOlderThan(id, getValidTimePeriod());
}

function getPriceUnsafe(bytes32 id) public view override returns (PythStructs.Price memory price) {
function getPriceUnsafe(bytes32 id) public virtual view override returns (PythStructs.Price memory price) {
PythStructs.PriceFeed memory priceFeed = queryPriceFeed(id);
return priceFeed.price;
}

function getPriceNoOlderThan(bytes32 id, uint age) public view override returns (PythStructs.Price memory price) {
function getPriceNoOlderThan(bytes32 id, uint age) public virtual view override returns (PythStructs.Price memory price) {
price = getPriceUnsafe(id);

require(diff(block.timestamp, price.publishTime) <= age, "no price available which is recent enough");

return price;
}

function getEmaPriceUnsafe(bytes32 id) public view override returns (PythStructs.Price memory price) {
function getEmaPriceUnsafe(bytes32 id) public virtual view override returns (PythStructs.Price memory price) {
PythStructs.PriceFeed memory priceFeed = queryPriceFeed(id);
return priceFeed.emaPrice;
}

function getEmaPriceNoOlderThan(bytes32 id, uint age) public view override returns (PythStructs.Price memory price) {
function getEmaPriceNoOlderThan(bytes32 id, uint age) public virtual view override returns (PythStructs.Price memory price) {
price = getEmaPriceUnsafe(id);

require(diff(block.timestamp, price.publishTime) <= age, "no ema price available which is recent enough");
Expand All @@ -62,7 +62,7 @@ abstract contract AbstractPyth is IPyth {
// Access modifier is overridden to public to be able to call it locally.
function updatePriceFeeds(bytes[] calldata updateData) public virtual payable override;

function updatePriceFeedsIfNecessary(bytes[] calldata updateData, bytes32[] calldata priceIds, uint64[] calldata publishTimes) external payable override {
function updatePriceFeedsIfNecessary(bytes[] calldata updateData, bytes32[] calldata priceIds, uint64[] calldata publishTimes) external virtual payable override {
require(priceIds.length == publishTimes.length, "priceIds and publishTimes arrays should have same length");

bool updateNeeded = false;
Expand Down
28 changes: 2 additions & 26 deletions IPyth.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,12 @@
pragma solidity ^0.8.0;

import "./PythStructs.sol";
import "./IPythEvents.sol";

/// @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, uint lastPublishTime, uint 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, uint batchSize, uint 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, uint batchCount, uint fee);

interface IPyth is IPythEvents {
/// @notice Returns the period (in seconds) that a price feed is considered valid since its publish time
function getValidTimePeriod() external view returns (uint validTimePeriod);

Expand Down
18 changes: 18 additions & 0 deletions IPythEvents.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

/// @title IPythEvents contains the events that Pyth contract emits.
/// @dev This interface can be used for listening to the updates for off-chain and testing purposes.
interface IPythEvents {
/// @dev Emitted when the price feed with `id` has received a fresh update.
/// @param id The Pyth Price Feed ID.
/// @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, uint64 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.
event BatchPriceFeedUpdate(uint16 chainId, uint64 sequenceNumber);
}
14 changes: 2 additions & 12 deletions MockPyth.sol
Original file line number Diff line number Diff line change
Expand Up @@ -41,37 +41,27 @@ contract MockPyth is AbstractPyth {
require(success, "failed to transfer update fee");
}

uint freshPrices = 0;

// Chain ID is id of the source chain that the price update comes from. Since it is just a mock contract
// We set it to 1.
uint16 chainId = 1;

for(uint i = 0; i < updateData.length; i++) {
PythStructs.PriceFeed memory priceFeed = abi.decode(updateData[i], (PythStructs.PriceFeed));

bool fresh = false;
uint lastPublishTime = priceFeeds[priceFeed.id].price.publishTime;

if (lastPublishTime < priceFeed.price.publishTime) {
// Price information is more recent than the existing price information.
fresh = true;
priceFeeds[priceFeed.id] = priceFeed;
freshPrices += 1;
emit PriceFeedUpdate(priceFeed.id, uint64(lastPublishTime), priceFeed.price.price, priceFeed.price.conf);
}

emit PriceFeedUpdate(priceFeed.id, fresh, chainId, sequenceNumber, priceFeed.price.publishTime,
lastPublishTime, priceFeed.price.price, priceFeed.price.conf);
}

// In the real contract, the input of this function contains multiple batches that each contain multiple prices.
// This event is emitted when a batch is processed. In this mock contract we consider there is only one batch of prices.
// Each batch has (chainId, sequenceNumber) as it's unique identifier. Here chainId is set to 1 and an increasing sequence number is used.
emit BatchPriceFeedUpdate(chainId, sequenceNumber, updateData.length, freshPrices);
emit BatchPriceFeedUpdate(chainId, sequenceNumber);
sequenceNumber += 1;

// There is only 1 batch of prices
emit UpdatePriceFeeds(msg.sender, 1, requiredFee);
}

function getUpdateFee(bytes[] calldata updateData) public override view returns (uint feeAmount) {
Expand Down
63 changes: 1 addition & 62 deletions abis/AbstractPyth.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,6 @@
"internalType": "uint64",
"name": "sequenceNumber",
"type": "uint64"
},
{
"indexed": false,
"internalType": "uint256",
"name": "batchSize",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "freshPricesInBatch",
"type": "uint256"
}
],
"name": "BatchPriceFeedUpdate",
Expand All @@ -39,35 +27,11 @@
"name": "id",
"type": "bytes32"
},
{
"indexed": true,
"internalType": "bool",
"name": "fresh",
"type": "bool"
},
{
"indexed": false,
"internalType": "uint16",
"name": "chainId",
"type": "uint16"
},
{
"indexed": false,
"internalType": "uint64",
"name": "sequenceNumber",
"type": "uint64"
},
{
"indexed": false,
"internalType": "uint256",
"name": "lastPublishTime",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "publishTime",
"type": "uint256"
"type": "uint64"
},
{
"indexed": false,
Expand All @@ -85,31 +49,6 @@
"name": "PriceFeedUpdate",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "sender",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "batchCount",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "fee",
"type": "uint256"
}
],
"name": "UpdatePriceFeeds",
"type": "event"
},
{
"inputs": [
{
Expand Down
63 changes: 1 addition & 62 deletions abis/IPyth.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,6 @@
"internalType": "uint64",
"name": "sequenceNumber",
"type": "uint64"
},
{
"indexed": false,
"internalType": "uint256",
"name": "batchSize",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "freshPricesInBatch",
"type": "uint256"
}
],
"name": "BatchPriceFeedUpdate",
Expand All @@ -39,35 +27,11 @@
"name": "id",
"type": "bytes32"
},
{
"indexed": true,
"internalType": "bool",
"name": "fresh",
"type": "bool"
},
{
"indexed": false,
"internalType": "uint16",
"name": "chainId",
"type": "uint16"
},
{
"indexed": false,
"internalType": "uint64",
"name": "sequenceNumber",
"type": "uint64"
},
{
"indexed": false,
"internalType": "uint256",
"name": "lastPublishTime",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "publishTime",
"type": "uint256"
"type": "uint64"
},
{
"indexed": false,
Expand All @@ -85,31 +49,6 @@
"name": "PriceFeedUpdate",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "sender",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "batchCount",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "fee",
"type": "uint256"
}
],
"name": "UpdatePriceFeeds",
"type": "event"
},
{
"inputs": [
{
Expand Down
52 changes: 52 additions & 0 deletions abis/IPythEvents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
[
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint16",
"name": "chainId",
"type": "uint16"
},
{
"indexed": false,
"internalType": "uint64",
"name": "sequenceNumber",
"type": "uint64"
}
],
"name": "BatchPriceFeedUpdate",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "bytes32",
"name": "id",
"type": "bytes32"
},
{
"indexed": false,
"internalType": "uint64",
"name": "publishTime",
"type": "uint64"
},
{
"indexed": false,
"internalType": "int64",
"name": "price",
"type": "int64"
},
{
"indexed": false,
"internalType": "uint64",
"name": "conf",
"type": "uint64"
}
],
"name": "PriceFeedUpdate",
"type": "event"
}
]
Loading