Skip to content

feat: stylus parse price feed updates fxn #2840

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 20 commits into
base: main
Choose a base branch
from

Conversation

ayushboss
Copy link
Contributor

@ayushboss ayushboss commented Jul 9, 2025

Summary

Implemented the parse price feed updates function for the stylus contract, and restructured the architecture of the update functions to deal with that.

Rationale

parsePriceFeedUpdates is a necessary component of the Pythnet API.

How has this been tested?

  • Current tests cover my changes
  • Added new tests
  • Manually tested the code

I have test cases validating these methods.

ayushboss and others added 14 commits July 7, 2025 13:55
…g vector indices

- Modified parse_price_feed_updates_internal to build a BTreeMap internally mapping price IDs to PriceInfoReturn
- Updated parse_price_feed_updates_with_config to return a vector with matching indices to input price_ids
- Added price_ids parameter to parse_price_feed_updates_internal function
- Maintained existing error handling and validation logic

Co-Authored-By: ayush.suresh@dourolabs.xyz <byteSlayer31037@gmail.com>
…y ordering

- parse_price_feed_updates_internal now returns Vec<([u8; 32], PriceInfoReturn)> without taking price_ids parameter
- parse_price_feed_updates_with_config converts internal result to BTreeMap for efficient lookup and returns ordered vector
- This enables update_price_feeds functions to use the dictionary directly as requested

Co-Authored-By: ayush.suresh@dourolabs.xyz <byteSlayer31037@gmail.com>
…eed data

- Extract price data from price_feed_message instead of reading from storage
- Fixes test failures where price data wasn't being processed correctly
- Maintains separation of concerns between parsing and storage updates

Co-Authored-By: ayush.suresh@dourolabs.xyz <byteSlayer31037@gmail.com>
- Add validation to check if publish times are within [min_allowed_publish_time, max_allowed_publish_time] range
- Return PythReceiverError::PriceFeedNotFoundWithinRange (error code 16) when publish times are outside allowed range
- Fix type casting from u64 to i64 for proper comparison with price_feed_message.publish_time

Co-Authored-By: ayush.suresh@dourolabs.xyz <byteSlayer31037@gmail.com>
…es_internal

- Add uniqueness checking logic when check_uniqueness parameter is true
- Require minAllowedPublishTime > prevPublishTime for uniqueness validation
- Return PythReceiverError::PriceFeedNotFoundWithinRange when uniqueness check fails
- Retrieve previous publish time from latest_price_info storage

Co-Authored-By: ayush.suresh@dourolabs.xyz <byteSlayer31037@gmail.com>
Copy link

vercel bot commented Jul 9, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
api-reference ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 11, 2025 8:53pm
component-library ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 11, 2025 8:53pm
developer-hub ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 11, 2025 8:53pm
entropy-debugger ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 11, 2025 8:53pm
entropy-explorer 🛑 Canceled (Inspect) Jul 11, 2025 8:53pm
insights 🛑 Canceled (Inspect) Jul 11, 2025 8:53pm
proposals 🛑 Canceled (Inspect) Jul 11, 2025 8:53pm
staking ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 11, 2025 8:53pm

… price values

- Fixed compilation errors by making all_parsed_price_pairs mutable
- Modified logic after first for loop to iterate through price pairs and preserve existing values
- Updated parse_price_feed_updates to wrap single update_data in vector
- All tests passing

Co-Authored-By: ayush.suresh@dourolabs.xyz <byteSlayer31037@gmail.com>
@ayushboss ayushboss marked this pull request as ready for review July 11, 2025 20:44
Comment on lines +227 to +233
_unique: bool,
) -> Result<Vec<([u8; 32], PriceInfoReturn)>, PythReceiverError> {
let price_pairs = self.parse_price_feed_updates_internal(
update_data,
min_publish_time,
max_publish_time,
false, // check_uniqueness
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not pass unique to parse_price_feed_updates_internal?

Comment on lines +445 to +452
let price_info_return = (
U64::from(publish_time),
I32::from_be_bytes(price_feed_message.exponent.to_be_bytes()),
I64::from_be_bytes(price_feed_message.price.to_be_bytes()),
U64::from(price_feed_message.conf),
I64::from_be_bytes(price_feed_message.ema_price.to_be_bytes()),
U64::from(price_feed_message.ema_conf),
);
Copy link
Contributor

@tejasbadadare tejasbadadare Jul 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noticed you're turning the signed ints to bytes and back again. There should be from/try_from impls for them as well, any reason you're going to bytes and back?

Comment on lines +272 to +275
fn get_total_fee(&self, total_num_updates: u64) -> U256 {
U256::from(total_num_updates).saturating_mul(self.single_update_fee_in_wei.get())
+ self.transaction_fee_in_wei.get()
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should just have get_update_fee(&self, update_data: Vec<Vec<u8>>) since the old version that just takes the update data length is deprecated

@@ -342,4 +342,14 @@ mod test {
multiple_updates_diff_vaa_results()[1]
);
}

#[motsu::test]
fn test_multiple_updates_same_id_updates_latest(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unfinished tests?

}

fn update_price_feeds_internal(
&mut self,
update_data: Vec<u8>,
) -> Result<(), PythReceiverError> {
_price_ids: Vec<[u8; 32]>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like price_ids is unused here because we don't pass it in parse_price_feed_updates_with_config -- we parse and update all the data, and then filter them using price_ids. There was a subtle griefing attack possibility with this behavior in the Pulse use case, but I don't think that's really a factor here and there are other mitigations (check_update_data_is_minimal.)

We can remove the _price_ids arg here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants