diff --git a/contracts/GenericSwap.sol b/contracts/GenericSwap.sol index e4c429f8..f1b8e3a1 100644 --- a/contracts/GenericSwap.sol +++ b/contracts/GenericSwap.sol @@ -28,8 +28,12 @@ contract GenericSwap is IGenericSwap, TokenCollector, EIP712 { receive() external payable {} /// @inheritdoc IGenericSwap - function executeSwap(GenericSwapData calldata swapData, bytes calldata takerTokenPermit) external payable returns (uint256 returnAmount) { - returnAmount = _executeSwap(swapData, msg.sender, takerTokenPermit); + function executeSwap( + GenericSwapData calldata swapData, + bytes calldata strategyData, + bytes calldata takerTokenPermit + ) external payable returns (uint256 returnAmount) { + returnAmount = _executeSwap(swapData, strategyData, msg.sender, takerTokenPermit); _emitGSExecuted(getGSDataHash(swapData), swapData, msg.sender, returnAmount); } @@ -37,6 +41,7 @@ contract GenericSwap is IGenericSwap, TokenCollector, EIP712 { /// @inheritdoc IGenericSwap function executeSwapWithSig( GenericSwapData calldata swapData, + bytes calldata strategyData, bytes calldata takerTokenPermit, address taker, bytes calldata takerSig @@ -47,7 +52,7 @@ contract GenericSwap is IGenericSwap, TokenCollector, EIP712 { filledSwap[swapHash] = true; if (!SignatureValidator.validateSignature(taker, gs712Hash, takerSig)) revert InvalidSignature(); - returnAmount = _executeSwap(swapData, taker, takerTokenPermit); + returnAmount = _executeSwap(swapData, strategyData, taker, takerTokenPermit); _emitGSExecuted(swapHash, swapData, taker, returnAmount); } @@ -59,6 +64,7 @@ contract GenericSwap is IGenericSwap, TokenCollector, EIP712 { /// @return returnAmount The output amount of the swap. function _executeSwap( GenericSwapData calldata _swapData, + bytes calldata strategyData, address _authorizedUser, bytes calldata _takerTokenPermit ) private returns (uint256 returnAmount) { @@ -75,7 +81,7 @@ contract GenericSwap is IGenericSwap, TokenCollector, EIP712 { _collect(_inputToken, _authorizedUser, _swapData.maker, _swapData.takerTokenAmount, _takerTokenPermit); } - IStrategy(_swapData.maker).executeStrategy{ value: msg.value }(_inputToken, _outputToken, _swapData.takerTokenAmount, _swapData.strategyData); + IStrategy(_swapData.maker).executeStrategy{ value: msg.value }(_inputToken, _outputToken, _swapData.takerTokenAmount, strategyData); returnAmount = _outputToken.getBalance(address(this)); if (returnAmount > 1) { diff --git a/contracts/interfaces/IGenericSwap.sol b/contracts/interfaces/IGenericSwap.sol index 4bc5693e..e5237836 100644 --- a/contracts/interfaces/IGenericSwap.sol +++ b/contracts/interfaces/IGenericSwap.sol @@ -56,18 +56,25 @@ interface IGenericSwap { /// @notice Executes a swap using provided swap data and taker token permit. /// @param swapData The swap data containing details of the swap. + /// @param strategyData The strategy data contains the details on how to perform the swap. /// @param takerTokenPermit The permit for spending taker's tokens. /// @return returnAmount The amount of tokens returned from the swap. - function executeSwap(GenericSwapData calldata swapData, bytes calldata takerTokenPermit) external payable returns (uint256 returnAmount); + function executeSwap( + GenericSwapData calldata swapData, + bytes calldata strategyData, + bytes calldata takerTokenPermit + ) external payable returns (uint256 returnAmount); /// @notice Executes a swap using provided swap data, taker token permit, taker address, and signature. /// @param swapData The swap data containing details of the swap. + /// @param strategyData The strategy data contains the details on how to perform the swap. /// @param takerTokenPermit The permit for spending taker's tokens. /// @param taker The address of the taker initiating the swap. /// @param takerSig The signature of the taker authorizing the swap. /// @return returnAmount The amount of tokens returned from the swap. function executeSwapWithSig( GenericSwapData calldata swapData, + bytes calldata strategyData, bytes calldata takerTokenPermit, address taker, bytes calldata takerSig diff --git a/contracts/libraries/GenericSwapData.sol b/contracts/libraries/GenericSwapData.sol index fa73b681..8bc85d9f 100644 --- a/contracts/libraries/GenericSwapData.sol +++ b/contracts/libraries/GenericSwapData.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; string constant GS_DATA_TYPESTRING = string( - "GenericSwapData(address maker,address takerToken,uint256 takerTokenAmount,address makerToken,uint256 makerTokenAmount,uint256 minMakerTokenAmount,uint256 expiry,uint256 salt,address recipient,bytes strategyData)" + "GenericSwapData(address maker,address takerToken,uint256 takerTokenAmount,address makerToken,uint256 makerTokenAmount,uint256 minMakerTokenAmount,uint256 expiry,uint256 salt,address recipient)" ); bytes32 constant GS_DATA_TYPEHASH = keccak256(bytes(GS_DATA_TYPESTRING)); @@ -17,7 +17,6 @@ struct GenericSwapData { uint256 expiry; uint256 salt; address payable recipient; - bytes strategyData; } // solhint-disable-next-line func-visibility @@ -34,8 +33,7 @@ function getGSDataHash(GenericSwapData memory gsData) pure returns (bytes32) { gsData.minMakerTokenAmount, gsData.expiry, gsData.salt, - gsData.recipient, - keccak256(gsData.strategyData) + gsData.recipient ) ); } diff --git a/test/Signing.t.sol b/test/Signing.t.sol index d571a9ee..56b4c131 100644 --- a/test/Signing.t.sol +++ b/test/Signing.t.sol @@ -48,8 +48,7 @@ contract testEIP712Signing is SigHelper { minMakerTokenAmount: abi.decode(vm.parseJson(genericSwapDataPayloadJson, "$.minMakerTokenAmount"), (uint256)), expiry: abi.decode(vm.parseJson(genericSwapDataPayloadJson, "$.expiry"), (uint256)), salt: abi.decode(vm.parseJson(genericSwapDataPayloadJson, "$.salt"), (uint256)), - recipient: abi.decode(vm.parseJson(genericSwapDataPayloadJson, "$.recipient"), (address)), - strategyData: abi.decode(vm.parseJson(genericSwapDataPayloadJson, "$.strategyData"), (bytes)) + recipient: abi.decode(vm.parseJson(genericSwapDataPayloadJson, "$.recipient"), (address)) }); uint256 signingKey = abi.decode(vm.parseJson(genericSwapDataPayloadJson, "$.signingKey"), (uint256)); bytes memory sig = signGenericSwap(signingKey, genericSwapData, chainId, verifyingContract); diff --git a/test/forkMainnet/GenericSwap.t.sol b/test/forkMainnet/GenericSwap.t.sol index b71e4999..dbcef983 100644 --- a/test/forkMainnet/GenericSwap.t.sol +++ b/test/forkMainnet/GenericSwap.t.sol @@ -14,7 +14,6 @@ import { IUniswapSwapRouter02 } from "test/utils/IUniswapSwapRouter02.sol"; import { MockStrategy } from "test/mocks/MockStrategy.sol"; import { GenericSwap } from "contracts/GenericSwap.sol"; import { AllowanceTarget } from "contracts/AllowanceTarget.sol"; -import { TokenCollector } from "contracts/abstracts/TokenCollector.sol"; import { SmartOrderStrategy } from "contracts/SmartOrderStrategy.sol"; import { Constant } from "contracts/libraries/Constant.sol"; import { GenericSwapData, getGSDataHash } from "contracts/libraries/GenericSwapData.sol"; @@ -50,6 +49,7 @@ contract GenericSwapTest is Test, Tokens, BalanceUtil, Permit2Helper, SigHelper uint24[] defaultV3Fees = [3000]; bytes defaultTakerPermit; bytes alicePermit; + bytes strategyData; SmartOrderStrategy smartStrategy; GenericSwap genericSwap; GenericSwapData defaultGSData; @@ -104,7 +104,7 @@ contract GenericSwapTest is Test, Tokens, BalanceUtil, Permit2Helper, SigHelper value: 0, data: routerPayload }); - bytes memory swapData = abi.encode(operations); + strategyData = abi.encode(operations); deal(taker, 100 ether); setTokenBalanceAndApprove(taker, UNISWAP_PERMIT2_ADDRESS, tokens, 100000); @@ -122,8 +122,7 @@ contract GenericSwapTest is Test, Tokens, BalanceUtil, Permit2Helper, SigHelper minMakerTokenAmount: minOutputAmount, expiry: defaultExpiry, salt: 5678, - recipient: payable(taker), - strategyData: swapData + recipient: payable(taker) }); defaultTakerPermit = getTokenlonPermit2Data(taker, takerPrivateKey, defaultGSData.takerToken, address(genericSwap)); @@ -154,7 +153,7 @@ contract GenericSwapTest is Test, Tokens, BalanceUtil, Permit2Helper, SigHelper ); vm.prank(taker); - genericSwap.executeSwap(defaultGSData, defaultTakerPermit); + genericSwap.executeSwap(defaultGSData, strategyData, defaultTakerPermit); takerTakerToken.assertChange(-int256(defaultGSData.takerTokenAmount)); // the makerTokenAmount in the defaultGSData is the exact quote from strategy @@ -190,7 +189,7 @@ contract GenericSwapTest is Test, Tokens, BalanceUtil, Permit2Helper, SigHelper gsData.salt ); vm.prank(taker); - genericSwap.executeSwap(gsData, defaultTakerPermit); + genericSwap.executeSwap(gsData, strategyData, defaultTakerPermit); takerTakerToken.assertChange(-int256(gsData.takerTokenAmount)); takerMakerToken.assertChange(int256(realChangedInGS)); @@ -225,7 +224,7 @@ contract GenericSwapTest is Test, Tokens, BalanceUtil, Permit2Helper, SigHelper gsData.salt ); vm.prank(taker); - genericSwap.executeSwap{ value: gsData.takerTokenAmount }(gsData, defaultTakerPermit); + genericSwap.executeSwap{ value: gsData.takerTokenAmount }(gsData, strategyData, defaultTakerPermit); takerTakerToken.assertChange(-int256(gsData.takerTokenAmount)); takerMakerToken.assertChange(int256(realChangedInGS)); @@ -261,7 +260,7 @@ contract GenericSwapTest is Test, Tokens, BalanceUtil, Permit2Helper, SigHelper gsData.salt ); vm.prank(taker); - genericSwap.executeSwap(gsData, defaultTakerPermit); + genericSwap.executeSwap(gsData, strategyData, defaultTakerPermit); takerTakerToken.assertChange(-int256(gsData.takerTokenAmount)); takerMakerToken.assertChange(int256(realChangedInGS)); @@ -274,13 +273,13 @@ contract GenericSwapTest is Test, Tokens, BalanceUtil, Permit2Helper, SigHelper vm.prank(taker); vm.expectRevert(IGenericSwap.ExpiredOrder.selector); - genericSwap.executeSwap(defaultGSData, defaultTakerPermit); + genericSwap.executeSwap(defaultGSData, strategyData, defaultTakerPermit); } function testCannotSwapWithInvalidETHInput() public { // case1 : msg.value != 0 when takerToken is not ETH vm.expectRevert(IGenericSwap.InvalidMsgValue.selector); - genericSwap.executeSwap{ value: 1 }(defaultGSData, defaultTakerPermit); + genericSwap.executeSwap{ value: 1 }(defaultGSData, strategyData, defaultTakerPermit); // change input token as ETH and update amount GenericSwapData memory gsData = defaultGSData; @@ -290,12 +289,12 @@ contract GenericSwapTest is Test, Tokens, BalanceUtil, Permit2Helper, SigHelper // case2 : msg.value > takerTokenAmount vm.prank(taker); vm.expectRevert(IGenericSwap.InvalidMsgValue.selector); - genericSwap.executeSwap{ value: gsData.takerTokenAmount + 1 }(gsData, defaultTakerPermit); + genericSwap.executeSwap{ value: gsData.takerTokenAmount + 1 }(gsData, strategyData, defaultTakerPermit); // case3 : msg.value < takerTokenAmount vm.prank(taker); vm.expectRevert(IGenericSwap.InvalidMsgValue.selector); - genericSwap.executeSwap{ value: gsData.takerTokenAmount - 1 }(gsData, defaultTakerPermit); + genericSwap.executeSwap{ value: gsData.takerTokenAmount - 1 }(gsData, strategyData, defaultTakerPermit); } function testCannotSwapWithInsufficientOutput() public { @@ -306,7 +305,7 @@ contract GenericSwapTest is Test, Tokens, BalanceUtil, Permit2Helper, SigHelper mockStrategy.setOutputAmountAndRecipient(gsData.minMakerTokenAmount - 1, payable(address(genericSwap))); vm.prank(taker); vm.expectRevert(IGenericSwap.InsufficientOutput.selector); - genericSwap.executeSwap(gsData, defaultTakerPermit); + genericSwap.executeSwap(gsData, strategyData, defaultTakerPermit); } function testCannotSwapWithZeroRecipient() public { @@ -315,7 +314,7 @@ contract GenericSwapTest is Test, Tokens, BalanceUtil, Permit2Helper, SigHelper vm.prank(taker); vm.expectRevert(IGenericSwap.ZeroAddress.selector); - genericSwap.executeSwap(gsData, defaultTakerPermit); + genericSwap.executeSwap(gsData, strategyData, defaultTakerPermit); } function testGenericSwapRelayed() public { @@ -336,7 +335,7 @@ contract GenericSwapTest is Test, Tokens, BalanceUtil, Permit2Helper, SigHelper ); bytes memory takerSig = signGenericSwap(takerPrivateKey, defaultGSData, address(genericSwap)); - genericSwap.executeSwapWithSig(defaultGSData, defaultTakerPermit, taker, takerSig); + genericSwap.executeSwapWithSig(defaultGSData, strategyData, defaultTakerPermit, taker, takerSig); takerTakerToken.assertChange(-int256(defaultGSData.takerTokenAmount)); // the makerTokenAmount in the defaultGSData is the exact quote from strategy @@ -349,15 +348,15 @@ contract GenericSwapTest is Test, Tokens, BalanceUtil, Permit2Helper, SigHelper vm.expectRevert(IGenericSwap.InvalidSignature.selector); // submit with user address as expected signer - genericSwap.executeSwapWithSig(defaultGSData, defaultTakerPermit, taker, randomSig); + genericSwap.executeSwapWithSig(defaultGSData, strategyData, defaultTakerPermit, taker, randomSig); } function testCannotReplayGenericSwapSig() public { bytes memory takerSig = signGenericSwap(takerPrivateKey, defaultGSData, address(genericSwap)); - genericSwap.executeSwapWithSig(defaultGSData, defaultTakerPermit, taker, takerSig); + genericSwap.executeSwapWithSig(defaultGSData, strategyData, defaultTakerPermit, taker, takerSig); vm.expectRevert(IGenericSwap.AlreadyFilled.selector); - genericSwap.executeSwapWithSig(defaultGSData, defaultTakerPermit, taker, takerSig); + genericSwap.executeSwapWithSig(defaultGSData, strategyData, defaultTakerPermit, taker, takerSig); } function testLeaveOneWeiWithMultipleUsers() public { @@ -385,7 +384,7 @@ contract GenericSwapTest is Test, Tokens, BalanceUtil, Permit2Helper, SigHelper ); vm.prank(taker); - genericSwap.executeSwap(defaultGSData, defaultTakerPermit); + genericSwap.executeSwap(defaultGSData, strategyData, defaultTakerPermit); // the second user: Alice // his makerTokenAmount is recalculate by `quoteExactInput() function base on the current state` @@ -418,7 +417,7 @@ contract GenericSwapTest is Test, Tokens, BalanceUtil, Permit2Helper, SigHelper ); vm.startPrank(alice); - genericSwap.executeSwap(aliceGSData, alicePermit); + genericSwap.executeSwap(aliceGSData, strategyData, alicePermit); vm.stopPrank(); takerTakerToken.assertChange(-int256(defaultGSData.takerTokenAmount)); diff --git a/test/utils/payload/genericSwapData.json b/test/utils/payload/genericSwapData.json index 71ab6c74..a4bd73f1 100644 --- a/test/utils/payload/genericSwapData.json +++ b/test/utils/payload/genericSwapData.json @@ -8,10 +8,9 @@ "expiry": 3376656000, "salt": 123, "recipient": "0xdf5621f59CcD4A58cF487E0C4E3fCDd6Db67E4dA", - "strategyData": "0xcbe324dfbf8d48a7ad9ef3cb0c2bdd411129db5238371b8609272f14921736fb0ab28dcede4f2e1e41393d575ffec60002e565bfbf5eaf896bc490a965c8452d08d9b71b", - "expectedSig": "0xdfe4e0414baa9b0ac4edcefc1d8ceb18dc21230f6b93a83c91188a105d1d7ece7809ca3c67db499fd497e35ba271a0a6689f7683d41b5d4602a5bb7895537a2d1c", + "expectedSig": "0x5a671e6994dbed10c4f8fd34cc4d526a8d74b15363fcefc30a20ad295674ec8a231c5e743da079623545601b37aa09c51c017da1a5cb6c0dde42da5fe7665e4c1b", "signingKey": "0x1dc4f07f92fa1783042350ffe685439f857a8fdd837589c00c5299e287c4afcb", "chainId": 5, "verifyingContract": "0x49eA36C04c109a8c62C9b48fd8C4d13b3EA98B27", - "typehash": "0x1b6f9d7673107802b331a5ab52a40f7d942bdf74fa821744df8b69eead3d26c1" + "typehash": "0x3aaeb6ca9ecb74a956054c8b123c6d2ab5251f97eed10a138611db2aafd0b792" }