Skip to content
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

Packing overrides and filler #221

Closed
wants to merge 8 commits into from
Closed

Packing overrides and filler #221

wants to merge 8 commits into from

Conversation

hensha256
Copy link
Collaborator

@hensha256 hensha256 commented Feb 1, 2024

Very open to renaming things in this PR

extrabytes is used to encode any or all of exclusiveFiller, inputOverride, and outputOverrides.
If none of these 3 fields are needed for a tranasction, extraBytes is empty

In the case where at least 1 of these values is included:
First byte:

  • bit 1: bool hasExclusiveFiller
  • bit 2: bool hasInputOverride
  • bit3: bool hasOutputOverrides
  • bits 4-8: outputOverrides.length

After this first byte, the relevant fields are appended in the order exclusiveFiller, inputOverride, outputOverrides.
exclusiveFiller is 20 bytes, inputOverride is 32 bytes, and outputOverrides is (32 * outputOverrides.length) bytes.


An exactInput trade with an exclusive filler (assuming the filler overrides the outputs), should save:

  • 32 bytes input override
  • 32 bytes output overrides length
  • 12 bytes of address passing
  • and adds 1 byte
    --> saving 75 x 0 bytes

This isn't huge gas savings on mainnet (though is still decent as you can see) but is much higher savings on L2s

@hensha256 hensha256 marked this pull request as ready for review February 2, 2024 15:09
Copy link
Collaborator

@marktoda marktoda left a comment

Choose a reason for hiding this comment

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

siick!!

// The time at which price becomes static
uint256 decayEndTime;
// Encoded exclusiveFiller, inputOverride, and outputOverrides, where needed
// First byte: fff0 0000 where f is a flag signalling inclusion of the 3 variables
Copy link
Collaborator

Choose a reason for hiding this comment

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

and the last 5 bits are the length of outputs array?

bytes32 constant OUTPUTS_LENGTH_FLAG_MASK = 0x1F00000000000000000000000000000000000000000000000000000000000000;

// "True" first bit of byte 1 signals that there is an exclusive filler
function hasExclusiveFiller(bytes memory extraData) internal pure returns (bool flag) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

would it be even cheaper to just take a bytes1 flags or bytes32 flags here? so we only have to do the mload once? or is that canceled out by the masking and expansion?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

oh yeah good point i'll try that

pure
returns (address filler, uint256 inputOverride, uint256[] memory outputOverrides)
{
if (extraData.length == 0) return (filler, inputOverride, outputOverrides);
Copy link
Collaborator

Choose a reason for hiding this comment

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

can just do empty return right?

Copy link
Collaborator

Choose a reason for hiding this comment

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

also in what case would we ever have 0 length?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

length==0 when there is no exclusive filler, no inputOverrides, and no outputoverrides... so i guess an open order where someone fills the exact amount in the order itself


if (hasExclusiveFiller(extraData)) {
// + 20 bytes for address, - 32 bytes for the length offset
require(extraData.length >= bytesOffset - 12);
Copy link
Collaborator

Choose a reason for hiding this comment

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

can we do a nicer custom err here?

Comment on lines +5 to +8
// The time at which the DutchOutputs start decaying
uint256 decayStartTime;
// The time at which price becomes static
uint256 decayEndTime;
Copy link
Collaborator

Choose a reason for hiding this comment

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

any benefit to including these in extraData as well and having them be only uint32s? that may also allow slightly cleaner reading as you could just have parseInputOverrides(bytes encodedCosignerData) -> CosignerData or something

Comment on lines +285 to +287
uint256 inputOverride,
uint256 outputOverride,
uint256 outputOverrideLength
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think you can take arrays in the fuzzer if you want to test different amounts

@marktoda
Copy link
Collaborator

skipping for now

@marktoda marktoda closed this Feb 21, 2024
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