Skip to content

Commit 2d2c731

Browse files
authored
chore(pricefeed) Add docs for cross rate (#729)
* chore(pricefeed) Add docs for cross rate * requested updates * pre-commit
1 parent d0c50d0 commit 2d2c731

File tree

2 files changed

+102
-0
lines changed

2 files changed

+102
-0
lines changed

pages/price-feeds/_meta.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"use-real-time-data": "Use Real-Time Price Data",
2727
"fetch-price-updates": "Fetch Price Updates",
2828
"schedule-price-updates": "Schedule Price Updates",
29+
"derive-cross-rate": "Derive Cross Rate",
2930
"migrate-an-app-to-pyth": "Migrate an App to Pyth",
3031
"use-pyth-for-morpho": "Use Pyth for Morpho Markets",
3132
"publish-data": "Publish Data",
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import { Callout } from "nextra/components";
2+
3+
# Derive Cross Rate
4+
5+
This guide shows how to combine two price feeds to derive a cross rate. These are also known as "synthetic" price feeds.
6+
Cross rates or Synthetic Price feeds are useful for trading pairs that are not directly supported by Pyth.
7+
8+
<Callout type="info" emoji="ℹ️">
9+
This guide is for developers who are building applications on **EVM
10+
blockchains** using **solidity only**.
11+
</Callout>
12+
13+
## Example
14+
15+
For example, if you want to trade the price of **`ETH/EUR{:jsx}`**, which is not directly supported by Pyth, you can combine the price of **`ETH/USD{:jsx}`** and **`EUR/USD{:jsx}`** to derive the price of **`ETH/EUR{:jsx}`**.
16+
17+
$$
18+
\large{\text{ETH/EUR} = \text{ETH/USD} \div \text{EUR/USD}}
19+
$$
20+
21+
## Derive a cross rate
22+
23+
The Pyth Solidity SDKprovides [`deriveCrossRate`](https://github.com/pyth-network/pyth-crosschain/blob/main/target_chains/ethereum/sdk/solidity/PythUtils.sol#L77) function to combine two price feeds.
24+
This method is available in [Pyth solidity SDK](https://github.com/pyth-network/pyth-crosschain/tree/main/target_chains/ethereum/sdk/solidity).
25+
26+
This method takes the following parameters:
27+
28+
- `price1`: The first price feed value, representing a / b (e.g., ETH/USD). Must be a signed integer (int64).
29+
- `expo1`: The exponent for price1, indicating the number of decimal places.
30+
- `price2`: The second price feed value, representing c / b (e.g., EUR/USD).
31+
- `expo2`: The exponent for price2.
32+
- `targetExponent`: The desired exponent for the output cross rate (a / c). The result will be scaled to this exponent.
33+
34+
Returns:
35+
36+
- `crossRate`: The computed cross rate (a / c), scaled to targetExponent.
37+
38+
## Example
39+
40+
```solidity copy
41+
pragma solidity ^0.8.0;
42+
43+
import "@pythnetwork/pyth-sdk-solidity/IPyth.sol";
44+
import "@pythnetwork/pyth-sdk-solidity/PythStructs.sol";
45+
import "@pythnetwork/pyth-sdk-solidity/PythUtils.sol";
46+
47+
contract ExampleCrossRate {
48+
IPyth public pyth;
49+
50+
constructor(address _pythContract) {
51+
pyth = IPyth(_pythContract);
52+
}
53+
54+
// priceUpdate should include both price feeds
55+
function getEthPerEur(
56+
bytes32 ethUsdId,
57+
bytes32 eurUsdId,
58+
bytes[] calldata priceUpdate
59+
) external payable returns (int64 price, int32 expo) {
60+
// Update both feeds
61+
uint fee = pyth.getUpdateFee(priceUpdate);
62+
pyth.updatePriceFeeds{ value: fee }(priceUpdate);
63+
64+
// Fetch prices
65+
PythStructs.Price memory ethUsd = pyth.getPriceNoOlderThan(ethUsdId, 60);
66+
PythStructs.Price memory eurUsd = pyth.getPriceNoOlderThan(eurUsdId, 60);
67+
68+
// Derive ETH/EUR = ETH/USD / EUR/USD
69+
int32 targetExpo = -8;
70+
int64 ethPerEur = PythUtils.deriveCrossRate(
71+
ethUsd.price,
72+
ethUsd.expo,
73+
eurUsd.price,
74+
eurUsd.expo,
75+
targetExpo
76+
);
77+
78+
return (ethPerEur, targetExpo);
79+
}
80+
}
81+
82+
```
83+
84+
### ⚠️ Things to Keep in Mind
85+
86+
- The function reverts if either price is **negative**, or if any exponent is **less than -255**.
87+
- The result is rounded down. If the result is smaller than 1 in the given `targetExponent{:jsx}`, it will return 0.
88+
- Confidence intervals are not derived in this function. If needed, you have to derive them manually.
89+
- Reverts with `PythErrors.ExponentOverflow{:jsx}` if `targetExponent + expo1 - expo2{:jsx}` is outside the range **[-58, 58]**.
90+
91+
## Additional Resources
92+
93+
You may find these additional resources helpful.
94+
95+
### How to use real-time data in EVM contracts
96+
97+
The [How to use real-time data in EVM contracts](./use-real-time-data/evm) guide provides a step-by-step guide on how to use real-time data in EVM contracts.
98+
99+
### Price Feed IDs
100+
101+
The [Price Feed IDs](https://www.pyth.network/developers/price-feed-ids) page lists the price feed IDs for each asset supported by Pyth.

0 commit comments

Comments
 (0)