Skip to content

Conversation

@Amxx
Copy link
Collaborator

@Amxx Amxx commented Apr 4, 2024

Will be usefull for processing "packed" values such as accountGasLimits and gasFees as defined in ERC-4337

PR Checklist

  • Tests
  • Documentation
  • Changeset entry (run npx changeset add)

@Amxx Amxx requested a review from ernestognw April 4, 2024 18:54
@changeset-bot
Copy link

changeset-bot bot commented Apr 4, 2024

🦋 Changeset detected

Latest commit: 39add0f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
openzeppelin-solidity Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

* @dev Helper library packing and unpacking multiple values into bytes32
*/
library Packing {
type Uint128x2 is bytes32;
Copy link
Collaborator Author

@Amxx Amxx Apr 4, 2024

Choose a reason for hiding this comment

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

For now we only have (uint128, uint128) <> bytes32, but we can imagine having other types, such as uint64x4

Everything here is designed to scale to other types.

Copy link
Member

@ernestognw ernestognw left a comment

Choose a reason for hiding this comment

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

Neat! I left only one comment regarding the high and low functions in the context of other types. Also, how would we name other types like uint64|uint64|uint128?

Comment on lines 26 to 39
/// @dev Split a Uint128x2 into two uint128
function split(Uint128x2 self) internal pure returns (uint128, uint128) {
return (high(self), low(self));
}

/// @dev Get the first element of a Uint128x2 (high part)
function high(Uint128x2 self) internal pure returns (uint128) {
return uint128(bytes16(Uint128x2.unwrap(self)));
}

/// @dev Get the second element of a Uint128x2 (low part)
function low(Uint128x2 self) internal pure returns (uint128) {
return uint128(uint256(Uint128x2.unwrap(self)));
}
Copy link
Member

Choose a reason for hiding this comment

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

high and low don't make much sense in the context of another type like Uint64x4, what do you think of only having a single split() function?:

Suggested change
/// @dev Split a Uint128x2 into two uint128
function split(Uint128x2 self) internal pure returns (uint128, uint128) {
return (high(self), low(self));
}
/// @dev Get the first element of a Uint128x2 (high part)
function high(Uint128x2 self) internal pure returns (uint128) {
return uint128(bytes16(Uint128x2.unwrap(self)));
}
/// @dev Get the second element of a Uint128x2 (low part)
function low(Uint128x2 self) internal pure returns (uint128) {
return uint128(uint256(Uint128x2.unwrap(self)));
}
/// @dev Split a Uint128x2 into two uint128
function split(Uint128x2 self) internal pure returns (uint128, uint128) {
return (
uint128(bytes16(Uint128x2.unwrap(self))),
uint128(uint256(Uint128x2.unwrap(self)))
)
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

There are places where doing a full split, and keeping only part of the result is a bit more expensive, and also less clean in terms of code.

I would keep these two function, but we can rename them.

I considered first() and second(), which may scale better

Copy link
Member

@ernestognw ernestognw Apr 4, 2024

Choose a reason for hiding this comment

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

Right, also I realized it would be easy to reach a Stack too deep error if we pack too many values, so I'd be in favor of having single getters.

Agree with first and second, but the distinction with high and low is that the former doesn't express the order (i.e. first ltr or rtl?). Shall we make it explicit? Maybe by exposing first() and firstRtl() Edit: Nah, let's keep first and second and be explicit in the Natspec

@ernestognw
Copy link
Member

Also, how would we name other types like uint64|uint64|uint128?

Just realized that if we have an Uint64x2, we can pack 4 of those in a Uint128x2 . Similar for every other combination down to the boolean. Great!

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