Skip to content

Commit

Permalink
minor fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Ericselvig committed Dec 7, 2024
1 parent 401fa0e commit 455bd30
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 58 deletions.
66 changes: 28 additions & 38 deletions src/JITHook.sol
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ contract JITHook is BaseHook, Owned {
uint256 public currentActiveStrategyId;

// mapping(PoolKey => GovToken) public govTokens;
GovToken public govToken;
GovToken public immutable govToken;

constructor(
IPoolManager _manager,
Expand Down Expand Up @@ -83,7 +83,7 @@ contract JITHook is BaseHook, Owned {
return
Hooks.Permissions({
beforeInitialize: false,
afterInitialize: true,
afterInitialize: false,
beforeAddLiquidity: false,
afterAddLiquidity: false,
beforeRemoveLiquidity: false,
Expand Down Expand Up @@ -144,7 +144,7 @@ contract JITHook is BaseHook, Owned {
);
}

// Converting swap amount into USD as well to compare
// Provide JIT liquidity only if swap amount exceeds the threshold
if (_getSwapAmount(key, params) >= swapThreshold) {
// withdraw funds from external swap before adding to the pool and
// check if internal swap is required before adding liquidity
Expand Down Expand Up @@ -179,8 +179,7 @@ contract JITHook is BaseHook, Owned {
// 1. remove liquidity from pool
// 2. add liquidity to external protocol

// TODO are 0, 0 ok?
_removeLiquidityFromPool(0, 0);
_removeLiquidityFromPool();
_depositToStrategy(
currentActiveStrategyId,
key.currency0,
Expand All @@ -198,11 +197,7 @@ contract JITHook is BaseHook, Owned {

// smaller LPs will call this function, funds added to external protocol
// note the user must deposit the pair of funds to the hook with the same ratio as the pool, otherwise it will not be accepted
function deposit(
Currency currency,
uint256 amount
) external {

function deposit(Currency currency, uint256 amount) external {
ERC20(Currency.unwrap(currency)).transferFrom(
msg.sender,
address(this),
Expand All @@ -211,23 +206,23 @@ contract JITHook is BaseHook, Owned {

// TODO instead of minting amounts directly, calculate the total USD value and mint that
if (amount > 0) {
(, int256 price, , ,) = priceFeeds[currency].latestRoundData();
(, int256 price, , , ) = priceFeeds[currency].latestRoundData();
uint256 usdValue = (uint256(price) * amount) / 1e8;

// deposit to strategy (currency => amount)
_depositToStrategy(currentActiveStrategyId, currency, amount);
// mint gove Token => usdValue
// mint gove Token => usdValue
govToken.mint(msg.sender, usdValue);
}

// todo emit event
}

// funds transferred to small LPs from external protocol
// TODO
// TODO
// key: currency0, currency1 => not deposited in external protocol because no one deposited it ?????
// without key, what tokens will returned ?
function withdraw(PoolKey calldata key) external {
// without key, what tokens will returned ?
function withdraw() external {
// TODO (later) amount specific withdrawl
// TODO give tokens on basis of staked tokens ratio
// Ex: staked $1000 USDC and $1000 ETH so give 50-50
Expand All @@ -245,14 +240,8 @@ contract JITHook is BaseHook, Owned {
_withdrawFromStrategy(currentActiveStrategyId, key.currency0, amount0);
_withdrawFromStrategy(currentActiveStrategyId, key.currency1, amount1);

ERC20(Currency.unwrap(key.currency0)).transfer(
msg.sender,
amount0
);
ERC20(Currency.unwrap(key.currency1)).transfer(
msg.sender,
amount1
);
ERC20(Currency.unwrap(key.currency0)).transfer(msg.sender, amount0);
ERC20(Currency.unwrap(key.currency1)).transfer(msg.sender, amount1);

// todo calculate token amount for the user, and transfer to user
// todo multiple user wil store funds here, when one user call this only his liquidty should be removed and transferred to user NOT ALL
Expand Down Expand Up @@ -347,14 +336,11 @@ contract JITHook is BaseHook, Owned {
/**
* @dev burns this contract's LP position, used in afterSwap hook
*/
function _removeLiquidityFromPool(
uint128 amount0Min,
uint128 amount1Min
) internal {
function _removeLiquidityFromPool() internal {
// decrease liquidity + take pair (transfer fee revenue) ? OR directly burn position
bytes memory actions = abi.encodePacked(Actions.BURN_POSITION);
bytes[] memory params = new bytes[](1);
params[0] = abi.encode(currentPositionId, amount0Min, amount1Min, "");
params[0] = abi.encode(currentPositionId, 0, 0, "");
delete currentPositionId;

positionManager.modifyLiquiditiesWithoutUnlock(actions, params);
Expand Down Expand Up @@ -410,8 +396,7 @@ contract JITHook is BaseHook, Owned {
uint256 token1Balance
) = _getBalanceFromStrategy(currentActiveStrategyId, key);


// not withdrawing the entire balance,
// not withdrawing the entire balance,
// because in future we will allow user to withdraw some specific amount of funds [right now it is complete balance]
_withdrawFromStrategy(
currentActiveStrategyId,
Expand All @@ -423,12 +408,14 @@ contract JITHook is BaseHook, Owned {
key.currency1,
token1Balance
);
// current price ratio
// current price ratio
(, int24 tick, , ) = StateLibrary.getSlot0(poolManager, key.toId());
uint160 sqrtPriceX96 = TickMath.getSqrtPriceAtTick(tick);

// P = y/x
uint256 currentPrice = (uint256(sqrtPriceX96) * uint256(sqrtPriceX96) * 1e18) >> 192;
// P = y/x
uint256 currentPrice = (uint256(sqrtPriceX96) *
uint256(sqrtPriceX96) *
1e18) >> 192;

// x token A, y token B
// x -> y
Expand All @@ -443,7 +430,8 @@ contract JITHook is BaseHook, Owned {

if (ourRatio > 1e18) {
// We have too much token0 relative to token1
uint256 excessAmount0 = token0Balance - ((token1Balance * 1e18) / currentPrice);
uint256 excessAmount0 = token0Balance -
((token1Balance * 1e18) / currentPrice);
poolManager.swap(
key,
IPoolManager.SwapParams({
Expand All @@ -455,7 +443,8 @@ contract JITHook is BaseHook, Owned {
);
} else if (ourRatio < 1e18) {
// We have too much token1 relative to token0
uint256 excessAmount1 = token1Balance - ((token0Balance * currentPrice) / 1e18);
uint256 excessAmount1 = token1Balance -
((token0Balance * currentPrice) / 1e18);
poolManager.swap(
key,
IPoolManager.SwapParams({
Expand All @@ -466,9 +455,10 @@ contract JITHook is BaseHook, Owned {
""
);
}
uint256 newToken0Balance = ERC20(Currency.unwrap(key.currency0)).balanceOf(address(this));
uint256 newToken1Balance = ERC20(Currency.unwrap(key.currency1)).balanceOf(address(this));
uint256 newToken0Balance = ERC20(Currency.unwrap(key.currency0))
.balanceOf(address(this));
uint256 newToken1Balance = ERC20(Currency.unwrap(key.currency1))
.balanceOf(address(this));
return (newToken0Balance, newToken1Balance);

}
}
82 changes: 62 additions & 20 deletions test/JITHook.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,16 @@ pragma solidity ^0.8.26;

import {Test} from "forge-std/Test.sol";

import {Deployers} from "@uniswap/v4-core/test/utils/Deployers.sol";
import {Deployers} from "v4-core/test/utils/Deployers.sol";
import {MockERC20} from "solmate/src/test/utils/mocks/MockERC20.sol";
import {WETH} from "solmate/src/tokens/WETH.sol";
import {DeployPermit2} from "permit2/test/utils/DeployPermit2.sol";
import {PositionDescriptor} from "v4-periphery/src/PositionDescriptor.sol";
import {PositionManager} from "v4-periphery/src/PositionManager.sol";
import {IAllowanceTransfer} from "permit2/src/interfaces/IAllowanceTransfer.sol";

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IWETH9} from "v4-periphery/src/interfaces/external/IWETH9.sol";

import {PoolManager} from "v4-core/src/PoolManager.sol";
import {IPoolManager} from "v4-core/src/interfaces/IPoolManager.sol";
Expand All @@ -20,30 +26,45 @@ import {Hooks} from "v4-core/src/libraries/Hooks.sol";
import {TickMath} from "v4-core/src/libraries/TickMath.sol";

import {JITHook} from "../src/JITHook.sol";
import {StrategiesController} from "../src/StrategiesController.sol";

// add mock pricefeed contract


contract JITHookTest is Test, Deployers {
// add mock pricefeed contract

contract JITHookTest is Test, Deployers, DeployPermit2 {
using StateLibrary for IPoolManager;
using PoolIdLibrary for PoolKey;
using CurrencyLibrary for Currency;

IWETH9 public _WETH9 = IWETH9(address(new WETH()));

Currency public token0;
Currency public token1;
JITHook public hook;
PositionManager posm;
// MockPriceFeed priceFeed0;
// MockPriceFeed priceFeed1;

uint256 constant THRESHOLD = 1e6 * 1e8;

function setUp() public {

StrategiesController controller = new StrategiesController();

deployFreshManagerAndRouters();
deployPosm();

(token0, token1) = deployAndMint2Currencies();
//(token0, token1) = deployAndMint2Currencies();
uint160 flags = uint160(Hooks.BEFORE_SWAP_FLAG | Hooks.AFTER_SWAP_FLAG);
address hookAddress = address(flags);
deployCodeTo("JITHook.sol", abi.encode(), hookAddress);
deployCodeTo(
"JITHook.sol",
abi.encode(
address(manager),
address(controller),
THRESHOLD,
address(posm)
),
hookAddress
);
hook = JITHook(hookAddress);

MockERC20(Currency.unwrap(token0)).approve(
Expand All @@ -62,29 +83,50 @@ contract JITHookTest is Test, Deployers {

// Initialize a pool with these two tokens
(key, ) = initPool(token0, token1, hook, 3000, SQRT_PRICE_1_1);

}

function test_deposit() public {
function deployPosm() internal {
IAllowanceTransfer permit2 = IAllowanceTransfer(deployPermit2());
PositionDescriptor positionDescriptor = new PositionDescriptor(
manager,
0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2,
"ETH"
);
posm = new PositionManager(
manager,
permit2,
100_000,
positionDescriptor,
_WETH9
);
}

function test_deposit() public {
uint256 depositAmount = 1e8;
uint256 initialUserBalance = MockERC20(Currency.unwrap(token0)).balanceOf(address(this));
uint256 initialHookBalance = MockERC20(Currency.unwrap(token0)).balanceOf(address(hook));
uint256 initialUserBalance = MockERC20(Currency.unwrap(token0))
.balanceOf(address(this));
uint256 initialHookBalance = MockERC20(Currency.unwrap(token0))
.balanceOf(address(hook));
// deposit
hook.deposit(token0, depositAmount);

// Get final balances
uint256 finalUserBalance = MockERC20(Currency.unwrap(token0)).balanceOf(address(this));
uint256 finalHookBalance = MockERC20(Currency.unwrap(token0)).balanceOf(address(hook));

uint256 finalUserBalance = MockERC20(Currency.unwrap(token0)).balanceOf(
address(this)
);
uint256 finalHookBalance = MockERC20(Currency.unwrap(token0)).balanceOf(
address(hook)
);

// Check token transfer
assertEq(finalUserBalance, initialUserBalance - depositAmount);
assertEq(finalHookBalance, initialHookBalance + depositAmount);

// use mock pricefeed for amount of govTokens
uint256 expectedGovTokens;
assertEq(hook.govToken().balanceOf(address(this)), expectedGovTokens);

assertEq(
hook.govToken().balanceOf(address(this)),
expectedGovTokens
);
}

}

0 comments on commit 455bd30

Please sign in to comment.