Files

83 lines
3.3 KiB
Solidity

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;
import {Test} from "forge-std/Test.sol";
import {Position} from "../../src/libraries/Position.sol";
import {SafeCast} from "../../src/libraries/SafeCast.sol";
contract PositionTest is Test {
using Position for mapping(bytes32 => Position.State);
mapping(bytes32 => Position.State) internal positions;
function test_fuzz_get(address owner, int24 tickLower, int24 tickUpper, bytes32 salt) public view {
bytes32 positionKey = keccak256(abi.encodePacked(owner, tickLower, tickUpper, salt));
Position.State storage expectedPosition = positions[positionKey];
Position.State storage position = positions.get(owner, tickLower, tickUpper, salt);
bytes32 expectedPositionSlot;
bytes32 positionSlot;
assembly ("memory-safe") {
expectedPositionSlot := expectedPosition.slot
positionSlot := position.slot
}
assertEq(positionSlot, expectedPositionSlot, "slots not equal");
}
function test_fuzz_update(
int128 liquidityDelta,
Position.State memory pos,
uint256 newFeeGrowthInside0X128,
uint256 newFeeGrowthInside1X128
) public {
Position.State storage position = positions[0];
position.liquidity = pos.liquidity;
position.feeGrowthInside0LastX128 = pos.feeGrowthInside0LastX128;
position.feeGrowthInside1LastX128 = pos.feeGrowthInside1LastX128;
uint128 oldLiquidity = position.liquidity;
if (position.liquidity == 0 && liquidityDelta == 0) {
vm.expectRevert(Position.CannotUpdateEmptyPosition.selector);
}
// new liquidity cannot overflow/underflow uint128
uint256 absLiquidityDelta;
if (liquidityDelta > 0) {
absLiquidityDelta = uint256(uint128(liquidityDelta));
uint256 newLiquidity = position.liquidity + absLiquidityDelta;
if (newLiquidity > type(uint128).max) {
vm.expectRevert(SafeCast.SafeCastOverflow.selector);
}
} else if (liquidityDelta < 0) {
if (liquidityDelta == type(int128).min) {
absLiquidityDelta = uint256(uint128(type(int128).max)) + 1;
} else {
absLiquidityDelta = uint256(uint128(-liquidityDelta));
}
if (position.liquidity < absLiquidityDelta) {
vm.expectRevert(SafeCast.SafeCastOverflow.selector);
}
}
Position.update(position, liquidityDelta, newFeeGrowthInside0X128, newFeeGrowthInside1X128);
if (liquidityDelta == 0) {
assertEq(position.liquidity, oldLiquidity);
} else if (liquidityDelta > 0) {
assertEq(position.liquidity, oldLiquidity + absLiquidityDelta);
} else {
assertEq(position.liquidity, oldLiquidity - absLiquidityDelta);
}
assertEq(position.feeGrowthInside0LastX128, newFeeGrowthInside0X128);
assertEq(position.feeGrowthInside1LastX128, newFeeGrowthInside1X128);
}
function test_fuzz_calculatePositionKey(address owner, int24 tickLower, int24 tickUpper, bytes32 salt)
public
pure
{
bytes32 positionKey = Position.calculatePositionKey(owner, tickLower, tickUpper, salt);
assertEq(positionKey, keccak256(abi.encodePacked(owner, tickLower, tickUpper, salt)));
}
}