Skip to content

Commit

Permalink
annotate memory safe assembly for further gas optimizations (#723)
Browse files Browse the repository at this point in the history
  • Loading branch information
gretzke authored May 28, 2024
1 parent 9b17e03 commit d5d4957
Show file tree
Hide file tree
Showing 32 changed files with 55 additions and 91 deletions.
2 changes: 1 addition & 1 deletion .forge-snapshots/donate gas with 1 token.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
106027
104674
2 changes: 1 addition & 1 deletion .forge-snapshots/donate gas with 2 tokens.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
146035
144554
2 changes: 1 addition & 1 deletion .forge-snapshots/getReserves.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1630
1552
2 changes: 1 addition & 1 deletion .forge-snapshots/swap CA custom curve + swap noop.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
128990
127257
2 changes: 1 addition & 1 deletion .forge-snapshots/swap CA fee on unspecified.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
174512
172779
Original file line number Diff line number Diff line change
@@ -1 +1 @@
108127
106660
2 changes: 1 addition & 1 deletion .forge-snapshots/swap against liquidity.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
119479
117746
2 changes: 1 addition & 1 deletion .forge-snapshots/swap burn 6909 for input.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
131285
129595
2 changes: 1 addition & 1 deletion .forge-snapshots/swap burn native 6909 for input.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
120369
118816
2 changes: 1 addition & 1 deletion .forge-snapshots/swap mint native output as 6909.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
142229
140629
2 changes: 1 addition & 1 deletion .forge-snapshots/swap mint output as 6909.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
158199
156433
Original file line number Diff line number Diff line change
@@ -1 +1 @@
211054
208496
2 changes: 1 addition & 1 deletion .forge-snapshots/swap with dynamic fee.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
142260
140527
2 changes: 1 addition & 1 deletion .forge-snapshots/swap with hooks.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
134930
133197
2 changes: 1 addition & 1 deletion .forge-snapshots/swap with lp fee and protocol fee.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
172061
170330
2 changes: 1 addition & 1 deletion .forge-snapshots/swap with return dynamic fee.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
148491
146758
2 changes: 1 addition & 1 deletion .forge-snapshots/update dynamic fee in before swap.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
150749
149016
9 changes: 3 additions & 6 deletions src/Extsload.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,15 @@ import {IExtsload} from "./interfaces/IExtsload.sol";
abstract contract Extsload is IExtsload {
/// @inheritdoc IExtsload
function extsload(bytes32 slot) external view returns (bytes32) {
/// @solidity memory-safe-assembly
assembly {
assembly ("memory-safe") {
mstore(0, sload(slot))
return(0, 0x20)
}
}

/// @inheritdoc IExtsload
function extsload(bytes32 startSlot, uint256 nSlots) external view returns (bytes memory) {
/// @solidity memory-safe-assembly
assembly {
assembly ("memory-safe") {
// The abi offset of dynamic array in the returndata is 32.
mstore(0, 0x20)
// A left bit-shift of 5 is equivalent to multiplying by 32 but costs less gas.
Expand All @@ -40,8 +38,7 @@ abstract contract Extsload is IExtsload {
// since the function is external and enters a new call context and exits right
// after execution, Solidity's memory management convention can be disregarded
// and a direct slice of memory can be returned
/// @solidity memory-safe-assembly
assembly {
assembly ("memory-safe") {
// Copy the abi offset of dynamic array and the length of the array to memory.
calldatacopy(0, 0x04, 0x40)
// A left bit-shift of 5 is equivalent to multiplying by 32 but costs less gas.
Expand Down
6 changes: 2 additions & 4 deletions src/Exttload.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ import {IExttload} from "./interfaces/IExttload.sol";
abstract contract Exttload is IExttload {
/// @inheritdoc IExttload
function exttload(bytes32 slot) external view returns (bytes32) {
/// @solidity memory-safe-assembly
assembly {
assembly ("memory-safe") {
mstore(0, tload(slot))
return(0, 0x20)
}
Expand All @@ -20,8 +19,7 @@ abstract contract Exttload is IExttload {
// since the function is external and enters a new call context and exits right
// after execution, Solidity's memory management convention can be disregarded
// and a direct slice of memory can be returned
/// @solidity memory-safe-assembly
assembly {
assembly ("memory-safe") {
// Copy the abi offset of dynamic array and the length of the array to memory.
calldatacopy(0, 0x04, 0x40)
// A left bit-shift of 5 is equivalent to multiplying by 32 but costs less gas.
Expand Down
18 changes: 6 additions & 12 deletions src/libraries/CustomRevert.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,15 @@ pragma solidity >=0.8.4;
library CustomRevert {
/// @dev Reverts with the selector of a custom error in the scratch space
function revertWith(bytes4 selector) internal pure {
/// @solidity memory-safe-assembly
assembly {
assembly ("memory-safe") {
mstore(0, selector)
revert(0, 0x04)
}
}

/// @dev Reverts with a custom error with an address argument in the scratch space
function revertWith(bytes4 selector, address addr) internal pure {
/// @solidity memory-safe-assembly
assembly {
assembly ("memory-safe") {
mstore(0, selector)
mstore(0x04, addr)
revert(0, 0x24)
Expand All @@ -28,8 +26,7 @@ library CustomRevert {

/// @dev Reverts with a custom error with an int24 argument in the scratch space
function revertWith(bytes4 selector, int24 value) internal pure {
/// @solidity memory-safe-assembly
assembly {
assembly ("memory-safe") {
mstore(0, selector)
mstore(0x04, value)
revert(0, 0x24)
Expand All @@ -38,8 +35,7 @@ library CustomRevert {

/// @dev Reverts with a custom error with a uint160 argument in the scratch space
function revertWith(bytes4 selector, uint160 value) internal pure {
/// @solidity memory-safe-assembly
assembly {
assembly ("memory-safe") {
mstore(0, selector)
mstore(0x04, value)
revert(0, 0x24)
Expand All @@ -48,8 +44,7 @@ library CustomRevert {

/// @dev Reverts with a custom error with two int24 arguments
function revertWith(bytes4 selector, int24 value1, int24 value2) internal pure {
/// @solidity memory-safe-assembly
assembly {
assembly ("memory-safe") {
mstore(0, selector)
mstore(0x04, value1)
mstore(0x24, value2)
Expand All @@ -59,8 +54,7 @@ library CustomRevert {

/// @dev Reverts with a custom error with two uint160 arguments
function revertWith(bytes4 selector, uint160 value1, uint160 value2) internal pure {
/// @solidity memory-safe-assembly
assembly {
assembly ("memory-safe") {
mstore(0, selector)
mstore(0x04, value1)
mstore(0x24, value2)
Expand Down
3 changes: 1 addition & 2 deletions src/libraries/Hooks.sol
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,7 @@ library Hooks {
/// @notice performs a hook call using the given calldata on the given hook that doesnt return a delta
/// @return result The complete data returned by the hook
function callHook(IHooks self, bytes memory data) internal returns (bytes memory result) {
/// @solidity memory-safe-assembly
assembly {
assembly ("memory-safe") {
if iszero(call(gas(), self, 0, add(data, 0x20), mload(data), 0, 0)) {
if iszero(returndatasize()) {
// if the call failed without a revert reason, revert with `FailedHookCall()`
Expand Down
3 changes: 1 addition & 2 deletions src/libraries/Position.sol
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,7 @@ library Position {
// positionKey = keccak256(abi.encodePacked(owner, tickLower, tickUpper, salt))
bytes32 positionKey;

/// @solidity memory-safe-assembly
assembly {
assembly ("memory-safe") {
mstore(0x26, salt) // [0x26, 0x46)
mstore(0x06, tickUpper) // [0x23, 0x26)
mstore(0x03, tickLower) // [0x20, 0x23)
Expand Down
3 changes: 1 addition & 2 deletions src/libraries/SafeCast.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ library SafeCast {
error SafeCastOverflow();

function _revertOverflow() private pure {
/// @solidity memory-safe-assembly
assembly {
assembly ("memory-safe") {
// Store the function selector of `SafeCastOverflow()`.
mstore(0x00, 0x93dafdf1)
// Revert with (offset, size).
Expand Down
15 changes: 5 additions & 10 deletions src/libraries/SqrtPriceMath.sol
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@ library SqrtPriceMath {
// if the product overflows, we know the denominator underflows
// in addition, we must check that the denominator does not underflow
// equivalent: if (product / amount != sqrtPX96 || numerator1 <= product) revert PriceOverflow();
/// @solidity memory-safe-assembly
assembly {
assembly ("memory-safe") {
if iszero(and(eq(div(product, amount), sqrtPX96), gt(numerator1, product))) {
mstore(0, 0xf5c787f1) // selector for PriceOverflow()
revert(0x1c, 0x04)
Expand Down Expand Up @@ -102,8 +101,7 @@ library SqrtPriceMath {
);

// equivalent: if (sqrtPX96 <= quotient) revert NotEnoughLiquidity();
/// @solidity memory-safe-assembly
assembly {
assembly ("memory-safe") {
if iszero(gt(sqrtPX96, quotient)) {
mstore(0, 0x4323a555) // selector for NotEnoughLiquidity()
revert(0x1c, 0x04)
Expand All @@ -129,8 +127,7 @@ library SqrtPriceMath {
returns (uint160 sqrtQX96)
{
// equivalent: if (sqrtPX96 == 0 || liquidity == 0) revert InvalidPriceOrLiquidity();
/// @solidity memory-safe-assembly
assembly {
assembly ("memory-safe") {
if or(iszero(sqrtPX96), iszero(liquidity)) {
mstore(0, 0x4f2461b8) // selector for InvalidPriceOrLiquidity()
revert(0x1c, 0x04)
Expand All @@ -156,8 +153,7 @@ library SqrtPriceMath {
returns (uint160 sqrtQX96)
{
// equivalent: if (sqrtPX96 == 0 || liquidity == 0) revert InvalidPriceOrLiquidity();
/// @solidity memory-safe-assembly
assembly {
assembly ("memory-safe") {
if or(iszero(sqrtPX96), iszero(liquidity)) {
mstore(0, 0x4f2461b8) // selector for InvalidPriceOrLiquidity()
revert(0x1c, 0x04)
Expand Down Expand Up @@ -187,8 +183,7 @@ library SqrtPriceMath {
if (sqrtPriceAX96 > sqrtPriceBX96) (sqrtPriceAX96, sqrtPriceBX96) = (sqrtPriceBX96, sqrtPriceAX96);

// equivalent: if (sqrtPriceAX96 == 0) revert InvalidPrice();
/// @solidity memory-safe-assembly
assembly {
assembly ("memory-safe") {
if iszero(sqrtPriceAX96) {
mstore(0, 0x00bfc921) // selector for InvalidPrice()
revert(0x1c, 0x04)
Expand Down
3 changes: 1 addition & 2 deletions src/libraries/StateLibrary.sol
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,7 @@ library StateLibrary {
// positionKey = keccak256(abi.encodePacked(owner, tickLower, tickUpper, salt))
bytes32 positionKey;

/// @solidity memory-safe-assembly
assembly {
assembly ("memory-safe") {
mstore(0x26, salt) // [0x26, 0x46)
mstore(0x06, tickUpper) // [0x23, 0x26)
mstore(0x03, tickLower) // [0x20, 0x23)
Expand Down
3 changes: 1 addition & 2 deletions src/libraries/TickBitmap.sol
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ library TickBitmap {
* uint256 mask = 1 << bitPos;
* self[wordPos] ^= mask;
*/
/// @solidity memory-safe-assembly
assembly {
assembly ("memory-safe") {
// ensure that the tick is spaced
if smod(tick, tickSpacing) {
mstore(0, 0xd4d8f3e6) // selector for TickMisaligned(int24,int24)
Expand Down
6 changes: 2 additions & 4 deletions src/libraries/TickMath.sol
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,7 @@ library TickMath {
absTick := xor(mask, add(mask, tick))
}
// Equivalent: if (absTick > MAX_TICK) revert InvalidTick();
/// @solidity memory-safe-assembly
assembly {
assembly ("memory-safe") {
if gt(absTick, MAX_TICK) {
// store 4-byte selector of "InvalidTick()" at memory [0x1c, 0x20)
mstore(0, 0xce8ef7fc)
Expand Down Expand Up @@ -118,8 +117,7 @@ library TickMath {
unchecked {
// Equivalent: if (sqrtPriceX96 < MIN_SQRT_PRICE || sqrtPriceX96 >= MAX_SQRT_PRICE) revert InvalidSqrtPrice();
// second inequality must be < because the price can never reach the price at the max tick
/// @solidity memory-safe-assembly
assembly {
assembly ("memory-safe") {
// if sqrtPriceX96 < MIN_SQRT_PRICE, the `sub` underflows and `gt` is true
// if sqrtPriceX96 >= MAX_SQRT_PRICE, sqrtPriceX96 - MIN_SQRT_PRICE > MAX_SQRT_PRICE - MIN_SQRT_PRICE - 1
if gt(sub(sqrtPriceX96, MIN_SQRT_PRICE), MAX_SQRT_PRICE_MINUS_MIN_SQRT_PRICE_MINUS_ONE) {
Expand Down
4 changes: 2 additions & 2 deletions src/libraries/TransientStateLibrary.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ library TransientStateLibrary {
/// @dev returns type(uint256).max if the reserves are synced but the value is 0
function getReserves(IPoolManager manager, Currency currency) internal view returns (uint256) {
bytes32 key;
assembly {
assembly ("memory-safe") {
mstore(0, RESERVES_OF_SLOT)
mstore(32, currency)
key := keccak256(0, 64)
Expand All @@ -43,7 +43,7 @@ library TransientStateLibrary {
/// @param currency The currency for which to lookup the delta
function currencyDelta(IPoolManager manager, address caller_, Currency currency) internal view returns (int256) {
bytes32 key;
assembly {
assembly ("memory-safe") {
mstore(0, caller_)
mstore(32, currency)
key := keccak256(0, 64)
Expand Down
6 changes: 2 additions & 4 deletions src/types/BeforeSwapDelta.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ function toBeforeSwapDelta(int128 deltaSpecified, int128 deltaUnspecified)
pure
returns (BeforeSwapDelta beforeSwapDelta)
{
/// @solidity memory-safe-assembly
assembly {
assembly ("memory-safe") {
beforeSwapDelta := or(shl(128, deltaSpecified), and(sub(shl(128, 1), 1), deltaUnspecified))
}
}
Expand All @@ -32,8 +31,7 @@ library BeforeSwapDeltaLibrary {
/// extracts int128 from the lower 128 bits of the BeforeSwapDelta
/// returned by beforeSwap and afterSwap
function getUnspecifiedDelta(BeforeSwapDelta delta) internal pure returns (int128 deltaUnspecified) {
/// @solidity memory-safe-assembly
assembly {
assembly ("memory-safe") {
deltaUnspecified := signextend(15, delta)
}
}
Expand Down
6 changes: 2 additions & 4 deletions src/types/Currency.sol
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,15 @@ library CurrencyLibrary {
// modified custom error selectors

if (currency.isNative()) {
/// @solidity memory-safe-assembly
assembly {
assembly ("memory-safe") {
// Transfer the ETH and revert if it fails.
if iszero(call(gas(), to, amount, 0x00, 0x00, 0x00, 0x00)) {
mstore(0x00, 0xf4b3b1bc) // `NativeTransferFailed()`.
revert(0x1c, 0x04)
}
}
} else {
/// @solidity memory-safe-assembly
assembly {
assembly ("memory-safe") {
mstore(0x14, to) // Store the `to` address in [0x20, 0x34).
mstore(0x34, amount) // Store the `amount` argument in [0x34, 0x54).
// Store the selector of `transfer(address,uint256)` in [0x10, 0x14).
Expand Down
3 changes: 1 addition & 2 deletions src/types/PoolId.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ type PoolId is bytes32;
library PoolIdLibrary {
/// @notice Returns value equal to keccak256(abi.encode(poolKey))
function toId(PoolKey memory poolKey) internal pure returns (PoolId poolId) {
/// @solidity memory-safe-assembly
assembly {
assembly ("memory-safe") {
poolId := keccak256(poolKey, mul(32, 5))
}
}
Expand Down
Loading

0 comments on commit d5d4957

Please sign in to comment.