diff --git a/foundry/src/TychoRouter.sol b/foundry/src/TychoRouter.sol index 955cd7d..e6c798b 100644 --- a/foundry/src/TychoRouter.sol +++ b/foundry/src/TychoRouter.sol @@ -76,8 +76,6 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard { //keccak256("NAME_OF_ROLE") : save gas on deployment bytes32 public constant EXECUTOR_SETTER_ROLE = 0x6a1dd52dcad5bd732e45b6af4e7344fa284e2d7d4b23b5b09cb55d36b0685c87; - bytes32 public constant FEE_SETTER_ROLE = - 0xe6ad9a47fbda1dc18de1eb5eeb7d935e5e81b4748f3cfc61e233e64f88182060; bytes32 public constant PAUSER_ROLE = 0x65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a; bytes32 public constant UNPAUSER_ROLE = @@ -85,19 +83,9 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard { bytes32 public constant FUND_RESCUER_ROLE = 0x912e45d663a6f4cc1d0491d8f046e06c616f40352565ea1cdb86a0e1aaefa41b; - address public feeReceiver; - - // Fee should be expressed in basis points (1/100th of a percent) - // For example, 100 = 1%, 500 = 5%, 1000 = 10% - uint256 public fee; - event Withdrawal( address indexed token, uint256 amount, address indexed receiver ); - event FeeReceiverSet( - address indexed oldFeeReceiver, address indexed newFeeReceiver - ); - event FeeSet(uint256 indexed oldFee, uint256 indexed newFee); constructor(address _permit2, address weth) { if (_permit2 == address(0) || weth == address(0)) { @@ -117,7 +105,6 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard { * - If `wrapEth` is true, the contract wraps the provided native ETH into WETH and uses it as the sell token. * - If `unwrapEth` is true, the contract converts the resulting WETH back into native ETH before sending it to the receiver. * - Swaps are executed sequentially using the `_swap` function. - * - A fee is deducted from the output token if `fee > 0`, and the remaining amount is sent to the receiver. * - Reverts with `TychoRouter__NegativeSlippage` if the output amount is less than `minAmountOut` and `minAmountOut` is greater than 0. * * @param amountIn The input token amount to be swapped. @@ -130,7 +117,7 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard { * @param receiver The address to receive the output tokens. * @param swaps Encoded swap graph data containing details of each swap. * - * @return amountOut The total amount of the output token received by the receiver, after deducting fees if applicable. + * @return amountOut The total amount of the output token received by the receiver. */ function splitSwap( uint256 amountIn, @@ -171,7 +158,6 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard { * - If `unwrapEth` is true, the contract converts the resulting WETH back into native ETH before sending it to the receiver. * - For ERC20 tokens, Permit2 is used to approve and transfer tokens from the caller to the router. * - Swaps are executed sequentially using the `_swap` function. - * - A fee is deducted from the output token if `fee > 0`, and the remaining amount is sent to the receiver. * - Reverts with `TychoRouter__NegativeSlippage` if the output amount is less than `minAmountOut` and `minAmountOut` is greater than 0. * * @param amountIn The input token amount to be swapped. @@ -186,7 +172,7 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard { * @param signature A valid signature authorizing the Permit2 approval. Ignored if `wrapEth` is true. * @param swaps Encoded swap graph data containing details of each swap. * - * @return amountOut The total amount of the output token received by the receiver, after deducting fees if applicable. + * @return amountOut The total amount of the output token received by the receiver. */ function splitSwapPermit2( uint256 amountIn, @@ -234,7 +220,6 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard { * - If `wrapEth` is true, the contract wraps the provided native ETH into WETH and uses it as the sell token. * - If `unwrapEth` is true, the contract converts the resulting WETH back into native ETH before sending it to the receiver. * - Swaps are executed sequentially using the `_swap` function. - * - A fee is deducted from the output token if `fee > 0`, and the remaining amount is sent to the receiver. * - Reverts with `TychoRouter__NegativeSlippage` if the output amount is less than `minAmountOut` and `minAmountOut` is greater than 0. * * @param amountIn The input token amount to be swapped. @@ -246,7 +231,7 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard { * @param receiver The address to receive the output tokens. * @param swaps Encoded swap graph data containing details of each swap. * - * @return amountOut The total amount of the output token received by the receiver, after deducting fees if applicable. + * @return amountOut The total amount of the output token received by the receiver. */ function sequentialSwap( uint256 amountIn, @@ -280,7 +265,6 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard { * - If `wrapEth` is true, the contract wraps the provided native ETH into WETH and uses it as the sell token. * - If `unwrapEth` is true, the contract converts the resulting WETH back into native ETH before sending it to the receiver. * - For ERC20 tokens, Permit2 is used to approve and transfer tokens from the caller to the router. - * - A fee is deducted from the output token if `fee > 0`, and the remaining amount is sent to the receiver. * - Reverts with `TychoRouter__NegativeSlippage` if the output amount is less than `minAmountOut` and `minAmountOut` is greater than 0. * * @param amountIn The input token amount to be swapped. @@ -294,7 +278,7 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard { * @param signature A valid signature authorizing the Permit2 approval. Ignored if `wrapEth` is true. * @param swaps Encoded swap graph data containing details of each swap. * - * @return amountOut The total amount of the output token received by the receiver, after deducting fees if applicable. + * @return amountOut The total amount of the output token received by the receiver. */ function sequentialSwapPermit2( uint256 amountIn, @@ -339,7 +323,6 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard { * @dev * - If `wrapEth` is true, the contract wraps the provided native ETH into WETH and uses it as the sell token. * - If `unwrapEth` is true, the contract converts the resulting WETH back into native ETH before sending it to the receiver. - * - A fee is deducted from the output token if `fee > 0`, and the remaining amount is sent to the receiver. * - Reverts with `TychoRouter__NegativeSlippage` if the output amount is less than `minAmountOut` and `minAmountOut` is greater than 0. * * @param amountIn The input token amount to be swapped. @@ -351,7 +334,7 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard { * @param receiver The address to receive the output tokens. * @param swapData Encoded swap details. * - * @return amountOut The total amount of the output token received by the receiver, after deducting fees if applicable. + * @return amountOut The total amount of the output token received by the receiver. */ function singleSwap( uint256 amountIn, @@ -385,7 +368,6 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard { * - If `wrapEth` is true, the contract wraps the provided native ETH into WETH and uses it as the sell token. * - If `unwrapEth` is true, the contract converts the resulting WETH back into native ETH before sending it to the receiver. * - For ERC20 tokens, Permit2 is used to approve and transfer tokens from the caller to the router. - * - A fee is deducted from the output token if `fee > 0`, and the remaining amount is sent to the receiver. * - Reverts with `TychoRouter__NegativeSlippage` if the output amount is less than `minAmountOut` and `minAmountOut` is greater than 0. * * @param amountIn The input token amount to be swapped. @@ -399,7 +381,7 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard { * @param signature A valid signature authorizing the Permit2 approval. Ignored if `wrapEth` is true. * @param swapData Encoded swap details. * - * @return amountOut The total amount of the output token received by the receiver, after deducting fees if applicable. + * @return amountOut The total amount of the output token received by the receiver. */ function singleSwapPermit2( uint256 amountIn, @@ -485,12 +467,6 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard { ); } - if (fee > 0) { - uint256 feeAmount = (amountOut * fee) / 10000; - amountOut -= feeAmount; - IERC20(tokenOut).safeTransfer(feeReceiver, feeAmount); - } - if (amountOut < minAmountOut) { revert TychoRouter__NegativeSlippage(amountOut, minAmountOut); } @@ -556,12 +532,6 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard { ); } - if (fee > 0) { - uint256 feeAmount = (amountOut * fee) / 10000; - amountOut -= feeAmount; - IERC20(tokenOut).safeTransfer(feeReceiver, feeAmount); - } - if (amountOut < minAmountOut) { revert TychoRouter__NegativeSlippage(amountOut, minAmountOut); } @@ -625,12 +595,6 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard { ); } - if (fee > 0) { - uint256 feeAmount = (amountOut * fee) / 10000; - amountOut -= feeAmount; - IERC20(tokenOut).safeTransfer(feeReceiver, feeAmount); - } - if (amountOut < minAmountOut) { revert TychoRouter__NegativeSlippage(amountOut, minAmountOut); } @@ -803,26 +767,6 @@ contract TychoRouter is AccessControl, Dispatcher, Pausable, ReentrancyGuard { _removeExecutor(target); } - /** - * @dev Allows setting the fee receiver. - */ - function setFeeReceiver(address newfeeReceiver) - external - onlyRole(FEE_SETTER_ROLE) - { - if (newfeeReceiver == address(0)) revert TychoRouter__AddressZero(); - emit FeeReceiverSet(feeReceiver, newfeeReceiver); - feeReceiver = newfeeReceiver; - } - - /** - * @dev Allows setting the fee. - */ - function setFee(uint256 newFee) external onlyRole(FEE_SETTER_ROLE) { - emit FeeSet(fee, newFee); - fee = newFee; - } - /** * @dev Allows withdrawing any ERC20 funds if funds get stuck in case of a bug. */ diff --git a/foundry/test/Constants.sol b/foundry/test/Constants.sol index 9b0f488..c8e80a4 100644 --- a/foundry/test/Constants.sol +++ b/foundry/test/Constants.sol @@ -15,8 +15,6 @@ contract Constants is Test, BaseConstants { address ADMIN = makeAddr("admin"); //admin=us address BOB = makeAddr("bob"); //bob=someone!=us address FUND_RESCUER = makeAddr("fundRescuer"); - address FEE_SETTER = makeAddr("feeSetter"); - address FEE_RECEIVER = makeAddr("feeReceiver"); address EXECUTOR_SETTER = makeAddr("executorSetter"); address ALICE = 0xcd09f75E2BF2A4d11F3AB23f1389FcC1621c0cc2; uint256 ALICE_PK = diff --git a/foundry/test/TychoRouter.t.sol b/foundry/test/TychoRouter.t.sol index 4a79e5c..e85ad3d 100644 --- a/foundry/test/TychoRouter.t.sol +++ b/foundry/test/TychoRouter.t.sol @@ -10,8 +10,6 @@ import {SafeCallback} from "@uniswap/v4-periphery/src/base/SafeCallback.sol"; contract TychoRouterTest is TychoRouterTestSetup { bytes32 public constant EXECUTOR_SETTER_ROLE = 0x6a1dd52dcad5bd732e45b6af4e7344fa284e2d7d4b23b5b09cb55d36b0685c87; - bytes32 public constant FEE_SETTER_ROLE = - 0xe6ad9a47fbda1dc18de1eb5eeb7d935e5e81b4748f3cfc61e233e64f88182060; bytes32 public constant PAUSER_ROLE = 0x65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a; bytes32 public constant FUND_RESCUER_ROLE = @@ -133,32 +131,6 @@ contract TychoRouterTest is TychoRouterTestSetup { vm.stopPrank(); } - function testFeeSetting() public { - vm.startPrank(FEE_SETTER); - assertEq(tychoRouter.fee(), 0); - tychoRouter.setFee(100); - assertEq(tychoRouter.fee(), 100); - vm.stopPrank(); - - vm.startPrank(BOB); - vm.expectRevert(); - tychoRouter.setFee(200); - vm.stopPrank(); - } - - function testFeeReceiverSetting() public { - vm.startPrank(FEE_SETTER); - assertEq(tychoRouter.feeReceiver(), address(0)); - tychoRouter.setFeeReceiver(FEE_RECEIVER); - assertEq(tychoRouter.feeReceiver(), FEE_RECEIVER); - vm.stopPrank(); - - vm.startPrank(BOB); - vm.expectRevert(); - tychoRouter.setFeeReceiver(FEE_RECEIVER); - vm.stopPrank(); - } - function testPause() public { vm.startPrank(PAUSER); assertEq(tychoRouter.paused(), false); diff --git a/foundry/test/TychoRouterSequentialSwap.t.sol b/foundry/test/TychoRouterSequentialSwap.t.sol index 75b179f..c5db19f 100644 --- a/foundry/test/TychoRouterSequentialSwap.t.sol +++ b/foundry/test/TychoRouterSequentialSwap.t.sol @@ -8,9 +8,6 @@ import "./executors/UniswapV4Utils.sol"; import {SafeCallback} from "@uniswap/v4-periphery/src/base/SafeCallback.sol"; contract TychoRouterSequentialSwapTest is TychoRouterTestSetup { - bytes32 public constant FEE_SETTER_ROLE = - 0xe6ad9a47fbda1dc18de1eb5eeb7d935e5e81b4748f3cfc61e233e64f88182060; - function _getSequentialSwaps() internal view returns (bytes[] memory) { // Trade 1 WETH for USDC through DAI with 2 swaps on Uniswap V2 // 1 WETH -> DAI -> USDC @@ -181,49 +178,6 @@ contract TychoRouterSequentialSwapTest is TychoRouterTestSetup { vm.stopPrank(); } - function testSequentialSwapFee() public { - // Trade 1 WETH for USDC - // Takes 1% fee at the end - - vm.startPrank(FEE_SETTER); - tychoRouter.setFee(100); - tychoRouter.setFeeReceiver(FEE_RECEIVER); - vm.stopPrank(); - - uint256 amountIn = 1 ether; - deal(WETH_ADDR, ALICE, amountIn); - - vm.startPrank(ALICE); - - ( - IAllowanceTransfer.PermitSingle memory permitSingle, - bytes memory signature - ) = handlePermit2Approval(WETH_ADDR, amountIn); - - bytes[] memory swaps = _getSequentialSwaps(); - - uint256 amountOut = tychoRouter.sequentialSwapPermit2( - amountIn, - WETH_ADDR, - USDC_ADDR, - 1000_000000, - false, - false, - ALICE, - permitSingle, - signature, - pleEncode(swaps) - ); - - uint256 expectedAmount = 2618213190; - assertEq(amountOut, expectedAmount); - uint256 usdcBalance = IERC20(USDC_ADDR).balanceOf(ALICE); - assertEq(usdcBalance, expectedAmount); - assertEq(IERC20(USDC_ADDR).balanceOf(FEE_RECEIVER), 26446597); - - vm.stopPrank(); - } - function testSequentialSwapWrapETH() public { uint256 amountIn = 1 ether; deal(ALICE, amountIn); diff --git a/foundry/test/TychoRouterSingleSwap.t.sol b/foundry/test/TychoRouterSingleSwap.t.sol index 9ca7e40..ea33401 100644 --- a/foundry/test/TychoRouterSingleSwap.t.sol +++ b/foundry/test/TychoRouterSingleSwap.t.sol @@ -8,9 +8,6 @@ import "./executors/UniswapV4Utils.sol"; import {SafeCallback} from "@uniswap/v4-periphery/src/base/SafeCallback.sol"; contract TychoRouterSingleSwapTest is TychoRouterTestSetup { - bytes32 public constant FEE_SETTER_ROLE = - 0xe6ad9a47fbda1dc18de1eb5eeb7d935e5e81b4748f3cfc61e233e64f88182060; - function testSingleSwapPermit2() public { // Trade 1 WETH for DAI with 1 swap on Uniswap V2 using Permit2 // 1 WETH -> DAI @@ -179,50 +176,6 @@ contract TychoRouterSingleSwapTest is TychoRouterTestSetup { ); } - function testSingleSwapFee() public { - // Trade 1 WETH for DAI with 1 swap on Uniswap V2 - // Takes 1% fee at the end - - vm.startPrank(FEE_SETTER); - tychoRouter.setFee(100); - tychoRouter.setFeeReceiver(FEE_RECEIVER); - vm.stopPrank(); - - uint256 amountIn = 1 ether; - - deal(WETH_ADDR, ALICE, amountIn); - vm.startPrank(ALICE); - // Approve the tokenIn to be transferred to the router - IERC20(WETH_ADDR).approve(address(tychoRouterAddr), amountIn); - - bytes memory protocolData = encodeUniswapV2Swap( - WETH_ADDR, WETH_DAI_POOL, tychoRouterAddr, false - ); - - bytes memory swap = - encodeSingleSwap(address(usv2Executor), protocolData); - - uint256 minAmountOut = 2600 * 1e18; - uint256 amountOut = tychoRouter.singleSwap( - amountIn, - WETH_ADDR, - DAI_ADDR, - minAmountOut, - false, - false, - ALICE, - swap - ); - - uint256 expectedAmount = 2633283105570259262790; - assertEq(amountOut, expectedAmount); - uint256 usdcBalance = IERC20(DAI_ADDR).balanceOf(ALICE); - assertEq(usdcBalance, expectedAmount); - assertEq(IERC20(DAI_ADDR).balanceOf(FEE_RECEIVER), 26598819248184436997); - - vm.stopPrank(); - } - function testSingleSwapWrapETH() public { uint256 amountIn = 1 ether; deal(ALICE, amountIn); diff --git a/foundry/test/TychoRouterSplitSwap.t.sol b/foundry/test/TychoRouterSplitSwap.t.sol index 12ae2a4..0887500 100644 --- a/foundry/test/TychoRouterSplitSwap.t.sol +++ b/foundry/test/TychoRouterSplitSwap.t.sol @@ -8,9 +8,6 @@ import "./executors/UniswapV4Utils.sol"; import {SafeCallback} from "@uniswap/v4-periphery/src/base/SafeCallback.sol"; contract TychoRouterSplitSwapTest is TychoRouterTestSetup { - bytes32 public constant FEE_SETTER_ROLE = - 0xe6ad9a47fbda1dc18de1eb5eeb7d935e5e81b4748f3cfc61e233e64f88182060; - function _getSplitSwaps() private view returns (bytes[] memory) { // Trade 1 WETH for USDC through DAI and WBTC with 4 swaps on Uniswap V2 // -> DAI -> @@ -223,59 +220,6 @@ contract TychoRouterSplitSwapTest is TychoRouterTestSetup { vm.stopPrank(); } - function testSplitSwapFee() public { - // Trade 1 WETH for DAI with 1 swap on Uniswap V2 - // Does permit2 token approval and transfer - // Takes fee at the end - - vm.startPrank(FEE_SETTER); - tychoRouter.setFee(100); - tychoRouter.setFeeReceiver(FEE_RECEIVER); - vm.stopPrank(); - - uint256 amountIn = 1 ether; - deal(WETH_ADDR, ALICE, amountIn); - - vm.startPrank(ALICE); - - ( - IAllowanceTransfer.PermitSingle memory permitSingle, - bytes memory signature - ) = handlePermit2Approval(WETH_ADDR, amountIn); - - bytes memory protocolData = encodeUniswapV2Swap( - WETH_ADDR, WETH_DAI_POOL, tychoRouterAddr, false - ); - - bytes memory swap = encodeSplitSwap( - uint8(0), uint8(1), uint24(0), address(usv2Executor), protocolData - ); - bytes[] memory swaps = new bytes[](1); - swaps[0] = swap; - - uint256 amountOut = tychoRouter.splitSwapPermit2( - amountIn, - WETH_ADDR, - DAI_ADDR, - 2633283105570259262780, - false, - false, - 2, - ALICE, - permitSingle, - signature, - pleEncode(swaps) - ); - - uint256 expectedAmount = 2633283105570259262790; - assertEq(amountOut, expectedAmount); - uint256 daiBalance = IERC20(DAI_ADDR).balanceOf(ALICE); - assertEq(daiBalance, expectedAmount); - assertEq(IERC20(DAI_ADDR).balanceOf(FEE_RECEIVER), 26598819248184436997); - - vm.stopPrank(); - } - function testSplitSwapWrapETH() public { // Trade 1 ETH (and wrap it) for DAI with 1 swap on Uniswap V2 diff --git a/foundry/test/TychoRouterTestSetup.sol b/foundry/test/TychoRouterTestSetup.sol index edecb13..1690d3c 100644 --- a/foundry/test/TychoRouterTestSetup.sol +++ b/foundry/test/TychoRouterTestSetup.sol @@ -78,7 +78,6 @@ contract TychoRouterTestSetup is Constants { tychoRouter = new TychoRouterExposed(PERMIT2_ADDRESS, WETH_ADDR); tychoRouterAddr = address(tychoRouter); tychoRouter.grantRole(keccak256("FUND_RESCUER_ROLE"), FUND_RESCUER); - tychoRouter.grantRole(keccak256("FEE_SETTER_ROLE"), FEE_SETTER); tychoRouter.grantRole(keccak256("PAUSER_ROLE"), PAUSER); tychoRouter.grantRole(keccak256("UNPAUSER_ROLE"), UNPAUSER); tychoRouter.grantRole(