IPyth
interface and implementation do not follow the recommended best practices
Description
The documentation for the IPyth
public interface↗ suggest the following best practices:
Use products with at least 3 active publishers
Check the status of the product
Use the confidence interval to protect your users from price uncertainty
The first recommendation cannot be followed using only the functions exposed by IPyth
, and the documentation does not elaborate on what additional functions should be used.
IPyth
exposes the following three functions:
function getCurrentPrice(bytes32 id) external view returns (PythStructs.Price memory price);
function getEmaPrice(bytes32 id) external view returns (PythStructs.Price memory price);
function getPrevPriceUnsafe(bytes32 id) external view returns (PythStructs.Price memory price, uint64 publishTime);
PythStructs.Price
does not contain information about how many publishers contributed to the given price.
A user could still call queryPriceFeed
(a public function which is not part of IPyth
). This function returns an instance of PythStructs.PriceFeed
, a struct that contains fields that can hold the required information.
However, internally the contract does not copy this information from the price attestation.
function newPriceInfo(PythInternalStructs.PriceAttestation memory pa) private view returns (PythInternalStructs.PriceInfo memory info) {
info.attestationTime = pa.timestamp;
// [code shortened for brevity]
// These aren't sent in the wire format yet
info.priceFeed.numPublishers = 0;
info.priceFeed.maxNumPublishers = 0;
return info;
}
This comment appears to be incorrect with respect to the attestation program reviewed by Zellic. The attest
function creates instances of the PriceAttestation
struct using PriceAttestation::from_pyth_price_bytes
, which does set the num_publishers
and max_num_publishers
fields.
Impact
Consumers of Pyth data on Ethereum might not follow the documented best practices and use unreliable price information.
Recommendations
Modify the
IPyth
interface to provide a way for Pyth users to read how many publishers were aggregated to compute a given price.Modify
newPriceInfo
to read from the price attestation the number of publishers that contributed to the price
Remediation
The finding has been acknowledged by Pyth Data Foundation. Their official response is reproduced below:
Pyth Data Association acknowledges the finding, but doesn’t believe it has security implications. However, we may deploy a bug fix to address it.