From 93c949f35e5ca0ef55a7347b0682b778afe18d29 Mon Sep 17 00:00:00 2001 From: ChefMist <133624774+ChefMist@users.noreply.github.com> Date: Tue, 5 Nov 2024 14:43:24 +0800 Subject: [PATCH] feat: include more detail to make it concrete --- src/Vault.sol | 3 -- src/pool-bin/BinPoolManager.sol | 5 ++ .../BinReturnsDeltaOverwriteSwap.t.sol | 54 +++++++++++++++++-- .../BinReturnsDeltaHookOverwriteSwap.sol | 33 +++++++++++- 4 files changed, 86 insertions(+), 9 deletions(-) diff --git a/src/Vault.sol b/src/Vault.sol index 475431b..2c9a0d2 100644 --- a/src/Vault.sol +++ b/src/Vault.sol @@ -175,9 +175,6 @@ contract Vault is IVault, VaultToken, Ownable { /// @dev optimization: msg.sender will always be app address, verification should be done on caller address if (delta >= 0) { - console2.log("before deduct from reservesOfApp"); - console2.log("reservesOfApp[msg.sender][currency]", reservesOfApp[msg.sender][currency]); - console2.log("delta", uint128(delta)); /// @dev arithmetic underflow make sure trader can't withdraw too much from app reservesOfApp[msg.sender][currency] -= uint128(delta); } else { diff --git a/src/pool-bin/BinPoolManager.sol b/src/pool-bin/BinPoolManager.sol index 31b8fe4..eadfb38 100644 --- a/src/pool-bin/BinPoolManager.sol +++ b/src/pool-bin/BinPoolManager.sol @@ -24,6 +24,8 @@ import {BeforeSwapDelta} from "../types/BeforeSwapDelta.sol"; import "./interfaces/IBinHooks.sol"; import {BinSlot0} from "./types/BinSlot0.sol"; +import {console2} from "forge-std/console2.sol"; + /// @notice Holds the state for all bin pools contract BinPoolManager is IBinPoolManager, ProtocolFees, Extsload { using BinPool for *; @@ -193,10 +195,13 @@ contract BinPoolManager is IBinPoolManager, ProtocolFees, Extsload { int128 delta0 = delta.amount0(); int128 delta1 = delta.amount1(); + // positive deduct reservesOfApp if (delta0 < 0) { + /// @dev account for delta0 first so reserveOfApp will be positive, then deduct hookDelta if required vault.accountAppBalanceDelta(key.currency0, delta0, msg.sender); if (hookDelta0 != 0) vault.accountAppBalanceDelta(key.currency0, hookDelta0, address(key.hooks)); } else { + /// @dev account for hookDelta0 first if (hookDelta0 != 0) vault.accountAppBalanceDelta(key.currency0, hookDelta0, address(key.hooks)); if (delta0 != 0) vault.accountAppBalanceDelta(key.currency0, delta0, msg.sender); } diff --git a/test/pool-bin/BinReturnsDeltaOverwriteSwap.t.sol b/test/pool-bin/BinReturnsDeltaOverwriteSwap.t.sol index 054fa48..78928fa 100644 --- a/test/pool-bin/BinReturnsDeltaOverwriteSwap.t.sol +++ b/test/pool-bin/BinReturnsDeltaOverwriteSwap.t.sol @@ -25,6 +25,7 @@ import {BinLiquidityHelper} from "./helpers/BinLiquidityHelper.sol"; import {BinTestHelper} from "./helpers/BinTestHelper.sol"; import {Hooks} from "../../src/libraries/Hooks.sol"; import {BinReturnsDeltaHookOverwriteSwap} from "./helpers/BinReturnsDeltaHookOverwriteSwap.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; contract BinReturnsDeltaOverwriteSwap is Test, GasSnapshot, BinTestHelper { using SafeCast for uint256; @@ -86,19 +87,64 @@ contract BinReturnsDeltaOverwriteSwap is Test, GasSnapshot, BinTestHelper { parameters: bytes32(uint256(binReturnsDeltaHookOverwriteSwap.getHooksRegistrationBitmap())).setBinStep(10) }); + binReturnsDeltaHookOverwriteSwap.setPoolKey(key); + poolManager.initialize(key, activeId); } function testSwap_xx() external { // assume liquidity added via hook and sent to the vault - token0.mint(address(vault), 100 ether); - token1.mint(address(vault), 100 ether); + // token0.mint(address(vault), 100 ether); + // token1.mint(address(vault), 100 ether); // assume hook has some liqudiity from earlier add liqudiity - token0.mint(address(binReturnsDeltaHookOverwriteSwap), 100 ether); - token1.mint(address(binReturnsDeltaHookOverwriteSwap), 100 ether); + // token0.mint(address(binReturnsDeltaHookOverwriteSwap), 100 ether); + // token1.mint(address(binReturnsDeltaHookOverwriteSwap), 100 ether); + + address hAddr = address(binReturnsDeltaHookOverwriteSwap); + + token0.mint(address(this), 10 ether); + token1.mint(address(this), 10 ether); + + console2.log("---------start of testSwap_xx add liquidity----------------------"); + console2.log(" balanceof user t0: ", IERC20(Currency.unwrap(currency0)).balanceOf(address(this)) / 1 ether); + console2.log(" balanceof user t1: ", IERC20(Currency.unwrap(currency1)).balanceOf(address(this)) / 1 ether); + console2.log(" balanceof user hAddr: ", IERC20(Currency.unwrap(currency0)).balanceOf(address(hAddr)) / 1 ether); + console2.log(" balanceof user hAddr: ", IERC20(Currency.unwrap(currency1)).balanceOf(address(hAddr)) / 1 ether); + console2.log(" balanceof user vault: ", IERC20(Currency.unwrap(currency0)).balanceOf(address(vault)) / 1 ether); + console2.log(" balanceof user vault: ", IERC20(Currency.unwrap(currency1)).balanceOf(address(vault)) / 1 ether); + console2.log("-------------------------------"); + + binReturnsDeltaHookOverwriteSwap.addLiquidity(1 ether, 1 ether); + + console2.log("---------end of testSwap_xx add liquidity ----------------------"); + console2.log(" balanceof user t0: ", IERC20(Currency.unwrap(currency0)).balanceOf(address(this)) / 1 ether); + console2.log(" balanceof user t1: ", IERC20(Currency.unwrap(currency1)).balanceOf(address(this)) / 1 ether); + console2.log(" balanceof user hAddr: ", IERC20(Currency.unwrap(currency0)).balanceOf(address(hAddr)) / 1 ether); + console2.log(" balanceof user hAddr: ", IERC20(Currency.unwrap(currency1)).balanceOf(address(hAddr)) / 1 ether); + console2.log(" balanceof user vault: ", IERC20(Currency.unwrap(currency0)).balanceOf(address(vault)) / 1 ether); + console2.log(" balanceof user vault: ", IERC20(Currency.unwrap(currency1)).balanceOf(address(vault)) / 1 ether); + console2.log("-------------------------------"); + + console2.log("---------start of testSwap_xx swap----------------------"); + console2.log(" reserveOfApp t0 (ethers)", vault.reservesOfApp(address(poolManager), key.currency0) / 1 ether); + console2.log(" reserveOfApp t1 (ethers)", vault.reservesOfApp(address(poolManager), key.currency1) / 1 ether); + console2.log(" balanceof user t0: ", IERC20(Currency.unwrap(currency0)).balanceOf(address(this)) / 1 ether); + console2.log(" balanceof user t1: ", IERC20(Currency.unwrap(currency1)).balanceOf(address(this)) / 1 ether); + console2.log(" balanceof user hAddr: ", IERC20(Currency.unwrap(currency0)).balanceOf(address(hAddr)) / 1 ether); + console2.log(" balanceof user hAddr: ", IERC20(Currency.unwrap(currency1)).balanceOf(address(hAddr)) / 1 ether); + console2.log("-------------------------------"); BalanceDelta delta = binSwapHelper.swap(key, true, -int128(1 ether), BinSwapHelper.TestSettings(true, true), ""); + + console2.log("---------end of testSwap_xx swap----------------------"); + console2.log(" reserveOfApp t0 (ethers)", vault.reservesOfApp(address(poolManager), key.currency0) / 1 ether); + console2.log(" reserveOfApp t1 (ethers)", vault.reservesOfApp(address(poolManager), key.currency1) / 1 ether); + console2.log(" balanceof user t0: ", IERC20(Currency.unwrap(currency0)).balanceOf(address(this)) / 1 ether); + console2.log(" balanceof user t1: ", IERC20(Currency.unwrap(currency1)).balanceOf(address(this)) / 1 ether); + console2.log(" balanceof user hAddr: ", IERC20(Currency.unwrap(currency0)).balanceOf(address(hAddr)) / 1 ether); + console2.log(" balanceof user hAddr: ", IERC20(Currency.unwrap(currency1)).balanceOf(address(hAddr)) / 1 ether); + console2.log("-------------------------------"); } function testFuzz_Swap_xx(bool swapForY, uint256 swapAmount, bool exactInput) external { diff --git a/test/pool-bin/helpers/BinReturnsDeltaHookOverwriteSwap.sol b/test/pool-bin/helpers/BinReturnsDeltaHookOverwriteSwap.sol index da31546..8542834 100644 --- a/test/pool-bin/helpers/BinReturnsDeltaHookOverwriteSwap.sol +++ b/test/pool-bin/helpers/BinReturnsDeltaHookOverwriteSwap.sol @@ -11,6 +11,9 @@ import {toBalanceDelta, BalanceDelta, BalanceDeltaLibrary} from "../../../src/ty import {BeforeSwapDelta, toBeforeSwapDelta} from "../../../src/types/BeforeSwapDelta.sol"; import {BaseBinTestHook} from "./BaseBinTestHook.sol"; import {CurrencySettlement} from "../../helpers/CurrencySettlement.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +import {console2} from "forge-std/console2.sol"; contract BinReturnsDeltaHookOverwriteSwap is BaseBinTestHook { error InvalidAction(); @@ -20,12 +23,17 @@ contract BinReturnsDeltaHookOverwriteSwap is BaseBinTestHook { IVault public immutable vault; IBinPoolManager public immutable poolManager; + PoolKey key; constructor(IVault _vault, IBinPoolManager _poolManager) { vault = _vault; poolManager = _poolManager; } + function setPoolKey(PoolKey memory _poolKey) external { + key = _poolKey; + } + function getHooksRegistrationBitmap() external pure override returns (uint16) { return _hooksRegistrationBitmapFrom( Permissions({ @@ -47,6 +55,27 @@ contract BinReturnsDeltaHookOverwriteSwap is BaseBinTestHook { ); } + function addLiquidity(uint256 amt0, uint256 amt1) public { + // do any logic + + // 1. Take input currency and amount from user + IERC20(Currency.unwrap(key.currency0)).transferFrom(msg.sender, address(this), amt0); + IERC20(Currency.unwrap(key.currency1)).transferFrom(msg.sender, address(this), amt1); + + // 2. Mint -- so vault has token balance + vault.lock(abi.encode(amt0, amt1)); + } + + function lockAcquired(bytes calldata callbackData) external returns (bytes memory) { + (uint256 amt0, uint256 amt1) = abi.decode(callbackData, (uint256, uint256)); + + vault.mint(address(this), key.currency0, amt0); + key.currency0.settle(vault, address(this), amt0, false); + + vault.mint(address(this), key.currency1, amt1); + key.currency1.settle(vault, address(this), amt1, false); + } + function beforeSwap(address, PoolKey calldata key, bool swapForY, int128 amountSpecified, bytes calldata data) external override @@ -56,10 +85,10 @@ contract BinReturnsDeltaHookOverwriteSwap is BaseBinTestHook { _getInputOutputAndAmount(key, swapForY, amountSpecified); // 1. Take input currency and amount - inputCurrency.take(vault, address(this), amount, false); + inputCurrency.take(vault, address(this), amount, true); // 2. Give output currency and amount achieving a 1:1 swap - outputCurrency.settle(vault, address(this), amount, false); + outputCurrency.settle(vault, address(this), amount, true); BeforeSwapDelta hookDelta = toBeforeSwapDelta(-amountSpecified, amountSpecified); return (this.beforeSwap.selector, hookDelta, 0);