Skip to content

refactor(core): optimize Balance storage library via Yul - #136

Open
SovaSlava wants to merge 1 commit into
1inch:mainfrom
SovaSlava:refactor/gas-optimization
Open

refactor(core): optimize Balance storage library via Yul#136
SovaSlava wants to merge 1 commit into
1inch:mainfrom
SovaSlava:refactor/gas-optimization

Conversation

@SovaSlava

Copy link
Copy Markdown

Description

This PR refactors the Balance storage library to perform in-place Yul arithmetic for packed slot mutations (increase, decrease, store, and setDocked).

By leveraging low-level EVM assembly, we bypass redundant unpack/repack steps (SHL, OR), type conversions, and external bounds-checking logic while strictly maintaining standard Panic(0x11) arithmetic safety guarantees.

Key Changes

  • increase: Performs in-place slot addition and verifies 248-bit overflow limits natively in Yul before SSTORE.
  • decrease: Performs in-place slot subtraction. Ensures amount <= prevBalance to guarantee that upper tokensCount bits remain untouched.
  • set: Updated to handle raw uint256 inputs and enforce Yul-level 248-bit masking to prevent dirty bit corruption during initialization.

Gas Benchmark

Across the entire test suite, this refactoring achieves a total reduction of -69370 gas (-1.287%) without any gas regressions (44 tests improved).

Testing

  • All existing unit tests pass cleanly (forge test).
  • Gas snapshot updated (.gas-snapshot).
  • Verified that overflow/underflow attempts correctly revert with standard Panic 0x11.

@SovaSlava
SovaSlava force-pushed the refactor/gas-optimization branch 5 times, most recently from 7491711 to e8c57a3 Compare July 29, 2026 22:51
@SovaSlava
SovaSlava force-pushed the refactor/gas-optimization branch from e8c57a3 to 1bc185e Compare July 29, 2026 22:52
Comment thread src/libs/Balance.sol
library BalanceLib {
/// @notice Loads balance data from storage using exactly 1 SLOAD
/// @dev Assembly implementation ensures optimal gas usage
/// @notice Loads packed balance and token count data from storage using exactly 1 SLOAD

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

        sstore(balance.slot, add(rawSlot, amount)) 
     } 
 } 

 /// @notice Safely decreases the packed balance by a specified amount using in-place subtraction. 
 /// @dev Utilizes Yul assembly to bypass bitmasking and repacking overhead. 
 /// Reverts with standard Solidity arithmetic Panic (0x11) if the amount exceeds the current balance. 
 /// @param balance The storage pointer to the packed Balance struct. 
 /// @param rawSlot The current unmasked 256-bit storage word (lower 248 bits: balance, upper 8 bits: tokensCount). 
 /// @param amount The token amount to subtract from the current balance. 
 function decrease(Balance storage balance, uint256 rawSlot, uint256 amount) internal { 
     assembly ("memory-safe") { 
         let max248 := shr(8, not(0)) 
         let prevBalance := and(rawSlot, max248) 

         if gt(amount, prevBalance) { 
             mstore(0x00, shl(224, 0x4e487b71)) // Panic(0x11) 
             mstore(0x04, 0x11) 
             revert(0x00, 0x24) 
         } 

         sstore(balance.slot, sub(rawSlot, amount)) 
     } 
 } 

}end point api v2

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I noticed the code snippet you attached is identical to the current implementation in this pr, but it has "}end point api v2" at the end. Was there a specific change you wanted to suggest here, or was it an accidental paste?
You just would like to change natspec text in my pr?

@kennypetty399-collabmusic kennypetty399-collabmusic left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stolen coins

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