diff --git a/src/TWAMM.sol b/src/TWAMM.sol index 97fd73d..808b59f 100644 --- a/src/TWAMM.sol +++ b/src/TWAMM.sol @@ -84,6 +84,7 @@ contract TWAMM is BaseHook, ITWAMM { }); } + // since we are initializing the hook this will be the first TWAMM in the hook function beforeInitialize(address, PoolKey calldata key, uint160, bytes calldata) external virtual @@ -96,6 +97,7 @@ contract TWAMM is BaseHook, ITWAMM { return BaseHook.beforeInitialize.selector; } + // TWAMM order are filled function beforeAddLiquidity( address, PoolKey calldata key, @@ -106,6 +108,7 @@ contract TWAMM is BaseHook, ITWAMM { return BaseHook.beforeAddLiquidity.selector; } + // TWAMM order are filled function beforeSwap(address, PoolKey calldata key, IPoolManager.SwapParams calldata, bytes calldata) external override @@ -116,14 +119,17 @@ contract TWAMM is BaseHook, ITWAMM { return (BaseHook.beforeSwap.selector, BeforeSwapDeltaLibrary.ZERO_DELTA, 0); } + // Virtual order are pending sub_orders that are waiting to be swapped function lastVirtualOrderTimestamp(PoolId key) external view returns (uint256) { return twammStates[key].lastVirtualOrderTimestamp; } + // The pool key holds the pool parms, and the order key holds the parms of the TWAMM order function getOrder(PoolKey calldata poolKey, OrderKey calldata orderKey) external view returns (Order memory) { return _getOrder(twammStates[PoolId.wrap(keccak256(abi.encode(poolKey)))], orderKey); } + // This is the pool in which the TWAMM will be effective on function getOrderPool(PoolKey calldata key, bool zeroForOne) external view @@ -141,6 +147,8 @@ contract TWAMM is BaseHook, ITWAMM { } /// @inheritdoc ITWAMM + // The executions of the TWAMM on the pool + // @note The pool key must hold the info of the swaps function executeTWAMMOrders(PoolKey memory key) public { PoolId poolId = key.toId(); (uint160 sqrtPriceX96,,,) = poolManager.getSlot0(poolId); @@ -158,6 +166,7 @@ contract TWAMM is BaseHook, ITWAMM { } /// @inheritdoc ITWAMM + // function submitOrder(PoolKey calldata key, OrderKey memory orderKey, uint256 amountIn) external returns (bytes32 orderId) diff --git a/src/TWAMMFactory.sol b/src/TWAMMFactory.sol new file mode 100644 index 0000000..77c439a --- /dev/null +++ b/src/TWAMMFactory.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.15; + +import {TWAMM} from "./TWAMM.sol"; +import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol"; +import {PoolManager} from "@uniswap/v4-core/src/PoolManager.sol"; + +contract TWAMMFactory { + PoolManager public immutable poolManager; + uint256 public immutable orderTimeInterval; + + event TWAMMDeployed(address twammAddress); + + constructor(PoolManager _poolManager, uint256 _orderTimeInterval) { + poolManager = _poolManager; + orderTimeInterval = _orderTimeInterval; + } + + function deployTWAMM() public returns (address) { + TWAMM newTWAMM = new TWAMM( + address(poolManager), + orderTimeInterval, + address(uint160(Hooks.BEFORE_INITIALIZE_FLAG | Hooks.BEFORE_SWAP_FLAG | Hooks.BEFORE_ADD_LIQUIDITY_FLAG)) + ); + + emit TWAMMDeployed(address(newTWAMM)); + return address(newTWAMM); + } +} \ No newline at end of file diff --git a/test/TWAMMFactory.t.sol b/test/TWAMMFactory.t.sol new file mode 100644 index 0000000..99c46f2 --- /dev/null +++ b/test/TWAMMFactory.t.sol @@ -0,0 +1,55 @@ +pragma solidity ^0.8.15; + +import {Test} from "forge-std/Test.sol"; +import {PoolManager} from "@uniswap/v4-core/src/PoolManager.sol"; +import {TWAMMFactory} from "../src/TWAMMFactory.sol"; +import {TWAMM} from "../src/TWAMM.sol"; +import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol"; + +contract TWAMMFactoryTest is Test { + PoolManager public poolManager; + TWAMMFactory public factory; + uint256 constant ORDER_TIME_INTERVAL = 10_000; + + event TWAMMDeployed(address twammAddress); + + function setUp() public { + // Deploy a mock PoolManager + poolManager = new PoolManager(500000); + + // Deploy the TWAMMFactory + factory = new TWAMMFactory(poolManager, ORDER_TIME_INTERVAL); + } + + function testFactoryDeployment() public { + assertEq(address(factory.poolManager()), address(poolManager)); + assertEq(factory.orderTimeInterval(), ORDER_TIME_INTERVAL); + } + + function testDeployTWAMM() public { + vm.expectEmit(true, true, true, true); + emit TWAMMDeployed(address(0)); // We don't know the exact address, so we use a placeholder + + address twammAddress = factory.deployTWAMM(); + + assertTrue(twammAddress != address(0)); + TWAMM twamm = TWAMM(twammAddress); + + // Verify that the TWAMM contract was deployed with the correct parameters + assertEq(address(twamm.poolManager()), address(poolManager)); + assertEq(twamm.ORDER_TIME_INTERVAL(), ORDER_TIME_INTERVAL); + + // Verify that the TWAMM contract has the correct hooks enabled + uint160 expectedFlags = uint160(Hooks.BEFORE_INITIALIZE_FLAG | Hooks.BEFORE_SWAP_FLAG | Hooks.BEFORE_ADD_LIQUIDITY_FLAG); + assertEq(uint160(twammAddress), expectedFlags); + } + + function testMultipleDeployments() public { + address twamm1 = factory.deployTWAMM(); + address twamm2 = factory.deployTWAMM(); + + assertTrue(twamm1 != twamm2); + assertTrue(twamm1 != address(0)); + assertTrue(twamm2 != address(0)); + } +} \ No newline at end of file