Skip to content

feat: add packed calldata update for ~24% calldata savings#265

Open
TuDo1403 wants to merge 2 commits intoStork-Oracle:mainfrom
TuDo1403:feat/packed-calldata-update
Open

feat: add packed calldata update for ~24% calldata savings#265
TuDo1403 wants to merge 2 commits intoStork-Oracle:mainfrom
TuDo1403:feat/packed-calldata-update

Conversation

@TuDo1403
Copy link
Copy Markdown

@TuDo1403 TuDo1403 commented Mar 20, 2026

Summary

  • Add LibCodec library that packs TemporalNumericValueInput into a flat uint256[] with 6 words per entry, packing v flag (1 bit), timestampNs (63 bits), and quantizedValue (192 bits) into a single word with zero wasted bits

Test plan

  • Foundry fuzz tests (1000 runs each) for single/multi-entry encode/decode roundtrip
  • Calldata roundtrip via manual word construction
  • Edge cases: empty input, invalid length revert, invalid v revert
  • int192 extremes (min, max, negative values)
  • Calldata size comparison test: 2628 → 1988 bytes for 10 entries (~24% savings, ~8% calldata gas)
  • Hardhat compilation verified

Add LibCodec library that packs TemporalNumericValueInput into a flat
uint256[] with 6 words per entry (vs ~9 ABI-encoded words). Packs v
flag, timestampNs, and quantizedValue into a single word with zero
wasted bits.

- Add updateTemporalNumericValuesV1Packed(uint256[]) entry point
- Add compress() helper for off-chain struct-to-packed conversion
- Extract shared verify+update logic into _verifyAndUpdate()
- Add Foundry fuzz tests for encode/decode roundtrip correctness
Copy link
Copy Markdown
Contributor

@akawalsky akawalsky left a comment

Choose a reason for hiding this comment

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

Great work - left a few comments. Going to get a review from @harryrackmil as well.

uint256 len = inputs.length;
words = new uint256[](len * WORDS_PER_ENTRY);

for (uint256 i; i < len; ++i) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Lets add an invariant to this loop to ensure timestampNs is actually 63 bits. Practically speaking we should be safe but it would be good to make this future proof (at least until 2262)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Let's bump the version in this file to 1.0.6. That way our pusher will be able to easily determine which function to use.

This will require small test changes in UpgradeableStork.ts

function updateTemporalNumericValuesV1(
StorkStructs.TemporalNumericValueInput[] calldata updateData
) public payable {
_verifyAndUpdate(updateData);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Worth noting that converting this calldata to memory will have some gas impact on this function call, but should be negligible compared to signature recovery. Overall I'm fine encouraging the newer method in favor of code simplification.

harryrackmil
harryrackmil previously approved these changes Mar 24, 2026
- add 63-bit timestampNs overflow check in LibCodec.encode
- bump version to 1.0.6
- convert Foundry tests to Hardhat TypeScript, remove foundry.toml
- assert exact 640-byte savings in calldata size test
- fix comment: 6 words per entry, not 7
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.

3 participants