diff --git a/contracts/UniswapV3Pool.sol b/contracts/UniswapV3Pool.sol index 4a22ff386..4c7c91d9c 100644 --- a/contracts/UniswapV3Pool.sol +++ b/contracts/UniswapV3Pool.sol @@ -152,19 +152,9 @@ contract UniswapV3Pool is IUniswapV3Pool, NoDelegateCall { ) { checkTicks(tickLower, tickUpper); - StateMath.SnapshotArgs memory args = StateMath.SnapshotArgs( - slot0, - liquidity, - _blockTimestamp(), - tickLower, - tickUpper - - ); - return StateMath.snapshotCumulativesInside( - ticks, - observations, - args - ); + StateMath.SnapshotArgs memory args = + StateMath.SnapshotArgs(slot0, liquidity, _blockTimestamp(), tickLower, tickUpper); + return StateMath.snapshotCumulativesInside(ticks, observations, args); } /// @inheritdoc IUniswapV3PoolDerivedState @@ -296,21 +286,16 @@ contract UniswapV3Pool is IUniswapV3Pool, NoDelegateCall { function makeFeeParams() private view returns (Tick.FeeParams memory params) { uint32 time = _blockTimestamp(); (int56 tickCumulative, uint160 secondsPerLiquidityCumulativeX128) = - observations.observeSingle( - time, - 0, - slot0.tick, - slot0.observationIndex, - liquidity, - slot0.observationCardinality - ); + observations.observeSingle( + time, + 0, + slot0.tick, + slot0.observationIndex, + liquidity, + slot0.observationCardinality + ); - params = Tick.FeeParams( - tickCumulative, - secondsPerLiquidityCumulativeX128, - time, - maxLiquidityPerTick - ); + params = Tick.FeeParams(tickCumulative, secondsPerLiquidityCumulativeX128, time, maxLiquidityPerTick); } /// @dev Gets and updates a position with the given liquidity delta @@ -485,27 +470,22 @@ contract UniswapV3Pool is IUniswapV3Pool, NoDelegateCall { computedLatestObservation: false }); - StateMath.SwapState memory state; + StateMath.SwapState memory state; bool exactInput; // pack the arguments to avoid abi encoder - StateMath.SwapArgs memory args = StateMath.SwapArgs( - cache, - fee, - tickSpacing, - feeGrowthGlobal0X128, - feeGrowthGlobal1X128, - zeroForOne, - amountSpecified, - sqrtPriceLimitX96 - ); - (state, cache, exactInput) = StateMath.swap( - args, - slot0, - ticks, - observations, - tickBitmap - ); + StateMath.SwapArgs memory args = + StateMath.SwapArgs( + cache, + fee, + tickSpacing, + feeGrowthGlobal0X128, + feeGrowthGlobal1X128, + zeroForOne, + amountSpecified, + sqrtPriceLimitX96 + ); + (state, cache, exactInput) = StateMath.swap(args, slot0, ticks, observations, tickBitmap); // update liquidity if it changed if (cache.liquidityStart != state.liquidity) liquidity = state.liquidity; diff --git a/contracts/libraries/StateMath.sol b/contracts/libraries/StateMath.sol index 29f8c663b..5edd57b18 100644 --- a/contracts/libraries/StateMath.sol +++ b/contracts/libraries/StateMath.sol @@ -2,19 +2,19 @@ pragma solidity ^0.7.6; pragma abicoder v2; -import "./../UniswapV3Pool.sol"; +import './../UniswapV3Pool.sol'; import './../interfaces/IERC20Minimal.sol'; -import "./../interfaces/callback/IUniswapV3SwapCallback.sol"; - -import "./TickMath.sol"; -import "./Tick.sol"; -import "./TickBitmap.sol"; -import "./SwapMath.sol"; -import "./FullMath.sol"; -import "./Oracle.sol"; -import "./FixedPoint128.sol"; -import "./SafeCast.sol"; -import "./LowGasSafeMath.sol"; +import './../interfaces/callback/IUniswapV3SwapCallback.sol'; + +import './TickMath.sol'; +import './Tick.sol'; +import './TickBitmap.sol'; +import './SwapMath.sol'; +import './FullMath.sol'; +import './Oracle.sol'; +import './FixedPoint128.sol'; +import './SafeCast.sol'; +import './LowGasSafeMath.sol'; library StateMath { using SafeCast for uint256; @@ -59,32 +59,37 @@ library StateMath { mapping(int24 => Tick.Info) storage ticks, Oracle.Observation[65535] storage observations, mapping(int16 => uint256) storage tickBitmap - ) public returns (SwapState memory state, SwapCache memory, bool) { + ) + public + returns ( + SwapState memory state, + SwapCache memory, + bool + ) + { Slot0 memory slot0Start = slot0; - state = - SwapState({ - amountSpecifiedRemaining: args.amountSpecified, - amountCalculated: 0, - sqrtPriceX96: slot0Start.sqrtPriceX96, - tick: slot0Start.tick, - feeGrowthGlobalX128: args.zeroForOne ? args.feeGrowthGlobal0X128 : args.feeGrowthGlobal1X128, - protocolFee: 0, - liquidity: args.cache.liquidityStart - }); + state = SwapState({ + amountSpecifiedRemaining: args.amountSpecified, + amountCalculated: 0, + sqrtPriceX96: slot0Start.sqrtPriceX96, + tick: slot0Start.tick, + feeGrowthGlobalX128: args.zeroForOne ? args.feeGrowthGlobal0X128 : args.feeGrowthGlobal1X128, + protocolFee: 0, + liquidity: args.cache.liquidityStart + }); // continue swapping as long as we haven't used the entire input/output and haven't reached the price limit while (state.amountSpecifiedRemaining != 0 && state.sqrtPriceX96 != args.sqrtPriceLimitX96) { - StepComputations memory step = createStep( - tickBitmap, - state, - args.zeroForOne, - args.tickSpacing - ); + StepComputations memory step = createStep(tickBitmap, state, args.zeroForOne, args.tickSpacing); // compute values to swap to the target tick, price limit, or point where input/output amount is exhausted (state.sqrtPriceX96, step.amountIn, step.amountOut, step.feeAmount) = SwapMath.computeSwapStep( state.sqrtPriceX96, - (args.zeroForOne ? step.sqrtPriceNextX96 < args.sqrtPriceLimitX96 : step.sqrtPriceNextX96 > args.sqrtPriceLimitX96) + ( + args.zeroForOne + ? step.sqrtPriceNextX96 < args.sqrtPriceLimitX96 + : step.sqrtPriceNextX96 > args.sqrtPriceLimitX96 + ) ? args.sqrtPriceLimitX96 : step.sqrtPriceNextX96, state.liquidity, @@ -119,15 +124,14 @@ library StateMath { // update tick and write an oracle entry if the tick change if (state.tick != slot0Start.tick) { SwapCache memory cache = args.cache; - (slot0.observationIndex, slot0.observationCardinality) = - observations.write( - slot0Start.observationIndex, - cache.blockTimestamp, - slot0Start.tick, - cache.liquidityStart, - slot0Start.observationCardinality, - slot0Start.observationCardinalityNext - ); + (slot0.observationIndex, slot0.observationCardinality) = observations.write( + slot0Start.observationIndex, + cache.blockTimestamp, + slot0Start.tick, + cache.liquidityStart, + slot0Start.observationCardinality, + slot0Start.observationCardinalityNext + ); slot0.sqrtPriceX96 = state.sqrtPriceX96; slot0.tick = state.tick; } else { @@ -140,9 +144,9 @@ library StateMath { function shiftTick( Slot0 memory slot0Start, - SwapState memory state, - StepComputations memory step, - SwapArgs memory args, + SwapState memory state, + StepComputations memory step, + SwapArgs memory args, mapping(int24 => Tick.Info) storage ticks, Oracle.Observation[65535] storage observations ) private returns (SwapState memory) { @@ -238,11 +242,12 @@ library StateMath { uint256 feeAmount; } - function createStep(mapping(int16 => uint256) storage tickBitmap, SwapState memory state, bool zeroForOne, int24 tickSpacing) - - public - view returns (StepComputations memory step) - { + function createStep( + mapping(int16 => uint256) storage tickBitmap, + SwapState memory state, + bool zeroForOne, + int24 tickSpacing + ) public view returns (StepComputations memory step) { step.sqrtPriceStartX96 = state.sqrtPriceX96; (step.tickNext, step.initialized) = tickBitmap.nextInitializedTickWithinOneWord( @@ -319,19 +324,16 @@ library StateMath { secondsOutsideLower - secondsOutsideUpper ); } else if (args.slot0.tick < args.tickUpper) { - ObsArgs memory args2 = ObsArgs( - tickCumulativeLower, - tickCumulativeUpper, - secondsPerLiquidityOutsideLowerX128, - secondsPerLiquidityOutsideUpperX128, - secondsOutsideLower, - secondsOutsideUpper - ); - return observeTick( - observations, - args, - args2 - ); + ObsArgs memory args2 = + ObsArgs( + tickCumulativeLower, + tickCumulativeUpper, + secondsPerLiquidityOutsideLowerX128, + secondsPerLiquidityOutsideUpperX128, + secondsOutsideLower, + secondsOutsideUpper + ); + return observeTick(observations, args, args2); } else { return ( tickCumulativeUpper - tickCumulativeLower, diff --git a/contracts/libraries/Tick.sol b/contracts/libraries/Tick.sol index 9e8491200..9eaa4a819 100644 --- a/contracts/libraries/Tick.sol +++ b/contracts/libraries/Tick.sol @@ -95,7 +95,6 @@ library Tick { feeGrowthInside1X128 = feeGrowthGlobal1X128 - feeGrowthBelow1X128 - feeGrowthAbove1X128; } - struct FeeParams { int56 tickCumulative; uint160 secondsPerLiquidityCumulativeX128; diff --git a/test/UniswapV3Pool.spec.ts b/test/UniswapV3Pool.spec.ts index fb1a428d4..9f94fe2a4 100644 --- a/test/UniswapV3Pool.spec.ts +++ b/test/UniswapV3Pool.spec.ts @@ -1355,9 +1355,7 @@ describe('UniswapV3Pool', () => { const sqrtTickMath = (await ( await ethers.getContractFactory('TickMathTest', { libraries: { TickMath: tickMathLib.address } }) ).deploy()) as TickMathTest - const swapMath = (await ( - await ethers.getContractFactory('SwapMathTest') - ).deploy()) as SwapMathTest + const swapMath = (await (await ethers.getContractFactory('SwapMathTest')).deploy()) as SwapMathTest const p0 = (await sqrtTickMath.getSqrtRatioAtTick(-24081)).add(1) // initialize at a price of ~0.3 token1/token0 // meaning if you swap in 2 token0, you should end up getting 0 token1