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

[Gas optimization] Suggestion from Ottersec #180

Merged
merged 10 commits into from
Oct 9, 2024
2 changes: 1 addition & 1 deletion .forge-snapshots/BinHookTest#testBurnSucceedsWithHook.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
178372
178321
Original file line number Diff line number Diff line change
@@ -1 +1 @@
188524
188513
2 changes: 1 addition & 1 deletion .forge-snapshots/BinHookTest#testMintSucceedsWithHook.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
311573
311511
2 changes: 1 addition & 1 deletion .forge-snapshots/BinHookTest#testSwapSucceedsWithHook.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
189823
189812
2 changes: 1 addition & 1 deletion .forge-snapshots/BinPoolManagerBytecodeSize.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
24384
24232
Original file line number Diff line number Diff line change
@@ -1 +1 @@
133886
133846
Original file line number Diff line number Diff line change
@@ -1 +1 @@
142697
142646
Original file line number Diff line number Diff line change
@@ -1 +1 @@
290044
289677
2 changes: 1 addition & 1 deletion .forge-snapshots/BinPoolManagerTest#testGasBurnOneBin.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
127060
127019
2 changes: 1 addition & 1 deletion .forge-snapshots/BinPoolManagerTest#testGasDonate.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
118796
118785
Original file line number Diff line number Diff line change
@@ -1 +1 @@
970977
970507
Original file line number Diff line number Diff line change
@@ -1 +1 @@
330288
329818
Original file line number Diff line number Diff line change
@@ -1 +1 @@
337889
337827
Original file line number Diff line number Diff line change
@@ -1 +1 @@
140439
140377
Original file line number Diff line number Diff line change
@@ -1 +1 @@
173347
173336
Original file line number Diff line number Diff line change
@@ -1 +1 @@
179376
179365
Original file line number Diff line number Diff line change
@@ -1 +1 @@
133378
133367
Original file line number Diff line number Diff line change
@@ -1 +1 @@
304846
304784
2 changes: 1 addition & 1 deletion .forge-snapshots/CLPoolManagerBytecodeSize.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
21307
21220
Original file line number Diff line number Diff line change
@@ -1 +1 @@
347635
347599
Original file line number Diff line number Diff line change
@@ -1 +1 @@
163106
163070
Original file line number Diff line number Diff line change
@@ -1 +1 @@
238392
238356
2 changes: 1 addition & 1 deletion .forge-snapshots/CLPoolManagerTest#donateBothTokens.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
163361
163350
2 changes: 1 addition & 1 deletion .forge-snapshots/CLPoolManagerTest#gasDonateOneToken.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
108308
108297
Original file line number Diff line number Diff line change
@@ -1 +1 @@
114866
112713
Original file line number Diff line number Diff line change
@@ -1 +1 @@
131100
131089
Original file line number Diff line number Diff line change
@@ -1 +1 @@
163678
163667
Original file line number Diff line number Diff line change
@@ -1 +1 @@
149117
149106
2 changes: 1 addition & 1 deletion .forge-snapshots/CLPoolManagerTest#swap_simple.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
71712
71701
Original file line number Diff line number Diff line change
@@ -1 +1 @@
143353
143342
2 changes: 1 addition & 1 deletion .forge-snapshots/CLPoolManagerTest#swap_withHooks.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
87984
87973
2 changes: 1 addition & 1 deletion .forge-snapshots/CLPoolManagerTest#swap_withNative.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
71715
71704
21 changes: 8 additions & 13 deletions src/base/Pausable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
pragma solidity ^0.8.20;

/**
* @dev Copy from openZeppelin contracts(v5.0.0) (utils/Pausable.sol), and remove unnecessary functions.
* @dev Referenced from openZeppelin contracts(v5.0.0) (utils/Pausable.sol), removed unnecessary functions and gas optimization.
* Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
Expand All @@ -12,7 +12,7 @@ pragma solidity ^0.8.20;
* simply including this module, only once the modifiers are put in place.
*/
abstract contract Pausable {
bool private _paused;
uint256 private _paused;
Copy link
Collaborator

Choose a reason for hiding this comment

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

if so , should we remove the comments above ?
copy from ......


/**
* @dev Emitted when the pause is triggered by `account`.
Expand All @@ -29,13 +29,6 @@ abstract contract Pausable {
*/
error EnforcedPause();

/**
* @dev Initializes the contract in unpaused state.
*/
constructor() {
_paused = false;
}

/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
Expand All @@ -51,8 +44,10 @@ abstract contract Pausable {
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
function paused() public view virtual returns (bool res) {
assembly ("memory-safe") {
res := sload(_paused.slot)
}
}

/**
Expand All @@ -72,15 +67,15 @@ abstract contract Pausable {
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
_paused = 1;
emit Paused(msg.sender);
}

/**
* @dev Returns to normal state.
*/
function _unpause() internal virtual {
_paused = false;
_paused = 0;
emit Unpaused(msg.sender);
}
}
16 changes: 4 additions & 12 deletions src/pool-bin/libraries/BinPosition.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,12 @@ library BinPosition {
/// @param binId The bin id where the position's liquidity is added
/// @param salt A unique value to differentiate between multiple positions in the same binId, by the same owner. Passed in by the caller.
function calculatePositionKey(address owner, uint24 binId, bytes32 salt) internal pure returns (bytes32 key) {
// dev same as `positionKey = keccak256(abi.encodePacked(owner, binId, salt))`
// dev same as `positionKey = keccak256(abi.encodePacked(binId, owner, salt))`
// make salt, binId, owner to be tightly packed in memory
// mstore in reverse order make sure latter can make use of the empty space in the former
assembly ("memory-safe") {
let fmp := mload(0x40)
mstore(add(fmp, 0x23), salt) // salt at [0x23, 0x43)
mstore(add(fmp, 0x03), binId) // binId at [0x20, 0x23)
mstore(fmp, owner) // owner at [0x0c, 0x20)
key := keccak256(add(fmp, 0x0c), 0x37) // len is 55 bytes

// now clean the memory we used
mstore(add(fmp, 0x40), 0) // fmp+0x40 held salt
mstore(add(fmp, 0x20), 0) // fmp+0x20 held binId, salt
mstore(fmp, 0) // fmp held owner
mstore(0x0, or(shl(160, binId), and(owner, 0xffffffffffffffffffffffffffffffffffffffff))) // binId at [0x09,0x0c), owner at [0x0c, 0x20)
mstore(0x20, salt) // salt at [0x20, 0x40)
key := keccak256(0x09, 0x37)
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/pool-cl/CLPoolManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ contract CLPoolManager is ICLPoolManager, ProtocolFees, Extsload {
bytes calldata hookData
) external override returns (BalanceDelta delta, BalanceDelta feeDelta) {
// Do not allow add liquidity when paused()
if (paused() && params.liquidityDelta > 0) revert PoolPaused();
if (params.liquidityDelta > 0 && paused()) revert PoolPaused();

PoolId id = key.toId();
CLPool.State storage pool = pools[id];
Expand Down
23 changes: 10 additions & 13 deletions src/pool-cl/libraries/CLPosition.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,18 @@ library CLPosition {
pure
returns (bytes32 key)
{
// same as `positionKey = keccak256(abi.encodePacked(owner, tickLower, tickUpper, salt))`
// same as `positionKey = keccak256(abi.encodePacked(tickLower, tickUpper, owner, salt))`
// make salt, tickUpper, tickLower, owner to be tightly packed in memory
// mstore in reverse order make sure latter can make use of the empty space in the former
assembly ("memory-safe") {
let fmp := mload(0x40)
mstore(add(fmp, 0x26), salt) // salt at [0x26, 0x46)
mstore(add(fmp, 0x06), tickUpper) // tickUpper at [0x23, 0x26)
mstore(add(fmp, 0x03), tickLower) // tickLower at [0x20, 0x23)
mstore(fmp, owner) // owner at [0x0c, 0x20)
key := keccak256(add(fmp, 0x0c), 0x3a) // len is 58 bytes

// now clean the memory we used since we don't need it anymore
mstore(add(fmp, 0x40), 0) // fmp+0x40 held salt
mstore(add(fmp, 0x20), 0) // fmp+0x20 held tickLower, tickUpper, salt
mstore(fmp, 0) // fmp held owner
mstore(
0x0,
or(
shl(160, and(0xFFFFFF, tickUpper)),
or(shl(184, tickLower), and(owner, 0xffffffffffffffffffffffffffffffffffffffff))
)
) // tickLower at [0x06, 0x09), tickUpper at [0x09,0x0c), owner at [0x0c, 0x20)
mstore(0x20, salt) // salt at [0x20, 0x40)
key := keccak256(0x06, 0x3a) // len is 58 bytes
}
}

Expand Down
14 changes: 6 additions & 8 deletions test/Extsload.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ contract ExtsloadTest is Test, GasSnapshot {
// | Name | Type | Slot | Offset | Bytes | Contract |
// |-----------------------|----------------------------------------|------|--------|-------|---------------------------------------------|
// | _owner | address | 0 | 0 | 20 | src/pool-cl/CLPoolManager.sol:CLPoolManager |
// | _paused | bool | 0 | 20 | 1 | src/pool-cl/CLPoolManager.sol:CLPoolManager |
// | hasPausableRole | mapping(address => bool) | 1 | 0 | 32 | src/pool-cl/CLPoolManager.sol:CLPoolManager |
// | _paused | uint256 | 1 | 0 | 32 | src/pool-cl/CLPoolManager.sol:CLPoolManager |
// | protocolFeesAccrued | mapping(Currency => uint256) | 2 | 0 | 32 | src/pool-cl/CLPoolManager.sol:CLPoolManager |
// | protocolFeeController | contract IProtocolFeeController | 3 | 0 | 20 | src/pool-cl/CLPoolManager.sol:CLPoolManager |
// | pools | mapping(PoolId => struct CLPool.State) | 4 | 0 | 32 | src/pool-cl/CLPoolManager.sol:CLPoolManager |
// | poolIdToPoolKey | mapping(PoolId => struct PoolKey) | 5 | 0 | 32 | src/pool-cl/CLPoolManager.sol:CLPoolManager |
ICLPoolManager poolManager;

Loadable loadable = new Loadable();
Expand All @@ -34,21 +34,19 @@ contract ExtsloadTest is Test, GasSnapshot {
}

function testExtsload() public {
// as contract is not paused, slot0 is 0x0...0_owner_address,
// if paused, slot0 is 0x0...1_owner_address
snapStart("ExtsloadTest#extsload");
bytes32 slot0 = poolManager.extsload(0x00);
snapEnd();
assertEq(abi.encode(slot0), abi.encode(address(this)));
assertEq(abi.encode(slot0), abi.encode(address(this))); // owner

bytes32 slot2 = poolManager.extsload(bytes32(uint256(0x02)));
assertEq(abi.encode(slot2), abi.encode(address(0xabcd)));
bytes32 slot2 = poolManager.extsload(bytes32(uint256(0x03)));
assertEq(abi.encode(slot2), abi.encode(address(0xabcd))); // protocolFeeController
}

function testExtsloadInBatch() public {
bytes32[] memory slots = new bytes32[](2);
slots[0] = 0x00;
slots[1] = bytes32(uint256(0x02));
slots[1] = bytes32(uint256(0x03));
snapStart("ExtsloadTest#extsloadInBatch");
slots = poolManager.extsload(slots);
snapEnd();
Expand Down
2 changes: 1 addition & 1 deletion test/pool-bin/BinPoolManager.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -872,7 +872,7 @@ contract BinPoolManagerTest is Test, GasSnapshot, BinTestHelper {
poolManager.initialize(key, activeId, new bytes(0));

// verify poolId.
uint256 POOL_SLOT = 4;
uint256 POOL_SLOT = 5;
snapStart("BinPoolManagerTest#testExtLoadPoolActiveId");
bytes32 slot0Bytes = poolManager.extsload(keccak256(abi.encode(key.toId(), POOL_SLOT)));
snapEnd();
Expand Down
4 changes: 2 additions & 2 deletions test/pool-bin/libraries/BinPosition.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,12 @@ contract BinPositionTest is Test {

function testFuzz_CalculatePositionKey(address owner, uint24 binId, bytes32 salt) public pure {
bytes32 positionKey = BinPosition.calculatePositionKey(owner, binId, salt);
assertEq(positionKey, keccak256(abi.encodePacked(owner, binId, salt)));
assertEq(positionKey, keccak256(abi.encodePacked(binId, owner, salt)));
}

function testFuzz_GetPosition(address owner, uint24 binId, bytes32 salt, uint256 share) public {
// manual keccak and add share
bytes32 key = keccak256(abi.encodePacked(owner, binId, salt));
bytes32 key = keccak256(abi.encodePacked(binId, owner, salt));
_self.positions[key].addShare(share);

// verify assembly version of keccak retrival works
Expand Down
4 changes: 2 additions & 2 deletions test/pool-cl/libraries/CLPosition.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ contract CLPositionTest is Test, GasSnapshot {
pure
{
bytes32 positionKey = CLPosition.calculatePositionKey(owner, tickLower, tickUpper, salt);
assertEq(positionKey, keccak256(abi.encodePacked(owner, tickLower, tickUpper, salt)));
assertEq(positionKey, keccak256(abi.encodePacked(tickLower, tickUpper, owner, salt)));
}

function test_MixFuzz(address owner, int24 tickLower, int24 tickUpper, bytes32 salt, int128 liquidityDelta)
Expand All @@ -106,7 +106,7 @@ contract CLPositionTest is Test, GasSnapshot {
CLPosition.Info storage info = pool.positions.get(owner, tickLower, tickUpper, salt);
info.update(liquidityDelta, 0, 0);

bytes32 key = keccak256(abi.encodePacked(owner, tickLower, tickUpper, salt));
bytes32 key = keccak256(abi.encodePacked(tickLower, tickUpper, owner, salt));
assertEq(pool.positions[key].liquidity, uint128(liquidityDelta));
}
}
Loading