Skip to content

Commit

Permalink
Merge pull request #28 from shuhuiluo/Let-Me-Think
Browse files Browse the repository at this point in the history
Optimize `computeSwapStep` and bit math
  • Loading branch information
aperture11 authored Jan 4, 2024
2 parents 5fe0536 + 2c53136 commit 1e2e1b3
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 170 deletions.
54 changes: 27 additions & 27 deletions .gas-snapshot
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
BitMathTest:testFuzz_LSB(uint256) (runs: 65536, μ: 14911, ~: 14909)
BitMathTest:testFuzz_MSB(uint256) (runs: 65536, μ: 14791, ~: 14816)
BitMathTest:testFuzz_MSB(uint256) (runs: 65536, μ: 14771, ~: 14796)
BitMathTest:testGas_LSB() (gas: 193393)
BitMathTest:testGas_LSB_Og() (gas: 291088)
BitMathTest:testGas_MSB() (gas: 213472)
BitMathTest:testGas_MSB() (gas: 208372)
BitMathTest:testGas_MSB_Og() (gas: 274437)
FullMathTest:testFuzz_MulDiv96(uint256,uint256) (runs: 65536, μ: 3601, ~: 3585)
FullMathTest:testFuzz_MulDivUp_OZ(uint256,uint256,uint256) (runs: 65536, μ: 4391, ~: 4237)
Expand Down Expand Up @@ -37,26 +37,26 @@ NPMCallerTest:testRevert_OwnerOf() (gas: 14407)
NPMCallerTest:testRevert_Positions() (gas: 24241)
NPMCallerTest:test_Approve() (gas: 73011)
NPMCallerTest:test_Burn() (gas: 611858)
NPMCallerTest:test_Collect():(uint256) (gas: 599278)
NPMCallerTest:test_DecreaseLiquidity():(uint256) (gas: 564896)
NPMCallerTest:test_Collect() (gas: 599278)
NPMCallerTest:test_DecreaseLiquidity() (gas: 564896)
NPMCallerTest:test_Factory() (gas: 10194)
NPMCallerTest:test_IncreaseLiquidity() (gas: 840075)
NPMCallerTest:test_IsApprovedForAll() (gas: 21253)
NPMCallerTest:test_Mint():(uint256) (gas: 483283)
NPMCallerTest:test_Mint() (gas: 483283)
NPMCallerTest:test_Permit() (gas: 534552)
NPMCallerTest:test_SetApprovalForAll() (gas: 34758)
NPMCallerTest:test_TotalSupply() (gas: 11953)
PoolAddressTest:testFuzz_ComputeAddress(address,address,uint24) (runs: 65536, μ: 12175, ~: 12161)
PoolAddressTest:testFuzz_ComputeAddressCalldata(address,address,uint24) (runs: 65536, μ: 10260, ~: 10247)
PoolAddressTest:testFuzz_ComputeAddressFromKey(address,address,uint24) (runs: 65536, μ: 12465, ~: 12451)
PoolAddressTest:testFuzz_VerifyCallback(address,address,uint24) (runs: 65536, μ: 11510, ~: 11497)
PoolAddressTest:testFuzz_VerifyCallbackCalldata(address,address,uint24) (runs: 65536, μ: 10752, ~: 10739)
PoolAddressTest:testFuzz_VerifyCallback(address,address,uint24) (runs: 65536, μ: 11510, ~: 11524)
PoolAddressTest:testFuzz_VerifyCallbackCalldata(address,address,uint24) (runs: 65536, μ: 10752, ~: 10766)
PoolAddressTest:testGas_ComputeAddress() (gas: 7766)
PoolAddressTest:testGas_ComputeAddress_Og() (gas: 8464)
PoolCallerTest:testFuzz_LiquidityNet(int24) (runs: 16, μ: 18777, ~: 18777)
PoolCallerTest:testFuzz_Observations(uint256) (runs: 16, μ: 18976, ~: 19049)
PoolCallerTest:testFuzz_Positions(bytes32) (runs: 16, μ: 19317, ~: 19317)
PoolCallerTest:testFuzz_Swap(bool,uint256,bytes) (runs: 16, μ: 240356, ~: 227379)
PoolCallerTest:testFuzz_Swap(bool,uint256,bytes) (runs: 16, μ: 247341, ~: 231108)
PoolCallerTest:testFuzz_TickBitmap(int16) (runs: 16, μ: 11022, ~: 11022)
PoolCallerTest:testFuzz_Ticks(int24) (runs: 16, μ: 20800, ~: 20800)
PoolCallerTest:testRevert_AS_Swap() (gas: 13272)
Expand All @@ -83,13 +83,13 @@ SafeCastTest:testToInt256(uint256) (runs: 65536, μ: 1182, ~: 686)
SafeCastTest:testToUint128(uint256) (runs: 65536, μ: 1529, ~: 538)
SafeCastTest:testToUint160(uint256) (runs: 65536, μ: 1192, ~: 318)
SqrtPriceMathTest:testFuzz_GetAmount0Delta(uint160,uint160,int128) (runs: 65536, μ: 12859, ~: 12606)
SqrtPriceMathTest:testFuzz_GetAmount0Delta(uint160,uint160,uint128,bool) (runs: 65536, μ: 12501, ~: 12249)
SqrtPriceMathTest:testFuzz_GetAmount0Delta(uint160,uint160,uint128,bool) (runs: 65536, μ: 12535, ~: 12258)
SqrtPriceMathTest:testFuzz_GetAmount1Delta(uint160,uint160,int128) (runs: 65536, μ: 12507, ~: 12426)
SqrtPriceMathTest:testFuzz_GetAmount1Delta(uint160,uint160,uint128,bool) (runs: 65536, μ: 12512, ~: 12445)
SqrtPriceMathTest:testFuzz_GetNextSqrtPriceFromAmount0RoundingUp(uint160,uint128,uint256,bool) (runs: 65536, μ: 16943, ~: 17528)
SqrtPriceMathTest:testFuzz_GetNextSqrtPriceFromAmount1RoundingDown(uint160,uint128,uint256,bool) (runs: 65536, μ: 19439, ~: 20070)
SqrtPriceMathTest:testFuzz_GetNextSqrtPriceFromInput(uint160,uint128,uint256,bool) (runs: 65536, μ: 13267, ~: 12487)
SqrtPriceMathTest:testFuzz_GetNextSqrtPriceFromOutput(uint160,uint128,uint256,bool) (runs: 65536, μ: 13846, ~: 13600)
SqrtPriceMathTest:testFuzz_GetAmount1Delta(uint160,uint160,uint128,bool) (runs: 65536, μ: 12535, ~: 12563)
SqrtPriceMathTest:testFuzz_GetNextSqrtPriceFromAmount0RoundingUp(uint160,uint128,uint256,bool) (runs: 65536, μ: 16548, ~: 16401)
SqrtPriceMathTest:testFuzz_GetNextSqrtPriceFromAmount1RoundingDown(uint160,uint128,uint256,bool) (runs: 65536, μ: 19142, ~: 18700)
SqrtPriceMathTest:testFuzz_GetNextSqrtPriceFromInput(uint160,uint128,uint256,bool) (runs: 65536, μ: 13307, ~: 12857)
SqrtPriceMathTest:testFuzz_GetNextSqrtPriceFromOutput(uint160,uint128,uint256,bool) (runs: 65536, μ: 14064, ~: 14705)
SqrtPriceMathTest:testGas_GetAmount0Delta() (gas: 256572)
SqrtPriceMathTest:testGas_GetAmount0Delta_Og() (gas: 280254)
SqrtPriceMathTest:testGas_GetAmount1Delta() (gas: 209212)
Expand All @@ -98,30 +98,30 @@ SqrtPriceMathTest:testGas_GetNextSqrtPriceFromInput() (gas: 227868)
SqrtPriceMathTest:testGas_GetNextSqrtPriceFromInput_Og() (gas: 243885)
SqrtPriceMathTest:testGas_GetNextSqrtPriceFromOutput() (gas: 213109)
SqrtPriceMathTest:testGas_GetNextSqrtPriceFromOutput_Og() (gas: 225117)
SwapMathTest:testFuzz_ComputeSwapStep(uint160,uint160,uint128,int256,uint24) (runs: 65536, μ: 22139, ~: 22254)
SwapMathTest:testFuzz_ComputeSwapStepExactIn(uint160,uint160,uint128,uint256,uint24) (runs: 65536, μ: 23607, ~: 23636)
SwapMathTest:testFuzz_ComputeSwapStepExactOut(uint160,uint160,uint128,uint256,uint24) (runs: 65536, μ: 22950, ~: 22846)
SwapMathTest:testGas_ComputeSwapStep() (gas: 386504)
SwapMathTest:testFuzz_ComputeSwapStep(uint160,uint160,uint128,int256,uint24) (runs: 65536, μ: 22118, ~: 22228)
SwapMathTest:testFuzz_ComputeSwapStepExactIn(uint160,uint160,uint128,uint256,uint24) (runs: 65536, μ: 23606, ~: 23636)
SwapMathTest:testFuzz_ComputeSwapStepExactOut(uint160,uint160,uint128,uint256,uint24) (runs: 65536, μ: 22951, ~: 22846)
SwapMathTest:testGas_ComputeSwapStep() (gas: 384720)
SwapMathTest:testGas_ComputeSwapStepExactIn() (gas: 394759)
SwapMathTest:testGas_ComputeSwapStepExactIn_Og() (gas: 515722)
SwapMathTest:testGas_ComputeSwapStepExactOut() (gas: 370755)
SwapMathTest:testGas_ComputeSwapStepExactOut_Og() (gas: 510266)
SwapMathTest:testGas_ComputeSwapStep_Og() (gas: 526558)
TickBitmapTest:testFuzz_Compress(int24,int24) (runs: 65536, μ: 8348, ~: 8393)
TickBitmapTest:testFuzz_FlipTick(int24) (runs: 65536, μ: 61584, ~: 61590)
TickBitmapTest:testFuzz_NextInitializedTickWithinOneWord(int24,uint8,bool) (runs: 65536, μ: 67949, ~: 67992)
TickBitmapTest:testFuzz_Compress(int24,int24) (runs: 65536, μ: 8348, ~: 8382)
TickBitmapTest:testFuzz_FlipTick(int24) (runs: 65536, μ: 61570, ~: 61576)
TickBitmapTest:testFuzz_NextInitializedTickWithinOneWord(int24,uint8,bool) (runs: 65536, μ: 67880, ~: 67868)
TickBitmapTest:testFuzz_Position(int24) (runs: 65536, μ: 498, ~: 498)
TickBitmapTest:testGas_NextInitializedTickWithinOneWord() (gas: 6776007)
TickBitmapTest:testGas_NextInitializedTickWithinOneWord() (gas: 6769095)
TickBitmapTest:testGas_NextInitializedTickWithinOneWord_Og() (gas: 7050256)
TickBitmapTest:test_NextInitializedTickWithinOneWord_GT() (gas: 203148)
TickBitmapTest:test_NextInitializedTickWithinOneWord_LTE() (gas: 212522)
TickBitmapTest:test_NextInitializedTickWithinOneWord_LTE() (gas: 204586)
TickBitmapTest:test_NextInitializedTick_GT() (gas: 342054)
TickBitmapTest:test_NextInitializedTick_LTE() (gas: 399975)
TickMathTest:testFuzz_GetSqrtRatioAtTick(int24) (runs: 65536, μ: 16536, ~: 16831)
TickMathTest:testFuzz_GetTickAtSqrtRatio(uint160) (runs: 65536, μ: 13140, ~: 13159)
TickBitmapTest:test_NextInitializedTick_LTE() (gas: 388455)
TickMathTest:testFuzz_GetSqrtRatioAtTick(int24) (runs: 65536, μ: 16522, ~: 16817)
TickMathTest:testFuzz_GetTickAtSqrtRatio(uint160) (runs: 65536, μ: 13125, ~: 13145)
TickMathTest:testGas_GetSqrtRatioAtTick() (gas: 146478)
TickMathTest:testGas_GetSqrtRatioAtTick_Og() (gas: 168547)
TickMathTest:testGas_GetTickAtSqrtRatio() (gas: 252577)
TickMathTest:testGas_GetTickAtSqrtRatio() (gas: 251177)
TickMathTest:testGas_GetTickAtSqrtRatio_Og() (gas: 307790)
TickMathTest:testRevert_GetSqrtRatioAtTick() (gas: 10445)
TickMathTest:testRevert_GetTickAtSqrtRatio() (gas: 10522)
12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@aperture_finance/uni-v3-lib",
"description": "A suite of Solidity libraries that have been imported and rewritten from Uniswap's v3-core and v3-periphery",
"version": "1.2.0",
"version": "1.2.1",
"author": "Aperture Finance",
"homepage": "https://aperture.finance/",
"license": "GPL-2.0-or-later",
Expand Down Expand Up @@ -32,15 +32,15 @@
"prettier:fix": "prettier -w {src,test}/**/*.sol"
},
"dependencies": {
"@openzeppelin/contracts": "^5.0.0",
"@openzeppelin/contracts": "^5.0.1",
"@uniswap/v3-core": "^1.0.1",
"@uniswap/v3-periphery": "^1.4.4",
"solady": "^0.0.138"
"solady": "^0.0.155"
},
"devDependencies": {
"prettier": "^3.0.3",
"prettier-plugin-solidity": "^1.1.3",
"typescript": "^5.2.2"
"prettier": "^3.1.1",
"prettier-plugin-solidity": "^1.3.1",
"typescript": "^5.3.3"
},
"prettier": {
"plugins": [
Expand Down
20 changes: 6 additions & 14 deletions src/BitMath.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,13 @@ library BitMath {
r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))
// r += (x >> r) >= 2**32 ? 32 : 0
r := or(r, shl(5, lt(0xffffffff, shr(r, x))))

// For the remaining 32 bits, use a De Bruijn lookup.
// https://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn
x := shr(r, x)
x := or(x, shr(1, x))
x := or(x, shr(2, x))
x := or(x, shr(4, x))
x := or(x, shr(8, x))
x := or(x, shr(16, x))

r := or(r, shl(4, lt(0xffff, shr(r, x))))
r := or(r, shl(3, lt(0xff, shr(r, x))))
r := or(
r,
byte(
shr(251, mul(x, shl(224, 0x07c4acdd))),
0x0009010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f
and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)),
0x0706060506020504060203020504030106050205030304010505030400000000
)
)
}
Expand Down Expand Up @@ -65,8 +57,8 @@ library BitMath {
r := or(
r,
byte(
shr(251, mul(shr(r, x), shl(224, 0x077cb531))),
0x00011c021d0e18031e16140f191104081f1b0d17151310071a0c12060b050a09
and(div(0xd76453e0, shr(r, x)), 0x1f),
0x001f0d1e100c1d070f090b19131c1706010e11080a1a141802121b1503160405
)
)
}
Expand Down
15 changes: 7 additions & 8 deletions src/SwapMath.sol
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,13 @@ library SwapMath {
unchecked {
bool zeroForOne = sqrtRatioCurrentX96 >= sqrtRatioTargetX96;
uint256 feeComplement = MAX_FEE_PIPS - feePips;
bool exactOut;
bool exactOut = amountRemaining < 0;
uint256 amountRemainingAbs;
assembly {
// exactOut = 1 if amountRemaining < 0 else 0
exactOut := slt(amountRemaining, 0)
// mask = -1 if amountRemaining < 0 else 0
let mask := sub(0, exactOut)
amountRemainingAbs := xor(mask, add(mask, amountRemaining))
}

if (!exactOut) {
assembly {
amountRemainingAbs := amountRemaining
}
uint256 amountRemainingLessFee = FullMath.mulDiv(amountRemainingAbs, feeComplement, MAX_FEE_PIPS);
amountIn = zeroForOne
? SqrtPriceMath.getAmount0Delta(sqrtRatioTargetX96, sqrtRatioCurrentX96, liquidity, true)
Expand Down Expand Up @@ -92,6 +88,9 @@ library SwapMath {
amountOut = zeroForOne
? SqrtPriceMath.getAmount1Delta(sqrtRatioTargetX96, sqrtRatioCurrentX96, liquidity, false)
: SqrtPriceMath.getAmount0Delta(sqrtRatioCurrentX96, sqrtRatioTargetX96, liquidity, false);
assembly {
amountRemainingAbs := sub(0, amountRemaining)
}
if (amountRemainingAbs >= amountOut) {
// `amountOut` is capped by the target price
sqrtRatioNextX96 = sqrtRatioTargetX96;
Expand Down
15 changes: 4 additions & 11 deletions src/TickMath.sol
Original file line number Diff line number Diff line change
Expand Up @@ -135,20 +135,13 @@ library TickMath {
msb := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))
msb := or(msb, shl(6, lt(0xffffffffffffffff, shr(msb, x))))
msb := or(msb, shl(5, lt(0xffffffff, shr(msb, x))))

// For the remaining 32 bits, use a De Bruijn lookup.
x := shr(msb, x)
x := or(x, shr(1, x))
x := or(x, shr(2, x))
x := or(x, shr(4, x))
x := or(x, shr(8, x))
x := or(x, shr(16, x))

msb := or(msb, shl(4, lt(0xffff, shr(msb, x))))
msb := or(msb, shl(3, lt(0xff, shr(msb, x))))
msb := or(
msb,
byte(
shr(251, mul(x, shl(224, 0x07c4acdd))),
0x0009010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f
and(0x1f, shr(shr(msb, x), 0x8421084210842108cc6318c6db6d54be)),
0x0706060506020504060203020504030106050205030304010505030400000000
)
)
}
Expand Down
Loading

0 comments on commit 1e2e1b3

Please sign in to comment.