The PriceConverterPyth
library is a Solidity library designed to convert token amounts on the base network to USD by leveraging the Pyth Network's price feeds. This utility allows developers to easily fetch real-time price data for ETH/USD and convert token values into USD within their smart contracts.
- Fetch ETH/USD Price: The library fetches the latest ETH/USD exchange rate from the Pyth Network.
- Convert ETH to USD: Converts a given amount of ETH into its equivalent USD value using the fetched exchange rate.
- Integration with Pyth Network: The library is integrated with the Pyth Network, a trusted source for real-time, decentralized price feeds.
- Solidity version
^0.8.19
- The Pyth Network's price feed contracts available on the base network.
function getPrice(
bytes32 priceFeedId,
IPyth pythFeed,
bytes[] calldata priceUpdate
) internal returns (uint256 price)
-
Description: Fetches the current ETH/USD price from the Pyth Network's price feed.
-
Parameters:
priceFeedId
: The unique identifier of the price feed (e.g., ETH/USD feed ID).pythFeed
: The address of the Pyth Network's price feed contract.priceUpdate
: An array of price update data that is used to update the on-chain price feed.
-
Returns: The current ETH/USD exchange rate, scaled to 18 decimal places.
-
Process:
- The function first submits a price update to the Pyth contract using the provided
priceUpdate
data, paying the necessary fee. - It then retrieves the latest ETH/USD price using the
priceFeedId
and returns the price scaled to 18 decimal places.
- The function first submits a price update to the Pyth contract using the provided
-
Important Notes:
- Ensure the price update is submitted before fetching the price. Failing to do so might result in outdated or incorrect data, leading to transaction failures.
function getConversionRate(
uint256 ETHAmount,
bytes32 priceFeedId,
IPyth pythFeed,
bytes[] calldata priceUpdate
) internal returns (uint256 ETHAmountInUsd)
-
Description: Converts a specified amount of ETH into its USD equivalent using the latest price data from the Pyth Network.
-
Parameters:
EthAmount
: The amount of ETH to be converted to USD.priceFeedId
: The unique identifier of the price feed (e.g., ETH/USD feed ID).pythFeed
: The address of the Pyth Network's price feed contract.priceUpdate
: An array of price update data used to update the on-chain price feed.
-
Returns: The equivalent USD value of the given ETH amount.
-
Process:
- The function first calls
getPrice()
to fetch the current ETH/USD exchange rate. - It then calculates the USD equivalent of the provided ETH amount by multiplying the exchange rate with
ETHAmount
and dividing by 1e18 (to account for the scaling factor).
- The function first calls
import "./PriceConverterPyth.sol";
contract MyContract {
using PriceConverterPyth for uint256;
IPyth public pythFeed;
bytes32 public priceFeedId;
constructor(IPyth _pythFeed, bytes32 _priceFeedId) {
pythFeed = _pythFeed;
priceFeedId = _priceFeedId;
}
function convertETHToUsd(uint256 ETHAmount, bytes[] calldata priceUpdate) external returns (uint256) {
return ETHAmount.getConversionRate(priceFeedId, pythFeed, priceUpdate);
}
}
The PriceConverterPyth
library provides a simple and effective way to interact with the Pyth Network's price feeds on the base blockchain. By using this library, developers can easily fetch real-time ETH/USD prices and convert token amounts into USD, enabling more dynamic and responsive smart contract applications.
This project contains the CreatePriceUpdateData
contract, a utility for generating price feed update data using the Pyth Network's mock implementation (MockPyth
). The contract is designed to create and validate price data updates on test networks, leveraging configuration data provided by a separate NetworkConfig
contract.
The key purpose of this contract is to generate and simulate price feed updates, which can be used to test and develop applications that rely on Pyth Network price feeds.
- forge-std/Script.sol: Used to create and execute scripts with Foundry, a popular Ethereum development framework.
- MockPyth.sol: A mock implementation of the Pyth Network's on-chain components, used for testing purposes.
- PythStructs.sol: Contains the struct definitions used by Pyth Network contracts.
- NetworkConfig.s.sol: Script that manages network-specific configuration, including price feed IDs and mock Pyth addresses.
- Constants.sol: Contains constant values used throughout the contract.
- CreatePriceUpdateData__InvalidPriceFeedId: Thrown when the price feed ID provided is invalid or empty.
- CreatePriceUpdateData__PriceFeedIdDoesNotExist: Thrown when the specified price feed ID does not exist in the mock Pyth contract.
- CreatePriceUpdateData__InvalidMockAddress: Thrown when the mock Pyth address is invalid (e.g., an address of
0x0
).
This contract contains the following key functions:
-
run()
: This is the main entry point for the script. It callscreatePriceUpdateDataConfig()
to generate the price update data. -
createPriceUpdateDataConfig()
: This function fetches the price feed ID and mock Pyth address from theNetworkConfig
contract and passes them tocreatePriceData()
to generate the price update data. -
createPriceData()
: This function:- Validates the provided price feed ID and mock Pyth address.
- Checks if the specified price feed ID exists in the mock Pyth contract.
- Uses the validated data to generate price feed update data using the
MockPyth.createPriceFeedUpdateData()
function. - Optionally tests the mock Pyth functionality, such as retrieving the valid time period.
-
setPriceData()
: This function creates and returns aPriceData
struct populated with the price data constants defined in theConstants
contract.
The PriceData
struct represents the price data required to update a price feed:
id
: The unique identifier of the price feed.price
: The current price of the asset.conf
: The confidence interval for the price.expo
: The exponent used to scale the price (e.g., -8 means the price is in 10^-8 units).emaPrice
: The exponentially weighted moving average of the price.emaConf
: The confidence interval for the EMA price.publishTime
: The timestamp when the price data was published.
VALID_TIME_PERIOD
: The period within which the price update is valid, set to 2 days from the current block timestamp.SINGLE_UPDATE_FEE_IN_WEI
: The fee for a single price update, set to 0.01 ETH.- Price Data Constants: Various constants related to the price data, such as
PRICE
,CONF
,EXPO
,EMA_PRICE
,EMA_CONF
, andPUBLISH_TIME
.
-
Compilation: Compile the contract using the Foundry toolchain.
forge compile
-
Execution: Run the script to generate the price update data on a specific network.
forge script script/CreatePriceUpdateData.s.sol:CreatePriceUpdateData -f <network>
Replace
<network>
with your desired RPC URL or network name. -
Testing: You can test the contract's functionality by interacting with the
MockPyth
contract and observing the price feed updates generated.
- Ensure the
NetworkConfig
contract is properly configured for your test network, including correct price feed IDs and mock Pyth addresses. - Verify that the
MockPyth
contract is deployed and contains the necessary price feeds before running the script.
The CreatePriceUpdateData
contract is a helpful tool for developers working with the Pyth Network, allowing them to simulate price feed updates in a controlled test environment. By leveraging mock contracts and network-specific configurations, developers can efficiently test and validate their applications that depend on Pyth's price feeds.
Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.
Foundry consists of:
- Forge: Ethereum testing framework (like Truffle, Hardhat and DappTools).
- Cast: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data.
- Anvil: Local Ethereum node, akin to Ganache, Hardhat Network.
- Chisel: Fast, utilitarian, and verbose solidity REPL.
$ forge build
$ forge test
$ forge fmt
$ forge snapshot
$ anvil
$ forge script script/Counter.s.sol:CounterScript --rpc-url <your_rpc_url> --private-key <your_private_key>
$ cast <subcommand>
$ forge --help
$ anvil --help
$ cast --help