feat: Yul bit-slicing engine, delegatecall forwarder, batch balance checker, G015 storage packer - #702
Merged
mijinummi merged 1 commit intoJul 29, 2026
Conversation
…ce checker, and G015 storage packer - YulBitSlice: extracts arbitrary bit-length slices from calldata buffers using pure Yul assembly, handling unaligned offsets and 32-byte word boundary straddling without intermediate memory copies. - YulProxyForwarder: minimal delegatecall forwarder that copies calldata, delegatecalls the implementation, and relays return data/revert reason verbatim, keeping proxy overhead to a fixed handful of opcodes. - BatchBalanceChecker: queries balanceOf across a token x account matrix in one call using staticcall in an assembly loop, building the selector once and tolerating reverting/non-contract targets without halting. - Rule G015 (gasguard-cli): storage_packer transformer that classifies state variables, reuses the existing storage_model packing algorithm, and rewrites contract source to group packable variables into shared slots while preserving comments and untouched code exactly. Wired up behind a new reorder-storage command alongside optimize-storage. Closes MDTechLabs#690 Closes MDTechLabs#691 Closes MDTechLabs#692 Closes MDTechLabs#695
|
@zoffunjunior381-jpg Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
2 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
contracts/utils/YulBitSlice.sol: pure-Yul library withextractBits(bytes calldata, bitOffset, bitLength)that reads arbitrary bit-length slices directly from calldata viacalldataload, handling slices that straddle a 32-byte word boundary, without copying the buffer into memory. Also adds a byte-alignedsliceBytesconvenience wrapper.contracts/proxy/YulProxyForwarder.sol: minimalfallback/receiveforwarder that doescalldatacopy→delegatecall(gas(), implementation, ...)→returndatacopy→return/revert, entirely in assembly, so proxied calls only pay for those four opcodes plus the delegatecall itself.contracts/utils/BatchBalanceChecker.sol:batchBalances(tokens, accounts)builds thebalanceOf(address)selector once, then loops over the token x account matrix withstaticcall, writing results into a flat memory array. Reverting or non-contract targets resolve to0instead of aborting the whole batch.gasguard-cliRule G015: newtransformers::storage_packermodule that classifies state variable declarations (reusing the existingstorage_modelpacking algorithm), then rewrites the contract source to group packable variables into shared 256-bit slots. Leading comments stay attached to their variable, and everything outside the declaration run (imports, structs, functions) is left byte-for-byte untouched. Wired up behind a newreorder-storageCLI command alongside the existingoptimize-storage. Also addedgasguard-cli/test/fixtures/storage_packing_transform.solas a worked example (5 slots → 2 slots).Assumptions / scope notes
contract/librarybody — it intentionally does not attempt a full AST rewrite of arbitrarily interleaved declarations, matching the lightweight text-based parsing style already used bycommands::optimize_storage.gasguard-cli/Cargo.tomlneeded an explicit[workspace]table added — the crate wasn't previously buildable/testable at all (cargo testfailed immediately with "current package believes it's in a workspace when it's not") because it isn't listed in the rootCargo.tomlworkspace members. This is a minimal, non-invasive fix so the new tests (and the crate generally) can actually run; it does not addgasguard-clito the root workspace.test/*.test.tsfiles for the new Solidity contracts follow the exact structure of the existingtest/utils/MappingResolver.test.tsand othertest/**/*.test.tsfiles in this repo — note that these files usevitestimports and are not currently picked up by thenpm test(jest) script, whosetestRegexonly matches*.spec.ts$. That's a pre-existing repo-wide condition affecting alltest/**/*.test.tsfiles, not something introduced here.Test plan
forge build contracts/utils/YulBitSlice.sol contracts/proxy/YulProxyForwarder.sol contracts/utils/BatchBalanceChecker.sol— compiles cleanly (Solc 0.8.20)cd gasguard-cli && cargo test— all newtransformers::storage_packertests pass (7/7); 2 pre-existing failures incommands::optimize_storagereproduce identically onmainand are unrelated to this change (out of scope)Closes #690
Closes #691
Closes #692
Closes #695