Skip to content

Commit

Permalink
save 600 gas, cleaner code when moving caller delta to tokensOwed
Browse files Browse the repository at this point in the history
  • Loading branch information
saucepoint committed Jun 26, 2024
1 parent 4bc5851 commit b382a1e
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 9 deletions.
2 changes: 1 addition & 1 deletion .forge-snapshots/autocompound_excessFeesCredit.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
279673
279016
14 changes: 7 additions & 7 deletions contracts/base/BaseLiquidityManagement.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {FeeMath} from "../libraries/FeeMath.sol";
import {LiquiditySaltLibrary} from "../libraries/LiquiditySaltLibrary.sol";
import {IBaseLiquidityManagement} from "../interfaces/IBaseLiquidityManagement.sol";
import {PositionLibrary} from "../libraries/Position.sol";
import {BalanceDeltaExtensionLibrary} from "../libraries/BalanceDeltaExtensionLibrary.sol";

import "forge-std/console2.sol";

Expand All @@ -38,6 +39,7 @@ contract BaseLiquidityManagement is IBaseLiquidityManagement, SafeCallback {
using SafeCast for uint256;
using LiquiditySaltLibrary for IHooks;
using PositionLibrary for IBaseLiquidityManagement.Position;
using BalanceDeltaExtensionLibrary for BalanceDelta;

mapping(address owner => mapping(LiquidityRangeId rangeId => Position)) public positions;

Expand Down Expand Up @@ -208,17 +210,15 @@ contract BaseLiquidityManagement is IBaseLiquidityManagement, SafeCallback {
BalanceDelta thisDelta
) private returns (BalanceDelta, BalanceDelta, BalanceDelta) {
// credit the excess tokens to the position's tokensOwed
tokensOwed = useAmount0
? toBalanceDelta(callerDelta.amount0(), tokensOwed.amount1())
: toBalanceDelta(tokensOwed.amount0(), callerDelta.amount1());
tokensOwed =
useAmount0 ? tokensOwed.setAmount0(callerDelta.amount0()) : tokensOwed.setAmount1(callerDelta.amount1());

// this contract is responsible for custodying the excess tokens
thisDelta = useAmount0
? thisDelta + toBalanceDelta(callerDelta.amount0(), 0)
: thisDelta + toBalanceDelta(0, callerDelta.amount1());
thisDelta =
useAmount0 ? thisDelta.addAmount0(callerDelta.amount0()) : thisDelta.addAmount1(callerDelta.amount1());

// the caller is not expected to collect the excess tokens
callerDelta = useAmount0 ? toBalanceDelta(0, callerDelta.amount1()) : toBalanceDelta(callerDelta.amount0(), 0);
callerDelta = useAmount0 ? callerDelta.setAmount0(0) : callerDelta.setAmount1(0);

return (tokensOwed, callerDelta, thisDelta);
}
Expand Down
53 changes: 53 additions & 0 deletions contracts/libraries/BalanceDeltaExtensionLibrary.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol";

library BalanceDeltaExtensionLibrary {
function setAmount0(BalanceDelta a, int128 amount0) internal pure returns (BalanceDelta) {
assembly {
// set the upper 128 bits of a to amount0
a := or(shl(128, amount0), and(sub(shl(128, 1), 1), a))
}
return a;
}

function setAmount1(BalanceDelta a, int128 amount1) internal pure returns (BalanceDelta) {
assembly {
// set the lower 128 bits of a to amount1
a := or(and(shl(128, sub(shl(128, 1), 1)), a), amount1)
}
return a;
}

function addAmount0(BalanceDelta a, int128 amount0) internal pure returns (BalanceDelta) {
assembly {
let a0 := sar(128, a)
let res0 := add(a0, amount0)
a := or(shl(128, res0), and(sub(shl(128, 1), 1), a))
}
return a;
}

function addAmount1(BalanceDelta a, int128 amount1) internal pure returns (BalanceDelta) {
assembly {
let a1 := signextend(15, a)
let res1 := add(a1, amount1)
a := or(and(shl(128, sub(shl(128, 1), 1)), a), res1)
}
return a;
}

function addAndAssign(BalanceDelta a, BalanceDelta b) internal pure returns (BalanceDelta) {
assembly {
let a0 := sar(128, a)
let a1 := signextend(15, a)
let b0 := sar(128, b)
let b1 := signextend(15, b)
let res0 := add(a0, b0)
let res1 := add(a1, b1)
a := or(shl(128, res0), and(sub(shl(128, 1), 1), res1))
}
return a;
}
}
2 changes: 1 addition & 1 deletion test/position-managers/Gas.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ contract GasTest is Test, Deployers, GasSnapshot {

// alice will use half of her fees to increase liquidity
(uint256 token0Owed, uint256 token1Owed) = lpm.feesOwed(tokenIdAlice);

(uint160 sqrtPriceX96,,,) = StateLibrary.getSlot0(manager, range.poolKey.toId());
uint256 liquidityDelta = LiquidityAmounts.getLiquidityForAmounts(
sqrtPriceX96,
Expand Down

0 comments on commit b382a1e

Please sign in to comment.