Skip to content

Commit

Permalink
feat: Support SettleAndMintRefund in periphery (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
ChefSnoopy authored Mar 25, 2024
1 parent 0d1987b commit ba7169c
Show file tree
Hide file tree
Showing 40 changed files with 244 additions and 38 deletions.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
79699
80435
Original file line number Diff line number Diff line change
@@ -1 +1 @@
627067
627803
Original file line number Diff line number Diff line change
@@ -1 +1 @@
918147
919685
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1268812
1270351
Original file line number Diff line number Diff line change
@@ -1 +1 @@
80824
80759
Original file line number Diff line number Diff line change
@@ -1 +1 @@
117826
117761
Original file line number Diff line number Diff line change
@@ -1 +1 @@
114631
114566
Original file line number Diff line number Diff line change
@@ -1 +1 @@
29390
9490
2 changes: 1 addition & 1 deletion .forge-snapshots/BinFungibleTokenTest#testMint.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
43594
43591
Original file line number Diff line number Diff line change
@@ -1 +1 @@
138752
139491
Original file line number Diff line number Diff line change
@@ -1 +1 @@
131484
132217
Original file line number Diff line number Diff line change
@@ -1 +1 @@
136297
137030
Original file line number Diff line number Diff line change
@@ -1 +1 @@
132258
132997
Original file line number Diff line number Diff line change
@@ -1 +1 @@
132333
133072
Original file line number Diff line number Diff line change
@@ -1 +1 @@
167590
168327
Original file line number Diff line number Diff line change
@@ -1 +1 @@
144076
144815
Original file line number Diff line number Diff line change
@@ -1 +1 @@
137582
138321
Original file line number Diff line number Diff line change
@@ -1 +1 @@
137669
138408
Original file line number Diff line number Diff line change
@@ -1 +1 @@
172111
172844
Original file line number Diff line number Diff line change
@@ -1 +1 @@
130040
130773
2 changes: 1 addition & 1 deletion .forge-snapshots/CLSwapRouterTest#ExactInput.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
250131
250868
2 changes: 1 addition & 1 deletion .forge-snapshots/CLSwapRouterTest#ExactInputSingle.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
180878
181611
2 changes: 1 addition & 1 deletion .forge-snapshots/CLSwapRouterTest#ExactOutput.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
256134
256867
2 changes: 1 addition & 1 deletion .forge-snapshots/CLSwapRouterTest#ExactOutputSingle.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
180439
181172
2 changes: 1 addition & 1 deletion .forge-snapshots/NonfungiblePositionManager#collect.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
199252
199079
Original file line number Diff line number Diff line change
@@ -1 +1 @@
75212
75144
Original file line number Diff line number Diff line change
@@ -1 +1 @@
80908
82440
2 changes: 1 addition & 1 deletion .forge-snapshots/NonfungiblePositionManager#mint.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
624939
626477
2 changes: 1 addition & 1 deletion lib/pancake-v4-core
2 changes: 1 addition & 1 deletion lib/solmate
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"test": "forge test",
"dev": "forge test -vvv -w",
"snapshot": "rm -fr .forge-snapshots && forge test",
"prettier": "forge fmt contracts/ && forge fmt test/ && forge fmt script/",
"prettier": "forge fmt src/ && forge fmt test/ && forge fmt script/",
"prettier-check": "forge fmt --check"
}
}
2 changes: 1 addition & 1 deletion src/SwapRouterBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ abstract contract SwapRouterBase is ISwapRouterBase {

function _payAndSettle(Currency currency, address msgSender, int128 settleAmount) internal virtual {
_pay(currency, msgSender, address(vault), uint256(uint128(settleAmount)));
vault.settle(currency);
vault.settleAndMintRefund(currency, msgSender);
}

function _pay(Currency currency, address payer, address recipient, uint256 amount) internal virtual;
Expand Down
4 changes: 2 additions & 2 deletions src/pool-bin/BinFungiblePositionManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -227,14 +227,14 @@ contract BinFungiblePositionManager is
function _settleDeltas(address user, PoolKey memory poolKey, BalanceDelta delta) internal {
if (delta.amount0() > 0) {
pay(poolKey.currency0, user, address(vault), uint256(int256(delta.amount0())));
vault.settle(poolKey.currency0);
vault.settleAndMintRefund(poolKey.currency0, user);
} else if (delta.amount0() < 0) {
vault.take(poolKey.currency0, user, uint128(-delta.amount0()));
}

if (delta.amount1() > 0) {
pay(poolKey.currency1, user, address(vault), uint256(int256(delta.amount1())));
vault.settle(poolKey.currency1);
vault.settleAndMintRefund(poolKey.currency1, user);
} else if (delta.amount1() < 0) {
vault.take(poolKey.currency1, user, uint128(-delta.amount1()));
}
Expand Down
4 changes: 2 additions & 2 deletions src/pool-cl/base/LiquidityManagement.sol
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,13 @@ abstract contract LiquidityManagement is CLPeripheryImmutableState, PeripheryPay
function settleDeltas(address sender, PoolKey memory poolKey, BalanceDelta delta) internal {
if (delta.amount0() > 0) {
pay(poolKey.currency0, sender, address(vault), uint256(int256(delta.amount0())));
vault.settle(poolKey.currency0);
vault.settleAndMintRefund(poolKey.currency0, sender);
} else if (delta.amount0() < 0) {
vault.take(poolKey.currency0, sender, uint128(-delta.amount0()));
}
if (delta.amount1() > 0) {
pay(poolKey.currency1, sender, address(vault), uint256(int256(delta.amount1())));
vault.settle(poolKey.currency1);
vault.settleAndMintRefund(poolKey.currency1, sender);
} else if (delta.amount1() < 0) {
vault.take(poolKey.currency1, sender, uint128(-delta.amount1()));
}
Expand Down
37 changes: 37 additions & 0 deletions test/pool-bin/BinFungiblePositionManager_AddLiquidity.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -538,4 +538,41 @@ contract BinFungiblePositionManager_AddLiquidityTest is Test, GasSnapshot, Liqui
deadline: block.timestamp + 600
});
}

function testSettleAndMintRefund() public {
// transfer excess token to vault
uint256 excessTokenAmount = 1 ether;
address hacker = address(1);
token0.mint(hacker, excessTokenAmount);
vm.startPrank(hacker);
token0.transfer(address(vault), excessTokenAmount);
vm.stopPrank();

// pre-test, verify alice has 1e18 token0 and token1
token0.mint(alice, 1 ether);
token1.mint(alice, 1 ether);
assertEq(token0.balanceOf(alice), 1 ether);
assertEq(token1.balanceOf(alice), 1 ether);

vm.startPrank(alice);
uint24[] memory binIds = getBinIds(activeId, 3);
IBinFungiblePositionManager.AddLiquidityParams memory params;
params = _getAddParams(key1, binIds, 1 ether, 1 ether, activeId, alice);
(,, uint256[] memory tokenIds,) = binFungiblePositionManager.addLiquidity(params);

for (uint256 i; i < tokenIds.length; i++) {
(Currency curr0, Currency curr1, uint24 fee, uint24 binId) =
binFungiblePositionManager.positions(tokenIds[i]);
assertEq(Currency.unwrap(curr0), Currency.unwrap(key1.currency0));
assertEq(Currency.unwrap(curr1), Currency.unwrap(key1.currency1));
assertEq(fee, key1.fee);
assertEq(binId, binIds[i]);
}

// check currency balance in vault
{
uint256 currency0Balance = vault.balanceOf(alice, currency0);
assertEq(currency0Balance, excessTokenAmount, "Unexpected currency0 balance in vault");
}
}
}
41 changes: 41 additions & 0 deletions test/pool-bin/BinSwapRouter.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,47 @@ contract BinSwapRouterTest is Test, GasSnapshot, LiquidityParamsHelper {
assertEq(token0.balanceOf(alice), abi.decode(result[0], (uint256)));
}

function testSettleAndMintRefund() public {
// transfer excess token to vault
uint256 excessTokenAmount = 1 ether;
address hacker = address(1);
token0.mint(hacker, excessTokenAmount);
vm.startPrank(hacker);
token0.transfer(address(vault), excessTokenAmount);
vm.stopPrank();

vm.startPrank(alice);
token0.mint(alice, 1 ether);

ISwapRouterBase.PathKey[] memory path = new ISwapRouterBase.PathKey[](1);
path[0] = ISwapRouterBase.PathKey({
intermediateCurrency: Currency.wrap(address(token1)),
fee: key.fee,
hooks: key.hooks,
hookData: new bytes(0),
poolManager: key.poolManager,
parameters: key.parameters
});

uint256 amountOut = router.exactInput(
IBinSwapRouterBase.V4BinExactInputParams({
currencyIn: Currency.wrap(address(token0)),
path: path,
recipient: alice,
amountIn: 1 ether,
amountOutMinimum: 0
}),
block.timestamp + 60
);
assertEq(token1.balanceOf(alice), amountOut);

// check currency balance in vault
{
uint256 currency0Balance = vault.balanceOf(alice, Currency.wrap(address(token0)));
assertEq(currency0Balance, excessTokenAmount, "Unexpected currency0 balance in vault");
}
}

// function testExactOutput_InsufficientAmountOut() public {
// //todo: in order to simulate this error, require
// // 1. hooks at beforeSwap do something funny on the pool resulting in actual amountOut lesser
Expand Down
34 changes: 34 additions & 0 deletions test/pool-cl/CLSwapRouter.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,40 @@ contract CLSwapRouterTest is TokenFixture, Test, GasSnapshot {
snapEnd();
}

function testSettleAndMintRefund() external {
// transfer excess token to vault
uint256 excessTokenAmount = 1 ether;
address hacker = address(1);
MockERC20(Currency.unwrap(currency0)).mint(hacker, excessTokenAmount);
vm.startPrank(hacker);
MockERC20(Currency.unwrap(currency0)).transfer(address(vault), excessTokenAmount);
vm.stopPrank();

uint256 amountOut = router.exactInputSingle(
ICLSwapRouterBase.V4CLExactInputSingleParams({
poolKey: poolKey0,
zeroForOne: true,
recipient: makeAddr("recipient"),
amountIn: 0.01 ether,
amountOutMinimum: 0,
sqrtPriceLimitX96: 0,
hookData: new bytes(0)
}),
block.timestamp + 100
);

uint256 received = IERC20(Currency.unwrap(currency1)).balanceOf(makeAddr("recipient"));
assertEq(received, amountOut);
// considering slippage and fee, tolerance is 1%
assertApproxEqAbs(amountOut, 1 ether, amountOut / 100);

// check currency balance in vault
{
uint256 currency0Balance = vault.balanceOf(address(this), currency0);
assertEq(currency0Balance, excessTokenAmount, "Unexpected currency0 balance in vault");
}
}

// allow refund of ETH
receive() external payable {}
}
Loading

0 comments on commit ba7169c

Please sign in to comment.