Skip to content

Conversation

legion2002
Copy link
Contributor

@legion2002 legion2002 commented Sep 3, 2025

Description

The PR adds a new calldata optimized execution mode to ERC7821 which allows you to batch calls to the same target address, without sending the redundant "to" variable in each call.

Even if the address(0) optimization is used in calldata, for each call there is still a 4 gas overhead.
With this PR, you can compress the calldata down to the theoretical optimal, this is specially useful when you want to do highly optimized self calls.

Note: The address(0) replacement is still available with the common to field passed.

Checklist

Ensure you completed all of the steps below before submitting your pull request:

  • Ran forge fmt?
  • Ran forge test?

Pull requests with an incomplete checklist will be thrown out.

@atarpara
Copy link
Collaborator

atarpara commented Sep 4, 2025

@legion2002 bounds checks for CallSansTo[] is missing.

@Vectorized
Copy link
Owner

i’ll work on this after i wake up. brb sleep now.

@legion2002
Copy link
Contributor Author

Thanks @atarpara, I maybe missing something, but doesn't solady intentionally skip these bounds checks, as mentioned here?

I was following the same pattern as how we treat the standard Call struct, do we do bounds check for that somewhere?

@Vectorized
Copy link
Owner

Vectorized commented Sep 5, 2025

@howydev @legion2002 @atarpara

Upon further thinking, this is actually more non-trivial than expected.

First, ERC7821 does not make any bounds checks. This is intentional (Solady tries to cater to max performance under expert use, freedom to bear footguns).

We expect that users who require checks use LibERC7579.decodeBatchAndOpData and LibERC7579.decodeBatch.

The reason why ERC7821 does not have the checks is because we expect that the executionData will be checked once via LibERC7579 somewhere else, when it matters. For Ithaca's case, that check is in the the _computeDigest functions, since in cases with both validation AND execution, the offsets of executionData can be different.

If we want to put this on ERC7821, we will need LibERC7579.isCompactBatch and LibERC7579.decodeCompactBatch.

Maybe can do this just on the Orchestrator, if all the intents will be done via the Orchestrator. I'm currently thinking if this is actually worth the effort. There is some overhead in detecting a compact representation, and re-encoding it. I'm thinking of simply abi.encode(address to, bytes[] calldatas). Also, the updated re-encoding function will need all the hardcore checks.

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