Skip to content

Commit

Permalink
add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
snreynolds committed Oct 21, 2024
1 parent 3daf662 commit c7ad6b7
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 0 deletions.
37 changes: 37 additions & 0 deletions test/mocks/MockReenterHook.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;

import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol";
import {BaseTestHooks} from "@uniswap/v4-core/src/test/BaseTestHooks.sol";
import {PositionManager} from "../../src/PositionManager.sol";

contract MockReenterHook is BaseTestHooks {
PositionManager posm;

function beforeAddLiquidity(
address,
PoolKey calldata,
IPoolManager.ModifyLiquidityParams calldata,
bytes calldata functionSelector
) external override returns (bytes4) {
if (functionSelector.length == 0) {
return this.beforeAddLiquidity.selector;
}
(bytes4 selector, address owner, uint256 tokenId) = abi.decode(functionSelector, (bytes4, address, uint256));

if (selector == posm.transferFrom.selector) {
posm.transferFrom(owner, address(this), tokenId);
} else if (selector == posm.subscribe.selector) {
posm.subscribe(tokenId, address(this), "");
} else if (selector == posm.unsubscribe.selector) {
posm.unsubscribe(tokenId);
}
return this.beforeAddLiquidity.selector;
}

function setPosm(PositionManager _posm) external {
posm = _posm;
}
}
81 changes: 81 additions & 0 deletions test/position-managers/PositionManager.notifier.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
import {StateLibrary} from "@uniswap/v4-core/src/libraries/StateLibrary.sol";
import {PoolIdLibrary} from "@uniswap/v4-core/src/types/PoolId.sol";
import {BalanceDelta, toBalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol";
import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol";
import {GasSnapshot} from "forge-gas-snapshot/GasSnapshot.sol";
import {PosmTestSetup} from "../shared/PosmTestSetup.sol";
import {MockSubscriber} from "../mocks/MockSubscriber.sol";
Expand All @@ -20,6 +21,7 @@ import {Actions} from "../../src/libraries/Actions.sol";
import {INotifier} from "../../src/interfaces/INotifier.sol";
import {MockReturnDataSubscriber, MockRevertSubscriber} from "../mocks/MockBadSubscribers.sol";
import {PositionInfoLibrary, PositionInfo} from "../../src/libraries/PositionInfoLibrary.sol";
import {MockReenterHook} from "../mocks/MockReenterHook.sol";

contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot {
using PoolIdLibrary for PoolKey;
Expand All @@ -31,10 +33,13 @@ contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot {
MockReturnDataSubscriber badSubscriber;
PositionConfig config;
MockRevertSubscriber revertSubscriber;
MockReenterHook reenterHook;

address alice = makeAddr("ALICE");
address bob = makeAddr("BOB");

PositionConfig reenterConfig;

function setUp() public {
deployFreshManagerAndRouters();
deployMintAndApprove2Currencies();
Expand All @@ -49,6 +54,17 @@ contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot {
revertSubscriber = new MockRevertSubscriber(lpm);
config = PositionConfig({poolKey: key, tickLower: -300, tickUpper: 300});

// set the reenter hook
MockReenterHook impl = new MockReenterHook();
address hookAddr = payable(address(uint160(Hooks.BEFORE_ADD_LIQUIDITY_FLAG)));
vm.etch(hookAddr, address(impl).code);
reenterHook = MockReenterHook(hookAddr);
reenterHook.setPosm(lpm);

PoolKey memory reenterKey = PoolKey(currency0, currency1, 3000, 60, IHooks(reenterHook));
manager.initialize(reenterKey, SQRT_PRICE_1_1);
reenterConfig = PositionConfig({poolKey: reenterKey, tickLower: -60, tickUpper: 60});

// TODO: Test NATIVE poolKey
}

Expand Down Expand Up @@ -647,4 +663,69 @@ contract PositionManagerNotifierTest is Test, PosmTestSetup, GasSnapshot {
assertEq(sub.notifyUnsubscribeCount(), beforeUnsubCount + 1);
}
}

function test_unsubscribe_reverts_PoolManagerMustBeLocked() public {
uint256 tokenId = lpm.nextTokenId();
mint(reenterConfig, 10e18, address(this), ZERO_BYTES);

bytes memory hookData = abi.encode(lpm.unsubscribe.selector, address(this), tokenId);
bytes memory actions = getMintEncoded(reenterConfig, 10e18, address(this), hookData);

// approve hook as it should not revert because it does not have permissions
lpm.approve(address(reenterHook), tokenId);
// subscribe as it should not revert because there is no subscriber
lpm.subscribe(tokenId, address(sub), ZERO_BYTES);

// should revert since the pool manager is unlocked
vm.expectRevert(
abi.encodeWithSelector(
Hooks.Wrap__FailedHookCall.selector,
address(reenterHook),
abi.encodeWithSelector(IPositionManager.PoolManagerMustBeLocked.selector)
)
);
lpm.modifyLiquidities(actions, _deadline);
}

function test_subscribe_reverts_PoolManagerMustBeLocked() public {
uint256 tokenId = lpm.nextTokenId();
mint(reenterConfig, 10e18, address(this), ZERO_BYTES);

bytes memory hookData = abi.encode(lpm.subscribe.selector, address(this), tokenId);
bytes memory actions = getMintEncoded(reenterConfig, 10e18, address(this), hookData);

// approve hook as it should not revert because it does not have permissions
lpm.approve(address(reenterHook), tokenId);

// should revert since the pool manager is unlocked
vm.expectRevert(
abi.encodeWithSelector(
Hooks.Wrap__FailedHookCall.selector,
address(reenterHook),
abi.encodeWithSelector(IPositionManager.PoolManagerMustBeLocked.selector)
)
);
lpm.modifyLiquidities(actions, _deadline);
}

function test_transferFrom_reverts_PoolManagerMustBeLocked() public {
uint256 tokenId = lpm.nextTokenId();
mint(reenterConfig, 10e18, address(this), ZERO_BYTES);

bytes memory hookData = abi.encode(lpm.transferFrom.selector, address(this), tokenId);
bytes memory actions = getMintEncoded(reenterConfig, 10e18, address(this), hookData);

// approve hook as it should not revert because it does not have permissions
lpm.approve(address(reenterHook), tokenId);

// should revert since the pool manager is unlocked
vm.expectRevert(
abi.encodeWithSelector(
Hooks.Wrap__FailedHookCall.selector,
address(reenterHook),
abi.encodeWithSelector(IPositionManager.PoolManagerMustBeLocked.selector)
)
);
lpm.modifyLiquidities(actions, _deadline);
}
}

0 comments on commit c7ad6b7

Please sign in to comment.