Skip to content

Commit 0928e43

Browse files
committed
chore(pricefeed) Add docs for cross rate
1 parent d0c50d0 commit 0928e43

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+
"combine-two-price-feeds": "Combine Two Price Feeds / Derive a 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+
# Combine Two Price Feeds / Derive a 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+
Pyth provides [`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+
### ⚠️ Things to Keep in Mind
39+
40+
- The function reverts if either price is **negative**, or if any exponent is **less than -255**.
41+
- The result is rounded down. If the result is smaller than 1 in the given `targetExponent{:jsx}`, it will return 0.
42+
- Confidence intervals are not derived in this function. If needed, you have to derive them manually.
43+
- Reverts with `PythErrors.ExponentOverflow{:jsx}` if `targetExponent + expo1 - expo2{:jsx}` is outside the range **[-58, 58]**.
44+
45+
## Example
46+
47+
```solidity copy
48+
pragma solidity ^0.8.0;
49+
50+
import "@pythnetwork/pyth-sdk-solidity/IPyth.sol";
51+
import "@pythnetwork/pyth-sdk-solidity/PythStructs.sol";
52+
import "@pythnetwork/pyth-sdk-solidity/PythUtils.sol";
53+
54+
contract ExampleCrossRate {
55+
IPyth public pyth;
56+
57+
constructor(address _pythContract) {
58+
pyth = IPyth(_pythContract);
59+
}
60+
61+
// priceUpdate should include both price feeds
62+
function getEthPerEur(
63+
bytes32 ethUsdId,
64+
bytes32 eurUsdId,
65+
bytes[] calldata priceUpdate
66+
) external payable returns (int64 price, int32 expo) {
67+
// Update both feeds
68+
uint fee = pyth.getUpdateFee(priceUpdate);
69+
pyth.updatePriceFeeds{ value: fee }(priceUpdate);
70+
71+
// Fetch prices
72+
PythStructs.Price memory ethUsd = pyth.getPriceNoOlderThan(ethUsdId, 60);
73+
PythStructs.Price memory eurUsd = pyth.getPriceNoOlderThan(eurUsdId, 60);
74+
75+
// Derive ETH/EUR = ETH/USD ÷ EUR/USD
76+
int32 targetExpo = -8;
77+
int64 ethPerEur = PythUtils.deriveCrossRate(
78+
ethUsd.price,
79+
ethUsd.expo,
80+
eurUsd.price,
81+
eurUsd.expo,
82+
targetExpo
83+
);
84+
85+
return (ethPerEur, targetExpo);
86+
}
87+
}
88+
89+
```
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)