From a43317b69bf7e73dcc5658cf5fd992be97e145ca Mon Sep 17 00:00:00 2001 From: Richa-iitr Date: Sat, 4 Jun 2022 09:13:19 +0530 Subject: [PATCH 01/27] swap-connector-polygon --- contracts/polygon/common/interfaces.sol | 4 + contracts/polygon/connectors/swap/events.sol | 14 +++ contracts/polygon/connectors/swap/helpers.sol | 94 +++++++++++++++++++ contracts/polygon/connectors/swap/main.sol | 82 ++++++++++++++++ 4 files changed, 194 insertions(+) create mode 100644 contracts/polygon/connectors/swap/events.sol create mode 100644 contracts/polygon/connectors/swap/helpers.sol create mode 100644 contracts/polygon/connectors/swap/main.sol diff --git a/contracts/polygon/common/interfaces.sol b/contracts/polygon/common/interfaces.sol index f843d5fb..e395b83c 100644 --- a/contracts/polygon/common/interfaces.sol +++ b/contracts/polygon/common/interfaces.sol @@ -26,3 +26,7 @@ interface AccountInterface { function disable(address) external; function isAuth(address) external view returns (bool); } + +interface InstaConnectors { + function connectors(string memory) external returns (address); +} diff --git a/contracts/polygon/connectors/swap/events.sol b/contracts/polygon/connectors/swap/events.sol new file mode 100644 index 00000000..0440abf0 --- /dev/null +++ b/contracts/polygon/connectors/swap/events.sol @@ -0,0 +1,14 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; + +contract Events { + event LogSwap( + string _connector, + address indexed buyToken, + address indexed sellToken, + uint256 buyAmt, + uint256 sellAmt, + uint256 getId, + uint256 setId + ); +} diff --git a/contracts/polygon/connectors/swap/helpers.sol b/contracts/polygon/connectors/swap/helpers.sol new file mode 100644 index 00000000..d5493866 --- /dev/null +++ b/contracts/polygon/connectors/swap/helpers.sol @@ -0,0 +1,94 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; +pragma abicoder v2; + +import { InstaConnectors } from "../../common/interfaces.sol"; + +abstract contract Helper { + /** + * @dev Instadapp Connectors Registry + */ + InstaConnectors internal constant instaConnectors = + InstaConnectors(0x2A00684bFAb9717C21271E0751BCcb7d2D763c88); + + struct InputData { + address buyAddr; + address sellAddr; + uint256 sellAmt; + uint256[] unitAmts; + bytes[] callDatas; + uint256 setId; + } +} + +contract SwapHelpers is Helper { + /** + *@param _connectors name of the connectors in preference order. + *@param _inputData data for the swap cast. + */ + function _swap(string[] memory _connectors, InputData memory _inputData) + internal + returns ( + bool success, + bytes memory returnData, + string memory _connector + ) + { + require(_connectors.length > 0, "zero-length-not-allowed"); + require( + _inputData.unitAmts.length == _connectors.length, + "unitAmts-length-invalid" + ); + require( + _inputData.callDatas.length == _connectors.length, + "callDatas-length-invalid" + ); + + for (uint256 i = 0; i < _connectors.length; i++) { + string[] memory _target = new string[](1); + bytes[] memory _data = new bytes[](1); + bytes4 swapData = bytes4( + keccak256("swap(address,address,uint256,uint256,bytes,uint256)") + ); + + string memory _1INCH = "1INCH-A"; + if (keccak256(bytes(_connectors[i])) == keccak256(bytes(_1INCH))) { + swapData = bytes4( + keccak256( + "sell(address,address,uint256,uint256,bytes,uint256)" + ) + ); + } + + _target[0] = _connectors[i]; + _data[0] = abi.encodeWithSelector( + swapData, + _inputData.buyAddr, + _inputData.sellAddr, + _inputData.sellAmt, + _inputData.unitAmts[i], + _inputData.callDatas[i], + _inputData.setId + ); + + bytes4 _castData = bytes4( + keccak256("cast(string[],bytes[],address)") + ); + bytes memory castData = abi.encodeWithSelector( + _castData, + _target, + _data, + address(0) + ); + + (success, returnData) = instaConnectors + .connectors(_connectors[i]) + .delegatecall(castData); + + if (success) { + _connector = _connectors[i]; + break; + } + } + } +} diff --git a/contracts/polygon/connectors/swap/main.sol b/contracts/polygon/connectors/swap/main.sol new file mode 100644 index 00000000..8a8561d1 --- /dev/null +++ b/contracts/polygon/connectors/swap/main.sol @@ -0,0 +1,82 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; + +/** + * @title Swap. + * @dev Swap integration for DEX Aggregators. + */ + +// import files +import { SwapHelpers } from "./helpers.sol"; +import { Events } from "./events.sol"; + +abstract contract Swap is SwapHelpers, Events { + /** + * @dev Swap ETH/ERC20_Token using dex aggregators. + * @notice Swap tokens from exchanges like kyber, 0x etc, with calculation done off-chain. + * @param _connectors The name of the connectors like 1INCH-A, 0x etc, in order of their priority. + * @param buyAddr The address of the token to buy.(For MATIC: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param sellAddr The address of the token to sell.(For MATIC: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param sellAmt The amount of the token to sell. + * @param unitAmts The amount of buyAmt/sellAmt with slippage for respective DEXs. + * @param callDatas Data from APIs for respective DEXs. + * @param setId ID stores the amount of token brought. + */ + function swap( + string[] memory _connectors, + address buyAddr, + address sellAddr, + uint256 sellAmt, + uint256[] memory unitAmts, + bytes[] calldata callDatas, + uint256 setId + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + InputData memory inputData = InputData({ + buyAddr: buyAddr, + sellAddr: sellAddr, + sellAmt: sellAmt, + unitAmts: unitAmts, + callDatas: callDatas, + setId: setId + }); + + ( + bool success, + bytes memory returnData, + string memory _connector + ) = _swap(_connectors, inputData); + + uint256 _buyAmt; + uint256 _sellAmt; + + if (!success) { + revert("swap-failed"); + } else { + (, _eventParam) = abi.decode(returnData, (string, bytes)); + (, , _buyAmt, _sellAmt, , ) = abi.decode( + _eventParam, + (address, address, uint256, uint256, uint256, uint256) + ); + } + + _eventName = "LogSwap(string,address,address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode( + _connector, + buyAddr, + sellAddr, + _buyAmt, + _sellAmt, + 0, + setId + ); + } +} + +contract ConnectV2Swap is Swap { + string public name = "Swap-v1"; +} From 2e21b0df0e29f33c9983ca61c3351dd5645231f1 Mon Sep 17 00:00:00 2001 From: Richa-iitr Date: Sat, 4 Jun 2022 09:20:36 +0530 Subject: [PATCH 02/27] minor change --- contracts/polygon/connectors/swap/helpers.sol | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/contracts/polygon/connectors/swap/helpers.sol b/contracts/polygon/connectors/swap/helpers.sol index d5493866..52bb12ad 100644 --- a/contracts/polygon/connectors/swap/helpers.sol +++ b/contracts/polygon/connectors/swap/helpers.sol @@ -22,10 +22,11 @@ abstract contract Helper { } contract SwapHelpers is Helper { - /** - *@param _connectors name of the connectors in preference order. - *@param _inputData data for the swap cast. - */ + /** + *@dev Performs the swap usign the dex aggregators. + *@param _connectors name of the connectors in preference order. + *@param _inputData data for the swap cast. + */ function _swap(string[] memory _connectors, InputData memory _inputData) internal returns ( @@ -51,7 +52,7 @@ contract SwapHelpers is Helper { keccak256("swap(address,address,uint256,uint256,bytes,uint256)") ); - string memory _1INCH = "1INCH-A"; + string memory _1INCH = "1INCH-A"; if (keccak256(bytes(_connectors[i])) == keccak256(bytes(_1INCH))) { swapData = bytes4( keccak256( From 6316cbe46e86138fa270b439ac9f7e6cb6ca93fa Mon Sep 17 00:00:00 2001 From: Richa-iitr Date: Sat, 4 Jun 2022 10:09:03 +0530 Subject: [PATCH 03/27] minor change --- contracts/polygon/connectors/swap/helpers.sol | 2 +- contracts/polygon/connectors/swap/main.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/polygon/connectors/swap/helpers.sol b/contracts/polygon/connectors/swap/helpers.sol index 52bb12ad..aa640a3b 100644 --- a/contracts/polygon/connectors/swap/helpers.sol +++ b/contracts/polygon/connectors/swap/helpers.sol @@ -23,7 +23,7 @@ abstract contract Helper { contract SwapHelpers is Helper { /** - *@dev Performs the swap usign the dex aggregators. + *@dev Swap using the dex aggregators. *@param _connectors name of the connectors in preference order. *@param _inputData data for the swap cast. */ diff --git a/contracts/polygon/connectors/swap/main.sol b/contracts/polygon/connectors/swap/main.sol index 8a8561d1..49e2844b 100644 --- a/contracts/polygon/connectors/swap/main.sol +++ b/contracts/polygon/connectors/swap/main.sol @@ -14,7 +14,7 @@ import { Events } from "./events.sol"; abstract contract Swap is SwapHelpers, Events { /** * @dev Swap ETH/ERC20_Token using dex aggregators. - * @notice Swap tokens from exchanges like kyber, 0x etc, with calculation done off-chain. + * @notice Swap tokens from exchanges like 1INCH, 0x etc, with calculation done off-chain. * @param _connectors The name of the connectors like 1INCH-A, 0x etc, in order of their priority. * @param buyAddr The address of the token to buy.(For MATIC: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) * @param sellAddr The address of the token to sell.(For MATIC: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) From 59334b7b72ffc78e2807533a7026ff78047a7702 Mon Sep 17 00:00:00 2001 From: Richa-iitr Date: Sat, 4 Jun 2022 17:54:25 +0530 Subject: [PATCH 04/27] updated code --- contracts/polygon/connectors/swap/helpers.sol | 38 +++++++++++-------- contracts/polygon/connectors/swap/main.sol | 8 +--- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/contracts/polygon/connectors/swap/helpers.sol b/contracts/polygon/connectors/swap/helpers.sol index aa640a3b..c2b3c67f 100644 --- a/contracts/polygon/connectors/swap/helpers.sol +++ b/contracts/polygon/connectors/swap/helpers.sol @@ -45,9 +45,9 @@ contract SwapHelpers is Helper { "callDatas-length-invalid" ); + // require _connectors[i] == "1INCH-A" || "ZEROX-A" || "PARASWAP-A" || similar connectors + for (uint256 i = 0; i < _connectors.length; i++) { - string[] memory _target = new string[](1); - bytes[] memory _data = new bytes[](1); bytes4 swapData = bytes4( keccak256("swap(address,address,uint256,uint256,bytes,uint256)") ); @@ -61,8 +61,7 @@ contract SwapHelpers is Helper { ); } - _target[0] = _connectors[i]; - _data[0] = abi.encodeWithSelector( + bytes memory _data = abi.encodeWithSelector( swapData, _inputData.buyAddr, _inputData.sellAddr, @@ -72,19 +71,9 @@ contract SwapHelpers is Helper { _inputData.setId ); - bytes4 _castData = bytes4( - keccak256("cast(string[],bytes[],address)") - ); - bytes memory castData = abi.encodeWithSelector( - _castData, - _target, - _data, - address(0) - ); - (success, returnData) = instaConnectors .connectors(_connectors[i]) - .delegatecall(castData); + .delegatecall(_data); if (success) { _connector = _connectors[i]; @@ -92,4 +81,23 @@ contract SwapHelpers is Helper { } } } + + function decodeEvents(string memory _connector, bytes memory returnData) + internal + view + returns (uint256 _buyAmt, uint256 _sellAmt) + { + (, bytes memory _eventParam) = abi.decode(returnData, (string, bytes)); + if (keccak256(bytes(_connector)) == keccak256(bytes("PARASWAP-A"))) { + (, , _buyAmt, _sellAmt, ) = abi.decode( + _eventParam, + (address, address, uint256, uint256, uint256) + ); + } else { + (, , _buyAmt, _sellAmt, , ) = abi.decode( + _eventParam, + (address, address, uint256, uint256, uint256, uint256) + ); + } + } } diff --git a/contracts/polygon/connectors/swap/main.sol b/contracts/polygon/connectors/swap/main.sol index 49e2844b..c59f5d9d 100644 --- a/contracts/polygon/connectors/swap/main.sol +++ b/contracts/polygon/connectors/swap/main.sol @@ -57,11 +57,7 @@ abstract contract Swap is SwapHelpers, Events { if (!success) { revert("swap-failed"); } else { - (, _eventParam) = abi.decode(returnData, (string, bytes)); - (, , _buyAmt, _sellAmt, , ) = abi.decode( - _eventParam, - (address, address, uint256, uint256, uint256, uint256) - ); + (_buyAmt, _sellAmt) = decodeEvents(_connector, returnData); } _eventName = "LogSwap(string,address,address,uint256,uint256,uint256,uint256)"; @@ -77,6 +73,6 @@ abstract contract Swap is SwapHelpers, Events { } } -contract ConnectV2Swap is Swap { +contract ConnectV2SwapPolygon is Swap { string public name = "Swap-v1"; } From 550f88ed6c0e50c3ee72cec6ef64c6d405a47cf8 Mon Sep 17 00:00:00 2001 From: Richa-iitr Date: Sat, 4 Jun 2022 17:59:38 +0530 Subject: [PATCH 05/27] tests-polygon --- test/polygon/swap/swap-test.ts | 173 +++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 test/polygon/swap/swap-test.ts diff --git a/test/polygon/swap/swap-test.ts b/test/polygon/swap/swap-test.ts new file mode 100644 index 00000000..80090ea8 --- /dev/null +++ b/test/polygon/swap/swap-test.ts @@ -0,0 +1,173 @@ +import hre from "hardhat"; +import axios from "axios"; +import { expect } from "chai"; +const { ethers } = hre; //check +import { BigNumber } from "bignumber.js"; +import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector"; +import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2"; +import { encodeSpells } from "../../../scripts/tests/encodeSpells"; +import { getMasterSigner } from "../../../scripts/tests/getMasterSigner"; +import { addresses } from "../../../scripts/tests/polygon/addresses"; +import { abis } from "../../../scripts/constant/abis"; +import { ConnectV2SwapPolygon__factory } from "../../../typechain"; +import er20abi from "../../../scripts/constant/abi/basics/erc20.json"; +import type { Signer, Contract } from "ethers"; + +describe("Swap", function () { + const connectorName = "swap-test"; + + let dsaWallet0: Contract; + let wallet0: Signer, wallet1: Signer; + let masterSigner: Signer; + let instaConnectorsV2: Contract; + let connector: Contract; + + before(async () => { + await hre.network.provider.request({ + method: "hardhat_reset", + params: [ + { + forking: { + // @ts-ignore + jsonRpcUrl: hre.config.networks.hardhat.forking.url + } + } + ] + }); + [wallet0, wallet1] = await ethers.getSigners(); + + masterSigner = await getMasterSigner(); + instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); + connector = await deployAndEnableConnector({ + connectorName, + contractArtifact: ConnectV2SwapPolygon__factory, + signer: masterSigner, + connectors: instaConnectorsV2 + }); + console.log("Connector address", connector.address); + }); + + it("Should have contracts deployed.", async function () { + expect(!!instaConnectorsV2.address).to.be.true; + expect(!!connector.address).to.be.true; + expect(!!(await masterSigner.getAddress())).to.be.true; + }); + + describe("DSA wallet setup", function () { + it("Should build DSA v2", async function () { + dsaWallet0 = await buildDSAv2(await wallet0.getAddress()); + console.log(dsaWallet0.address); + expect(!!dsaWallet0.address).to.be.true; + }); + + it("Deposit matic into DSA wallet", async function () { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: ethers.utils.parseEther("10") + }); + + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); + }); + }); + + describe("Main", function () { + it("should swap the tokens", async function () { + let buyTokenAmountZeroX: any; + let buyTokenAmount1Inch: any; + let buyTokenAmountParaswap: any; + async function getArg() { + // const slippage = 0.5; + /* matic -> usdt */ + const sellTokenAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; // matic, decimals 18 + const sellTokenDecimals = 18; + const buyTokenAddress = "0xc2132d05d31c914a87c6611c10748aeb04b58e8f"; // USDT, decimals 6 + const buyTokenDecimals = 6; + const amount = 2; + + const srcAmount = new BigNumber(amount).times(new BigNumber(10).pow(sellTokenDecimals)).toFixed(0); + + let zeroXUrl = `https://polygon.api.0x.org/swap/v1/quote`; + let paraswapUrl1 = `https://apiv5.paraswap.io/prices/`; + let paraswapUrl2 = `https://apiv5.paraswap.io/transactions/137?ignoreChecks=true`; + + //zeroX + const paramsZeroX = { + buyToken: "USDT", + sellToken: "MATIC", + sellAmount: "2000000000000000000" // Always denominated in wei + }; + + const responseZeroX = await axios.get(zeroXUrl, { params: paramsZeroX }).then((data: any) => data); + buyTokenAmountZeroX = responseZeroX.data.buyAmount; + const calldataZeroX = responseZeroX.data.data; + + //paraswap + let paramsPara = { + srcToken: sellTokenAddress, + destToken: buyTokenAddress, + srcDecimals: sellTokenDecimals, + destDecimals: buyTokenDecimals, + amount: srcAmount, + side: "SELL", + network: 137 + }; + + const priceRoute = (await axios.get(paraswapUrl1, { params: paramsPara })).data.priceRoute; + buyTokenAmountParaswap = priceRoute.destAmount; + let minAmount = new BigNumber(priceRoute.destAmount).times((100 - 1) / 100).toFixed(0); + + let txConfig = { + priceRoute: priceRoute, + srcToken: sellTokenAddress, + destToken: buyTokenAddress, + srcDecimals: sellTokenDecimals, + destDecimals: buyTokenDecimals, + srcAmount: srcAmount, + destAmount: minAmount, + userAddress: dsaWallet0.address + }; + const calldataPara = (await axios.post(paraswapUrl2, txConfig)).data.data; + + let calculateUnitAmt = (buyAmount: any) => { + const buyTokenAmountRes = new BigNumber(buyAmount) + .dividedBy(new BigNumber(10).pow(buyTokenDecimals)) + .toFixed(8); + + let unitAmt: any = new BigNumber(buyTokenAmountRes).dividedBy(new BigNumber(amount)); + + unitAmt = unitAmt.multipliedBy((100 - 1) / 100); + unitAmt = unitAmt.multipliedBy(1e18).toFixed(0); + return unitAmt; + }; + let unitAmt0x = calculateUnitAmt(buyTokenAmountZeroX); + let unitAmtParaswap = calculateUnitAmt(buyTokenAmountParaswap); + + let unitAmts = [unitAmt0x, unitAmtParaswap]; + let calldatas = [calldataZeroX, calldataPara]; + + let connectors = ["ZEROX-A", "PARASWAP-A"]; + + return [connectors, buyTokenAddress, sellTokenAddress, srcAmount, unitAmts, calldatas, 0]; + } + + let arg = await getArg(); + const spells = [ + { + connector: connectorName, + method: "swap", + args: arg + } + ]; + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), await wallet1.getAddress()); + const receipt = await tx.wait(); + + const usdtToken = await ethers.getContractAt( + er20abi, + "0xc2132d05d31c914a87c6611c10748aeb04b58e8f" // usdt address + ); + + expect(await usdtToken.balanceOf(dsaWallet0.address)).to.be.gte(buyTokenAmountZeroX); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(ethers.utils.parseEther("9")); + }); + }); +}); From 8e89d6652135b54ca0289d81a379adc0f2923dcd Mon Sep 17 00:00:00 2001 From: Richa-iitr Date: Sun, 5 Jun 2022 00:34:58 +0530 Subject: [PATCH 06/27] swap-mainnet,avalanche --- contracts/avalanche/common/interfaces.sol | 4 + .../avalanche/connectors/swap/events.sol | 14 +++ .../avalanche/connectors/swap/helpers.sol | 102 ++++++++++++++++++ contracts/avalanche/connectors/swap/main.sol | 78 ++++++++++++++ contracts/mainnet/common/interfaces.sol | 4 + contracts/mainnet/connectors/swap/events.sol | 14 +++ contracts/mainnet/connectors/swap/helpers.sol | 102 ++++++++++++++++++ contracts/mainnet/connectors/swap/main.sol | 78 ++++++++++++++ 8 files changed, 396 insertions(+) create mode 100644 contracts/avalanche/connectors/swap/events.sol create mode 100644 contracts/avalanche/connectors/swap/helpers.sol create mode 100644 contracts/avalanche/connectors/swap/main.sol create mode 100644 contracts/mainnet/connectors/swap/events.sol create mode 100644 contracts/mainnet/connectors/swap/helpers.sol create mode 100644 contracts/mainnet/connectors/swap/main.sol diff --git a/contracts/avalanche/common/interfaces.sol b/contracts/avalanche/common/interfaces.sol index cffe7136..e9a3b0c1 100644 --- a/contracts/avalanche/common/interfaces.sol +++ b/contracts/avalanche/common/interfaces.sol @@ -21,3 +21,7 @@ interface AccountInterface { function disable(address) external; function isAuth(address) external view returns (bool); } + +interface InstaConnectors { + function connectors(string memory) external returns (address); +} diff --git a/contracts/avalanche/connectors/swap/events.sol b/contracts/avalanche/connectors/swap/events.sol new file mode 100644 index 00000000..0440abf0 --- /dev/null +++ b/contracts/avalanche/connectors/swap/events.sol @@ -0,0 +1,14 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; + +contract Events { + event LogSwap( + string _connector, + address indexed buyToken, + address indexed sellToken, + uint256 buyAmt, + uint256 sellAmt, + uint256 getId, + uint256 setId + ); +} diff --git a/contracts/avalanche/connectors/swap/helpers.sol b/contracts/avalanche/connectors/swap/helpers.sol new file mode 100644 index 00000000..5285982f --- /dev/null +++ b/contracts/avalanche/connectors/swap/helpers.sol @@ -0,0 +1,102 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; +pragma abicoder v2; + +import { InstaConnectors } from "../../common/interfaces.sol"; + +abstract contract Helper { + /** + * @dev Instadapp Connectors Registry + */ + InstaConnectors internal constant instaConnectors = + InstaConnectors(0x127d8cD0E2b2E0366D522DeA53A787bfE9002C14); + + struct InputData { + address buyAddr; + address sellAddr; + uint256 sellAmt; + uint256[] unitAmts; + bytes[] callDatas; + uint256 setId; + } +} + +contract SwapHelpers is Helper { + /** + *@dev Swap using the dex aggregators. + *@param _connectors name of the connectors in preference order. + *@param _inputData data for the swap cast. + */ + function _swap(string[] memory _connectors, InputData memory _inputData) + internal + returns ( + bool success, + bytes memory returnData, + string memory _connector + ) + { + require(_connectors.length > 0, "zero-length-not-allowed"); + require( + _inputData.unitAmts.length == _connectors.length, + "unitAmts-length-invalid" + ); + require( + _inputData.callDatas.length == _connectors.length, + "callDatas-length-invalid" + ); + + // require _connectors[i] == "1INCH-A" || "ZEROX-A" || "PARASWAP-A" || similar connectors + + for (uint256 i = 0; i < _connectors.length; i++) { + bytes4 swapData = bytes4( + keccak256("swap(address,address,uint256,uint256,bytes,uint256)") + ); + + string memory _1INCH = "1INCH-A"; + if (keccak256(bytes(_connectors[i])) == keccak256(bytes(_1INCH))) { + swapData = bytes4( + keccak256( + "sell(address,address,uint256,uint256,bytes,uint256)" + ) + ); + } + + bytes memory _data = abi.encodeWithSelector( + swapData, + _inputData.buyAddr, + _inputData.sellAddr, + _inputData.sellAmt, + _inputData.unitAmts[i], + _inputData.callDatas[i], + _inputData.setId + ); + + (success, returnData) = instaConnectors + .connectors(_connectors[i]) + .delegatecall(_data); + if (success) { + _connector = _connectors[i]; + break; + } + } + } + + function decodeEvents(string memory _connector, bytes memory returnData) + internal + view + returns (uint256 _buyAmt, uint256 _sellAmt) + { + (, bytes memory _eventParam) = abi.decode(returnData, (string, bytes)); + if (keccak256(bytes(_connector)) == keccak256(bytes("PARASWAP-A"))) { + (, , _buyAmt, _sellAmt, ) = abi.decode( + _eventParam, + (address, address, uint256, uint256, uint256) + ); + } else { + (, , _buyAmt, _sellAmt, , ) = abi.decode( + _eventParam, + (address, address, uint256, uint256, uint256, uint256) + ); + } + } +} diff --git a/contracts/avalanche/connectors/swap/main.sol b/contracts/avalanche/connectors/swap/main.sol new file mode 100644 index 00000000..a25bcbc2 --- /dev/null +++ b/contracts/avalanche/connectors/swap/main.sol @@ -0,0 +1,78 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; + +/** + * @title Swap. + * @dev Swap integration for DEX Aggregators. + */ + +// import files +import { SwapHelpers } from "./helpers.sol"; +import { Events } from "./events.sol"; + +abstract contract Swap is SwapHelpers, Events { + /** + * @dev Swap ETH/ERC20_Token using dex aggregators. + * @notice Swap tokens from exchanges like 1INCH, 0x etc, with calculation done off-chain. + * @param _connectors The name of the connectors like 1INCH-A, 0x etc, in order of their priority. + * @param buyAddr The address of the token to buy.(For MATIC: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param sellAddr The address of the token to sell.(For MATIC: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param sellAmt The amount of the token to sell. + * @param unitAmts The amount of buyAmt/sellAmt with slippage for respective DEXs. + * @param callDatas Data from APIs for respective DEXs. + * @param setId ID stores the amount of token brought. + */ + function swap( + string[] memory _connectors, + address buyAddr, + address sellAddr, + uint256 sellAmt, + uint256[] memory unitAmts, + bytes[] calldata callDatas, + uint256 setId + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + InputData memory inputData = InputData({ + buyAddr: buyAddr, + sellAddr: sellAddr, + sellAmt: sellAmt, + unitAmts: unitAmts, + callDatas: callDatas, + setId: setId + }); + + ( + bool success, + bytes memory returnData, + string memory _connector + ) = _swap(_connectors, inputData); + + uint256 _buyAmt; + uint256 _sellAmt; + + if (!success) { + revert("swap-failed"); + } else { + (_buyAmt, _sellAmt) = decodeEvents(_connector, returnData); + } + + _eventName = "LogSwap(string,address,address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode( + _connector, + buyAddr, + sellAddr, + _buyAmt, + _sellAmt, + 0, + setId + ); + } +} + +contract ConnectV2SwapAvalanche is Swap { + string public name = "Swap-v1"; +} diff --git a/contracts/mainnet/common/interfaces.sol b/contracts/mainnet/common/interfaces.sol index 0ccaf951..e1ed2ca2 100644 --- a/contracts/mainnet/common/interfaces.sol +++ b/contracts/mainnet/common/interfaces.sol @@ -27,3 +27,7 @@ interface AccountInterface { function disable(address) external; function isAuth(address) external view returns (bool); } + +interface InstaConnectors { + function connectors(string memory) external returns (address); +} \ No newline at end of file diff --git a/contracts/mainnet/connectors/swap/events.sol b/contracts/mainnet/connectors/swap/events.sol new file mode 100644 index 00000000..0440abf0 --- /dev/null +++ b/contracts/mainnet/connectors/swap/events.sol @@ -0,0 +1,14 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; + +contract Events { + event LogSwap( + string _connector, + address indexed buyToken, + address indexed sellToken, + uint256 buyAmt, + uint256 sellAmt, + uint256 getId, + uint256 setId + ); +} diff --git a/contracts/mainnet/connectors/swap/helpers.sol b/contracts/mainnet/connectors/swap/helpers.sol new file mode 100644 index 00000000..c111767b --- /dev/null +++ b/contracts/mainnet/connectors/swap/helpers.sol @@ -0,0 +1,102 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; +pragma abicoder v2; + +import { InstaConnectors } from "../../common/interfaces.sol"; + +abstract contract Helper { + /** + * @dev Instadapp Connectors Registry + */ + InstaConnectors internal constant instaConnectors = + InstaConnectors(0x97b0B3A8bDeFE8cB9563a3c610019Ad10DB8aD11); + + struct InputData { + address buyAddr; + address sellAddr; + uint256 sellAmt; + uint256[] unitAmts; + bytes[] callDatas; + uint256 setId; + } +} + +contract SwapHelpers is Helper { + /** + *@dev Swap using the dex aggregators. + *@param _connectors name of the connectors in preference order. + *@param _inputData data for the swap cast. + */ + function _swap(string[] memory _connectors, InputData memory _inputData) + internal + returns ( + bool success, + bytes memory returnData, + string memory _connector + ) + { + require(_connectors.length > 0, "zero-length-not-allowed"); + require( + _inputData.unitAmts.length == _connectors.length, + "unitAmts-length-invalid" + ); + require( + _inputData.callDatas.length == _connectors.length, + "callDatas-length-invalid" + ); + + // require _connectors[i] == "1INCH-A" || "ZEROX-A" || "PARASWAP-A" || similar connectors + + for (uint256 i = 0; i < _connectors.length; i++) { + bytes4 swapData = bytes4( + keccak256("swap(address,address,uint256,uint256,bytes,uint256)") + ); + + string memory _1INCH = "1INCH-A"; + if (keccak256(bytes(_connectors[i])) == keccak256(bytes(_1INCH))) { + swapData = bytes4( + keccak256( + "sell(address,address,uint256,uint256,bytes,uint256)" + ) + ); + } + + bytes memory _data = abi.encodeWithSelector( + swapData, + _inputData.buyAddr, + _inputData.sellAddr, + _inputData.sellAmt, + _inputData.unitAmts[i], + _inputData.callDatas[i], + _inputData.setId + ); + + (success, returnData) = instaConnectors + .connectors(_connectors[i]) + .delegatecall(_data); + if (success) { + _connector = _connectors[i]; + break; + } + } + } + + function decodeEvents(string memory _connector, bytes memory returnData) + internal + view + returns (uint256 _buyAmt, uint256 _sellAmt) + { + (, bytes memory _eventParam) = abi.decode(returnData, (string, bytes)); + if (keccak256(bytes(_connector)) == keccak256(bytes("PARASWAP-A"))) { + (, , _buyAmt, _sellAmt, ) = abi.decode( + _eventParam, + (address, address, uint256, uint256, uint256) + ); + } else { + (, , _buyAmt, _sellAmt, , ) = abi.decode( + _eventParam, + (address, address, uint256, uint256, uint256, uint256) + ); + } + } +} diff --git a/contracts/mainnet/connectors/swap/main.sol b/contracts/mainnet/connectors/swap/main.sol new file mode 100644 index 00000000..494e5281 --- /dev/null +++ b/contracts/mainnet/connectors/swap/main.sol @@ -0,0 +1,78 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; + +/** + * @title Swap. + * @dev Swap integration for DEX Aggregators. + */ + +// import files +import { SwapHelpers } from "./helpers.sol"; +import { Events } from "./events.sol"; + +abstract contract Swap is SwapHelpers, Events { + /** + * @dev Swap ETH/ERC20_Token using dex aggregators. + * @notice Swap tokens from exchanges like 1INCH, 0x etc, with calculation done off-chain. + * @param _connectors The name of the connectors like 1INCH-A, 0x etc, in order of their priority. + * @param buyAddr The address of the token to buy.(For MATIC: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param sellAddr The address of the token to sell.(For MATIC: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) + * @param sellAmt The amount of the token to sell. + * @param unitAmts The amount of buyAmt/sellAmt with slippage for respective DEXs. + * @param callDatas Data from APIs for respective DEXs. + * @param setId ID stores the amount of token brought. + */ + function swap( + string[] memory _connectors, + address buyAddr, + address sellAddr, + uint256 sellAmt, + uint256[] memory unitAmts, + bytes[] calldata callDatas, + uint256 setId + ) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + InputData memory inputData = InputData({ + buyAddr: buyAddr, + sellAddr: sellAddr, + sellAmt: sellAmt, + unitAmts: unitAmts, + callDatas: callDatas, + setId: setId + }); + + ( + bool success, + bytes memory returnData, + string memory _connector + ) = _swap(_connectors, inputData); + + uint256 _buyAmt; + uint256 _sellAmt; + + if (!success) { + revert("swap-failed"); + } else { + (_buyAmt, _sellAmt) = decodeEvents(_connector, returnData); + } + + _eventName = "LogSwap(string,address,address,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode( + _connector, + buyAddr, + sellAddr, + _buyAmt, + _sellAmt, + 0, + setId + ); + } +} + +contract ConnectV2Swap is Swap { + string public name = "Swap-v1"; +} From 11823ff42b10f91d93ee3a7da7762675af046fb8 Mon Sep 17 00:00:00 2001 From: Richa-iitr Date: Sun, 5 Jun 2022 01:13:20 +0530 Subject: [PATCH 07/27] tests-mainnet --- test/mainnet/swap/swap-test.ts | 173 +++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 test/mainnet/swap/swap-test.ts diff --git a/test/mainnet/swap/swap-test.ts b/test/mainnet/swap/swap-test.ts new file mode 100644 index 00000000..1e5145f7 --- /dev/null +++ b/test/mainnet/swap/swap-test.ts @@ -0,0 +1,173 @@ +import hre from "hardhat"; +import axios from "axios"; +import { expect } from "chai"; +const { ethers } = hre; //check +import { BigNumber } from "bignumber.js"; +import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector"; +import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2"; +import { encodeSpells } from "../../../scripts/tests/encodeSpells"; +import { getMasterSigner } from "../../../scripts/tests/getMasterSigner"; +import { addresses } from "../../../scripts/tests/mainnet/addresses"; +import { abis } from "../../../scripts/constant/abis"; +import { ConnectV2Swap__factory } from "../../../typechain"; +import er20abi from "../../../scripts/constant/abi/basics/erc20.json"; +import type { Signer, Contract } from "ethers"; + +describe("Swap | Mainnet", function () { + const connectorName = "swap-test"; + + let dsaWallet0: Contract; + let wallet0: Signer, wallet1: Signer; + let masterSigner: Signer; + let instaConnectorsV2: Contract; + let connector: Contract; + + before(async () => { + await hre.network.provider.request({ + method: "hardhat_reset", + params: [ + { + forking: { + // @ts-ignore + jsonRpcUrl: hre.config.networks.hardhat.forking.url + } + } + ] + }); + [wallet0, wallet1] = await ethers.getSigners(); + + masterSigner = await getMasterSigner(); + instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); + connector = await deployAndEnableConnector({ + connectorName, + contractArtifact: ConnectV2Swap__factory, + signer: masterSigner, + connectors: instaConnectorsV2 + }); + console.log("Connector address", connector.address); + }); + + it("Should have contracts deployed.", async function () { + expect(!!instaConnectorsV2.address).to.be.true; + expect(!!connector.address).to.be.true; + expect(!!(await masterSigner.getAddress())).to.be.true; + }); + + describe("DSA wallet setup", function () { + it("Should build DSA v2", async function () { + dsaWallet0 = await buildDSAv2(await wallet0.getAddress()); + console.log(dsaWallet0.address); + expect(!!dsaWallet0.address).to.be.true; + }); + + it("Deposit matic into DSA wallet", async function () { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: ethers.utils.parseEther("10") + }); + + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); + }); + }); + + describe("Main", function () { + it("should swap the tokens", async function () { + let buyTokenAmountZeroX: any; + let buyTokenAmount1Inch: any; + let buyTokenAmountParaswap: any; + async function getArg() { + // const slippage = 0.5; + /* matic -> usdt */ + const sellTokenAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; // matic, decimals 18 + const sellTokenDecimals = 18; + const buyTokenAddress = "0xdAC17F958D2ee523a2206206994597C13D831ec7"; // USDT, decimals 6 + const buyTokenDecimals = 6; + const amount = 2; + + const srcAmount = new BigNumber(amount).times(new BigNumber(10).pow(sellTokenDecimals)).toFixed(0); + + let zeroXUrl = `https://api.0x.org/swap/v1/quote`; + let paraswapUrl1 = `https://apiv5.paraswap.io/prices/`; + let paraswapUrl2 = `https://apiv5.paraswap.io/transactions/1?ignoreChecks=true`; + + //zeroX + const paramsZeroX = { + buyToken: "USDT", + sellToken: "ETH", + sellAmount: "2000000000000000000" // Always denominated in wei + }; + + const responseZeroX = await axios.get(zeroXUrl, { params: paramsZeroX }).then((data: any) => data); + buyTokenAmountZeroX = responseZeroX.data.buyAmount; + const calldataZeroX = responseZeroX.data.data; + + //paraswap + let paramsPara = { + srcToken: sellTokenAddress, + destToken: buyTokenAddress, + srcDecimals: sellTokenDecimals, + destDecimals: buyTokenDecimals, + amount: srcAmount, + side: "SELL", + network: 1 + }; + + const priceRoute = (await axios.get(paraswapUrl1, { params: paramsPara })).data.priceRoute; + buyTokenAmountParaswap = priceRoute.destAmount; + let minAmount = new BigNumber(priceRoute.destAmount).times((100 - 1) / 100).toFixed(0); + + let txConfig = { + priceRoute: priceRoute, + srcToken: sellTokenAddress, + destToken: buyTokenAddress, + srcDecimals: sellTokenDecimals, + destDecimals: buyTokenDecimals, + srcAmount: srcAmount, + destAmount: minAmount, + userAddress: dsaWallet0.address + }; + const calldataPara = (await axios.post(paraswapUrl2, txConfig)).data.data; + + let calculateUnitAmt = (buyAmount: any) => { + const buyTokenAmountRes = new BigNumber(buyAmount) + .dividedBy(new BigNumber(10).pow(buyTokenDecimals)) + .toFixed(8); + + let unitAmt: any = new BigNumber(buyTokenAmountRes).dividedBy(new BigNumber(amount)); + + unitAmt = unitAmt.multipliedBy((100 - 1) / 100); + unitAmt = unitAmt.multipliedBy(1e18).toFixed(0); + return unitAmt; + }; + let unitAmt0x = calculateUnitAmt(buyTokenAmountZeroX); + let unitAmtParaswap = calculateUnitAmt(buyTokenAmountParaswap); + + let unitAmts = [unitAmt0x, unitAmtParaswap]; + let calldatas = [calldataZeroX, calldataPara]; + + let connectors = ["ZEROX-A", "PARASWAP-A"]; + + return [connectors, buyTokenAddress, sellTokenAddress, srcAmount, unitAmts, calldatas, 0]; + } + + let arg = await getArg(); + const spells = [ + { + connector: connectorName, + method: "swap", + args: arg + } + ]; + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), await wallet1.getAddress()); + const receipt = await tx.wait(); + + const usdtToken = await ethers.getContractAt( + er20abi, + "0xdAC17F958D2ee523a2206206994597C13D831ec7" // dai address + ); + + expect(await usdtToken.balanceOf(dsaWallet0.address)).to.be.gte(buyTokenAmountZeroX); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(ethers.utils.parseEther("9")); + }); + }); +}); From 872e8968a3348e098329dc8be2a7072bf5884c77 Mon Sep 17 00:00:00 2001 From: Richa-iitr Date: Sun, 5 Jun 2022 07:59:38 +0530 Subject: [PATCH 08/27] tests-avalanche --- test/avalanche/swap/swap-test.ts | 174 +++++++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 test/avalanche/swap/swap-test.ts diff --git a/test/avalanche/swap/swap-test.ts b/test/avalanche/swap/swap-test.ts new file mode 100644 index 00000000..35707b62 --- /dev/null +++ b/test/avalanche/swap/swap-test.ts @@ -0,0 +1,174 @@ +import hre from "hardhat"; +import axios from "axios"; +import { expect } from "chai"; +const { ethers } = hre; //check +import { BigNumber } from "bignumber.js"; +import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector"; +import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2"; +import { encodeSpells } from "../../../scripts/tests/encodeSpells"; +import { getMasterSigner } from "../../../scripts/tests/getMasterSigner"; +import { addresses } from "../../../scripts/tests/avalanche/addresses"; +import { abis } from "../../../scripts/constant/abis"; +import { ConnectV2SwapAvalanche__factory } from "../../../typechain"; +import er20abi from "../../../scripts/constant/abi/basics/erc20.json"; +import type { Signer, Contract } from "ethers"; + +describe("Swap | Avalanche", function () { + const connectorName = "swap-test"; + + let dsaWallet0: Contract; + let wallet0: Signer, wallet1: Signer; + let masterSigner: Signer; + let instaConnectorsV2: Contract; + let connector: Contract; + + before(async () => { + await hre.network.provider.request({ + method: "hardhat_reset", + params: [ + { + forking: { + // @ts-ignore + jsonRpcUrl: hre.config.networks.hardhat.forking.url + } + } + ] + }); + [wallet0, wallet1] = await ethers.getSigners(); + + masterSigner = await getMasterSigner(); + instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); + connector = await deployAndEnableConnector({ + connectorName, + contractArtifact: ConnectV2SwapAvalanche__factory, + signer: masterSigner, + connectors: instaConnectorsV2 + }); + console.log("Connector address", connector.address); + }); + + it("Should have contracts deployed.", async function () { + expect(!!instaConnectorsV2.address).to.be.true; + expect(!!connector.address).to.be.true; + expect(!!(await masterSigner.getAddress())).to.be.true; + }); + + describe("DSA wallet setup", function () { + it("Should build DSA v2", async function () { + dsaWallet0 = await buildDSAv2(await wallet0.getAddress()); + console.log(dsaWallet0.address); + expect(!!dsaWallet0.address).to.be.true; + }); + + it("Deposit matic into DSA wallet", async function () { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: ethers.utils.parseEther("10") + }); + + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); + }); + }); + + describe("Main", function () { + it("should swap the tokens", async function () { + let buyTokenAmountZeroX: any; + // let buyTokenAmount1Inch: any; + let buyTokenAmountParaswap: any; + async function getArg() { + // const slippage = 0.5; + /* avax -> usdt */ + const sellTokenAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; // matic, decimals 18 + const sellTokenDecimals = 18; + const buyTokenAddress = "0xd586E7F844cEa2F87f50152665BCbc2C279D8d70"; // USDT, decimals 6 + const buyTokenDecimals = 18; + const amount = 1; + + const srcAmount = new BigNumber(amount).times(new BigNumber(10).pow(sellTokenDecimals)).toFixed(0); + + let zeroXUrl = `https://avalanche.api.0x.org/swap/v1/quote`; + let paraswapUrl1 = `https://apiv5.paraswap.io/prices/`; + let paraswapUrl2 = `https://apiv5.paraswap.io/transactions/43114?ignoreChecks=true`; + + + //paraswap + let paramsPara = { + srcToken: sellTokenAddress, + destToken: buyTokenAddress, + srcDecimals: sellTokenDecimals, + destDecimals: buyTokenDecimals, + amount: srcAmount, + side: "SELL", + network: 43114 + }; + + const priceRoute = (await axios.get(paraswapUrl1, { params: paramsPara })).data.priceRoute; + buyTokenAmountParaswap = priceRoute.destAmount; + let minAmount = new BigNumber(priceRoute.destAmount).times((100 - 1) / 100).toFixed(0); + + let txConfig = { + priceRoute: priceRoute, + srcToken: sellTokenAddress, + destToken: buyTokenAddress, + srcDecimals: sellTokenDecimals, + destDecimals: buyTokenDecimals, + srcAmount: srcAmount, + destAmount: minAmount, + userAddress: dsaWallet0.address + }; + const calldataPara = (await axios.post(paraswapUrl2, txConfig)).data.data; + + // zeroX + const paramsZeroX = { + buyToken: buyTokenAddress, + sellToken: sellTokenAddress, + sellAmount: "1000000000000000000" // Always denominated in wei + }; + + const responseZeroX = await axios.get(zeroXUrl, { params: paramsZeroX }).then((data: any) => data); + buyTokenAmountZeroX = responseZeroX.data.buyAmount; + const calldataZeroX = responseZeroX.data.data; + + let calculateUnitAmt = (buyAmount: any) => { + const buyTokenAmountRes = new BigNumber(buyAmount) + .dividedBy(new BigNumber(10).pow(buyTokenDecimals)) + .toFixed(8); + + let unitAmt: any = new BigNumber(buyTokenAmountRes).dividedBy(new BigNumber(amount)); + + unitAmt = unitAmt.multipliedBy((100 - 1) / 100); + unitAmt = unitAmt.multipliedBy(1e18).toFixed(0); + return unitAmt; + }; + let unitAmt0x = calculateUnitAmt(buyTokenAmountZeroX); + let unitAmtParaswap = calculateUnitAmt(buyTokenAmountParaswap); + + let unitAmts = [ unitAmtParaswap, unitAmt0x]; + let calldatas = [ calldataPara, calldataZeroX]; + + let connectors = ["PARASWAP-A", "ZEROX-A"]; + + return [connectors, buyTokenAddress, sellTokenAddress, srcAmount, unitAmts, calldatas, 0]; + } + + let arg = await getArg(); + const spells = [ + { + connector: connectorName, + method: "swap", + args: arg + } + ]; + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), await wallet1.getAddress()); + const receipt = await tx.wait(); + + const usdtToken = await ethers.getContractAt( + er20abi, + "0xd586E7F844cEa2F87f50152665BCbc2C279D8d70" // usdt address + ); + + expect(await usdtToken.balanceOf(dsaWallet0.address)).to.be.gte(buyTokenAmountZeroX); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(ethers.utils.parseEther("9")); + }); + }); +}); From 51dac79ae931143464c0d620191d68dec9080672 Mon Sep 17 00:00:00 2001 From: Richa-iitr Date: Sun, 5 Jun 2022 08:30:59 +0530 Subject: [PATCH 09/27] minor fix --- test/avalanche/swap/swap-test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/avalanche/swap/swap-test.ts b/test/avalanche/swap/swap-test.ts index 35707b62..6490777b 100644 --- a/test/avalanche/swap/swap-test.ts +++ b/test/avalanche/swap/swap-test.ts @@ -167,7 +167,7 @@ describe("Swap | Avalanche", function () { "0xd586E7F844cEa2F87f50152665BCbc2C279D8d70" // usdt address ); - expect(await usdtToken.balanceOf(dsaWallet0.address)).to.be.gte(buyTokenAmountZeroX); + expect(await usdtToken.balanceOf(dsaWallet0.address)).to.be.gte(buyTokenAmountParaswap); expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(ethers.utils.parseEther("9")); }); }); From 948bf954ecad5ed7dc677897929e0e4b017adaab Mon Sep 17 00:00:00 2001 From: Richa-iitr Date: Sun, 5 Jun 2022 09:42:01 +0530 Subject: [PATCH 10/27] tests update --- test/mainnet/swap/swap-test.ts | 47 ++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/test/mainnet/swap/swap-test.ts b/test/mainnet/swap/swap-test.ts index 1e5145f7..a64c0831 100644 --- a/test/mainnet/swap/swap-test.ts +++ b/test/mainnet/swap/swap-test.ts @@ -76,25 +76,26 @@ describe("Swap | Mainnet", function () { let buyTokenAmount1Inch: any; let buyTokenAmountParaswap: any; async function getArg() { - // const slippage = 0.5; - /* matic -> usdt */ - const sellTokenAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; // matic, decimals 18 + const slippage = 0.5; + /* eth -> dai */ + const sellTokenAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; // eth, decimals 18 const sellTokenDecimals = 18; - const buyTokenAddress = "0xdAC17F958D2ee523a2206206994597C13D831ec7"; // USDT, decimals 6 - const buyTokenDecimals = 6; - const amount = 2; + const buyTokenAddress = "0x6B175474E89094C44Da98b954EedeAC495271d0F"; // DAI, decimals 6 + const buyTokenDecimals = 18; + const amount = 1; const srcAmount = new BigNumber(amount).times(new BigNumber(10).pow(sellTokenDecimals)).toFixed(0); let zeroXUrl = `https://api.0x.org/swap/v1/quote`; + let inchUrl = `https://api.1inch.exchange/v4.0/1/swap`; let paraswapUrl1 = `https://apiv5.paraswap.io/prices/`; let paraswapUrl2 = `https://apiv5.paraswap.io/transactions/1?ignoreChecks=true`; //zeroX const paramsZeroX = { - buyToken: "USDT", + buyToken: "DAI", sellToken: "ETH", - sellAmount: "2000000000000000000" // Always denominated in wei + sellAmount: "1000000000000000000" // Always denominated in wei }; const responseZeroX = await axios.get(zeroXUrl, { params: paramsZeroX }).then((data: any) => data); @@ -128,6 +129,24 @@ describe("Swap | Mainnet", function () { }; const calldataPara = (await axios.post(paraswapUrl2, txConfig)).data.data; + //1inch + const paramDaiUsdc = { + buyToken: buyTokenAddress, + sellToken: sellTokenAddress, + sellAmount: "1000000000000000000", + dsaAddress: dsaWallet0.address + } + const response1 = await axios.get("https://api.instadapp.io/defi/mainnet/1inch/swap", { + params: paramDaiUsdc + }); + + const data1 = response1.data; + // console.log(data1); + let unitAmt1Inch = data1.unitAmt; + const calldata1Inch = data1.calldata; + buyTokenAmount1Inch = data1.buyTokenAmount; + console.log(buyTokenAmount1Inch); + let calculateUnitAmt = (buyAmount: any) => { const buyTokenAmountRes = new BigNumber(buyAmount) .dividedBy(new BigNumber(10).pow(buyTokenDecimals)) @@ -142,10 +161,10 @@ describe("Swap | Mainnet", function () { let unitAmt0x = calculateUnitAmt(buyTokenAmountZeroX); let unitAmtParaswap = calculateUnitAmt(buyTokenAmountParaswap); - let unitAmts = [unitAmt0x, unitAmtParaswap]; - let calldatas = [calldataZeroX, calldataPara]; + let unitAmts = [unitAmt1Inch, unitAmt0x, unitAmtParaswap]; + let calldatas = [calldata1Inch, calldataZeroX, calldataPara]; - let connectors = ["ZEROX-A", "PARASWAP-A"]; + let connectors = ["1INCH-A","ZEROX-A", "PARASWAP-A"]; return [connectors, buyTokenAddress, sellTokenAddress, srcAmount, unitAmts, calldatas, 0]; } @@ -161,12 +180,12 @@ describe("Swap | Mainnet", function () { const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), await wallet1.getAddress()); const receipt = await tx.wait(); - const usdtToken = await ethers.getContractAt( + const daiToken = await ethers.getContractAt( er20abi, - "0xdAC17F958D2ee523a2206206994597C13D831ec7" // dai address + "0x6B175474E89094C44Da98b954EedeAC495271d0F" // dai address ); - expect(await usdtToken.balanceOf(dsaWallet0.address)).to.be.gte(buyTokenAmountZeroX); + expect(await daiToken.balanceOf(dsaWallet0.address)).to.be.gte(buyTokenAmount1Inch); expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(ethers.utils.parseEther("9")); }); }); From 9bc29252c30537e9e84ef3d33d19a0a3e78f11d4 Mon Sep 17 00:00:00 2001 From: Richa-iitr Date: Sun, 5 Jun 2022 09:57:17 +0530 Subject: [PATCH 11/27] linted code --- contracts/avalanche/connectors/swap/events.sol | 2 +- contracts/mainnet/connectors/swap/events.sol | 2 +- contracts/mainnet/connectors/swap/helpers.sol | 2 +- contracts/polygon/connectors/swap/events.sol | 2 +- contracts/polygon/connectors/swap/helpers.sol | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/contracts/avalanche/connectors/swap/events.sol b/contracts/avalanche/connectors/swap/events.sol index 0440abf0..463d3730 100644 --- a/contracts/avalanche/connectors/swap/events.sol +++ b/contracts/avalanche/connectors/swap/events.sol @@ -3,7 +3,7 @@ pragma solidity ^0.7.0; contract Events { event LogSwap( - string _connector, + string _connector, address indexed buyToken, address indexed sellToken, uint256 buyAmt, diff --git a/contracts/mainnet/connectors/swap/events.sol b/contracts/mainnet/connectors/swap/events.sol index 0440abf0..463d3730 100644 --- a/contracts/mainnet/connectors/swap/events.sol +++ b/contracts/mainnet/connectors/swap/events.sol @@ -3,7 +3,7 @@ pragma solidity ^0.7.0; contract Events { event LogSwap( - string _connector, + string _connector, address indexed buyToken, address indexed sellToken, uint256 buyAmt, diff --git a/contracts/mainnet/connectors/swap/helpers.sol b/contracts/mainnet/connectors/swap/helpers.sol index c111767b..f25be85a 100644 --- a/contracts/mainnet/connectors/swap/helpers.sol +++ b/contracts/mainnet/connectors/swap/helpers.sol @@ -45,7 +45,7 @@ contract SwapHelpers is Helper { "callDatas-length-invalid" ); - // require _connectors[i] == "1INCH-A" || "ZEROX-A" || "PARASWAP-A" || similar connectors + // require _connectors[i] == "1INCH-A" || "ZEROX-A" || "PARASWAP-A" || similar connectors for (uint256 i = 0; i < _connectors.length; i++) { bytes4 swapData = bytes4( diff --git a/contracts/polygon/connectors/swap/events.sol b/contracts/polygon/connectors/swap/events.sol index 0440abf0..463d3730 100644 --- a/contracts/polygon/connectors/swap/events.sol +++ b/contracts/polygon/connectors/swap/events.sol @@ -3,7 +3,7 @@ pragma solidity ^0.7.0; contract Events { event LogSwap( - string _connector, + string _connector, address indexed buyToken, address indexed sellToken, uint256 buyAmt, diff --git a/contracts/polygon/connectors/swap/helpers.sol b/contracts/polygon/connectors/swap/helpers.sol index c2b3c67f..40c27b6b 100644 --- a/contracts/polygon/connectors/swap/helpers.sol +++ b/contracts/polygon/connectors/swap/helpers.sol @@ -45,7 +45,7 @@ contract SwapHelpers is Helper { "callDatas-length-invalid" ); - // require _connectors[i] == "1INCH-A" || "ZEROX-A" || "PARASWAP-A" || similar connectors + // require _connectors[i] == "1INCH-A" || "ZEROX-A" || "PARASWAP-A" || similar connectors for (uint256 i = 0; i < _connectors.length; i++) { bytes4 swapData = bytes4( From 8a3fdde8538839ebcb984153c7f63c801dadbe99 Mon Sep 17 00:00:00 2001 From: Richa-iitr Date: Tue, 7 Jun 2022 05:42:03 +0530 Subject: [PATCH 12/27] modified name --- contracts/avalanche/connectors/swap/main.sol | 4 ++-- contracts/mainnet/connectors/swap/main.sol | 4 ++-- contracts/polygon/connectors/swap/main.sol | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/contracts/avalanche/connectors/swap/main.sol b/contracts/avalanche/connectors/swap/main.sol index a25bcbc2..5bb6a6f8 100644 --- a/contracts/avalanche/connectors/swap/main.sol +++ b/contracts/avalanche/connectors/swap/main.sol @@ -73,6 +73,6 @@ abstract contract Swap is SwapHelpers, Events { } } -contract ConnectV2SwapAvalanche is Swap { - string public name = "Swap-v1"; +contract ConnectV2SwapAggregatorAvalanche is Swap { + string public name = "Swap-Aggregator-v1"; } diff --git a/contracts/mainnet/connectors/swap/main.sol b/contracts/mainnet/connectors/swap/main.sol index 494e5281..a6c61cbd 100644 --- a/contracts/mainnet/connectors/swap/main.sol +++ b/contracts/mainnet/connectors/swap/main.sol @@ -73,6 +73,6 @@ abstract contract Swap is SwapHelpers, Events { } } -contract ConnectV2Swap is Swap { - string public name = "Swap-v1"; +contract ConnectV2SwapAggregator is Swap { + string public name = "Swap-Aggregator-v1"; } diff --git a/contracts/polygon/connectors/swap/main.sol b/contracts/polygon/connectors/swap/main.sol index c59f5d9d..93a6d6af 100644 --- a/contracts/polygon/connectors/swap/main.sol +++ b/contracts/polygon/connectors/swap/main.sol @@ -73,6 +73,6 @@ abstract contract Swap is SwapHelpers, Events { } } -contract ConnectV2SwapPolygon is Swap { - string public name = "Swap-v1"; +contract ConnectV2SwapAggregatorPolygon is Swap { + string public name = "Swap-Aggregator-v1"; } From 32429d2b05af17f4e1e1e87ffccf0578e7fdccd4 Mon Sep 17 00:00:00 2001 From: Richa-iitr Date: Wed, 8 Jun 2022 19:20:24 +0530 Subject: [PATCH 13/27] code refactor --- contracts/avalanche/connectors/swap/events.sol | 3 +-- .../avalanche/connectors/swap/helpers.sol | 18 +++++++++--------- contracts/avalanche/connectors/swap/main.sol | 3 +-- contracts/mainnet/connectors/swap/events.sol | 3 +-- contracts/mainnet/connectors/swap/helpers.sol | 17 +++++++---------- contracts/mainnet/connectors/swap/main.sol | 3 +-- contracts/polygon/connectors/swap/events.sol | 3 +-- contracts/polygon/connectors/swap/helpers.sol | 16 +++++++--------- contracts/polygon/connectors/swap/main.sol | 3 +-- test/avalanche/swap/swap-test.ts | 4 ++-- test/mainnet/swap/swap-test.ts | 4 ++-- test/polygon/swap/swap-test.ts | 4 ++-- 12 files changed, 35 insertions(+), 46 deletions(-) diff --git a/contracts/avalanche/connectors/swap/events.sol b/contracts/avalanche/connectors/swap/events.sol index 463d3730..da92aeb2 100644 --- a/contracts/avalanche/connectors/swap/events.sol +++ b/contracts/avalanche/connectors/swap/events.sol @@ -2,13 +2,12 @@ pragma solidity ^0.7.0; contract Events { - event LogSwap( + event LogSwapAggregator( string _connector, address indexed buyToken, address indexed sellToken, uint256 buyAmt, uint256 sellAmt, - uint256 getId, uint256 setId ); } diff --git a/contracts/avalanche/connectors/swap/helpers.sol b/contracts/avalanche/connectors/swap/helpers.sol index 5285982f..c51683b5 100644 --- a/contracts/avalanche/connectors/swap/helpers.sol +++ b/contracts/avalanche/connectors/swap/helpers.sol @@ -4,7 +4,7 @@ pragma abicoder v2; import { InstaConnectors } from "../../common/interfaces.sol"; -abstract contract Helper { +contract SwapHelpers { /** * @dev Instadapp Connectors Registry */ @@ -19,9 +19,7 @@ abstract contract Helper { bytes[] callDatas; uint256 setId; } -} -contract SwapHelpers is Helper { /** *@dev Swap using the dex aggregators. *@param _connectors name of the connectors in preference order. @@ -35,25 +33,27 @@ contract SwapHelpers is Helper { string memory _connector ) { - require(_connectors.length > 0, "zero-length-not-allowed"); + uint256 _length = _connectors.length; + require(_length > 0, "zero-length-not-allowed"); require( - _inputData.unitAmts.length == _connectors.length, + _inputData.unitAmts.length == _length, "unitAmts-length-invalid" ); require( - _inputData.callDatas.length == _connectors.length, + _inputData.callDatas.length == _length, "callDatas-length-invalid" ); // require _connectors[i] == "1INCH-A" || "ZEROX-A" || "PARASWAP-A" || similar connectors - for (uint256 i = 0; i < _connectors.length; i++) { + for (uint256 i = 0; i < _length; i++) { bytes4 swapData = bytes4( keccak256("swap(address,address,uint256,uint256,bytes,uint256)") ); - string memory _1INCH = "1INCH-A"; - if (keccak256(bytes(_connectors[i])) == keccak256(bytes(_1INCH))) { + if ( + keccak256(bytes(_connectors[i])) == keccak256(bytes("1INCH-A")) + ) { swapData = bytes4( keccak256( "sell(address,address,uint256,uint256,bytes,uint256)" diff --git a/contracts/avalanche/connectors/swap/main.sol b/contracts/avalanche/connectors/swap/main.sol index 5bb6a6f8..198b663c 100644 --- a/contracts/avalanche/connectors/swap/main.sol +++ b/contracts/avalanche/connectors/swap/main.sol @@ -60,14 +60,13 @@ abstract contract Swap is SwapHelpers, Events { (_buyAmt, _sellAmt) = decodeEvents(_connector, returnData); } - _eventName = "LogSwap(string,address,address,uint256,uint256,uint256,uint256)"; + _eventName = "LogSwapAggregator(string,address,address,uint256,uint256,uint256)"; _eventParam = abi.encode( _connector, buyAddr, sellAddr, _buyAmt, _sellAmt, - 0, setId ); } diff --git a/contracts/mainnet/connectors/swap/events.sol b/contracts/mainnet/connectors/swap/events.sol index 463d3730..da92aeb2 100644 --- a/contracts/mainnet/connectors/swap/events.sol +++ b/contracts/mainnet/connectors/swap/events.sol @@ -2,13 +2,12 @@ pragma solidity ^0.7.0; contract Events { - event LogSwap( + event LogSwapAggregator( string _connector, address indexed buyToken, address indexed sellToken, uint256 buyAmt, uint256 sellAmt, - uint256 getId, uint256 setId ); } diff --git a/contracts/mainnet/connectors/swap/helpers.sol b/contracts/mainnet/connectors/swap/helpers.sol index f25be85a..1e875145 100644 --- a/contracts/mainnet/connectors/swap/helpers.sol +++ b/contracts/mainnet/connectors/swap/helpers.sol @@ -4,7 +4,7 @@ pragma abicoder v2; import { InstaConnectors } from "../../common/interfaces.sol"; -abstract contract Helper { +contract SwapHelpers { /** * @dev Instadapp Connectors Registry */ @@ -19,9 +19,6 @@ abstract contract Helper { bytes[] callDatas; uint256 setId; } -} - -contract SwapHelpers is Helper { /** *@dev Swap using the dex aggregators. *@param _connectors name of the connectors in preference order. @@ -35,25 +32,25 @@ contract SwapHelpers is Helper { string memory _connector ) { - require(_connectors.length > 0, "zero-length-not-allowed"); + uint256 _length = _connectors.length; + require(_length > 0, "zero-length-not-allowed"); require( - _inputData.unitAmts.length == _connectors.length, + _inputData.unitAmts.length == _length, "unitAmts-length-invalid" ); require( - _inputData.callDatas.length == _connectors.length, + _inputData.callDatas.length == _length, "callDatas-length-invalid" ); // require _connectors[i] == "1INCH-A" || "ZEROX-A" || "PARASWAP-A" || similar connectors - for (uint256 i = 0; i < _connectors.length; i++) { + for (uint256 i = 0; i < _length; i++) { bytes4 swapData = bytes4( keccak256("swap(address,address,uint256,uint256,bytes,uint256)") ); - string memory _1INCH = "1INCH-A"; - if (keccak256(bytes(_connectors[i])) == keccak256(bytes(_1INCH))) { + if (keccak256(bytes(_connectors[i])) == keccak256(bytes("1INCH-A"))) { swapData = bytes4( keccak256( "sell(address,address,uint256,uint256,bytes,uint256)" diff --git a/contracts/mainnet/connectors/swap/main.sol b/contracts/mainnet/connectors/swap/main.sol index a6c61cbd..2f7bda18 100644 --- a/contracts/mainnet/connectors/swap/main.sol +++ b/contracts/mainnet/connectors/swap/main.sol @@ -60,14 +60,13 @@ abstract contract Swap is SwapHelpers, Events { (_buyAmt, _sellAmt) = decodeEvents(_connector, returnData); } - _eventName = "LogSwap(string,address,address,uint256,uint256,uint256,uint256)"; + _eventName = "LogSwapAggregator(string,address,address,uint256,uint256,uint256)"; _eventParam = abi.encode( _connector, buyAddr, sellAddr, _buyAmt, _sellAmt, - 0, setId ); } diff --git a/contracts/polygon/connectors/swap/events.sol b/contracts/polygon/connectors/swap/events.sol index 463d3730..da92aeb2 100644 --- a/contracts/polygon/connectors/swap/events.sol +++ b/contracts/polygon/connectors/swap/events.sol @@ -2,13 +2,12 @@ pragma solidity ^0.7.0; contract Events { - event LogSwap( + event LogSwapAggregator( string _connector, address indexed buyToken, address indexed sellToken, uint256 buyAmt, uint256 sellAmt, - uint256 getId, uint256 setId ); } diff --git a/contracts/polygon/connectors/swap/helpers.sol b/contracts/polygon/connectors/swap/helpers.sol index 40c27b6b..f6729788 100644 --- a/contracts/polygon/connectors/swap/helpers.sol +++ b/contracts/polygon/connectors/swap/helpers.sol @@ -4,7 +4,7 @@ pragma abicoder v2; import { InstaConnectors } from "../../common/interfaces.sol"; -abstract contract Helper { +contract SwapHelpers { /** * @dev Instadapp Connectors Registry */ @@ -19,9 +19,7 @@ abstract contract Helper { bytes[] callDatas; uint256 setId; } -} -contract SwapHelpers is Helper { /** *@dev Swap using the dex aggregators. *@param _connectors name of the connectors in preference order. @@ -35,25 +33,25 @@ contract SwapHelpers is Helper { string memory _connector ) { - require(_connectors.length > 0, "zero-length-not-allowed"); + uint256 _length = _connectors.length; + require(_length > 0, "zero-length-not-allowed"); require( - _inputData.unitAmts.length == _connectors.length, + _inputData.unitAmts.length == _length, "unitAmts-length-invalid" ); require( - _inputData.callDatas.length == _connectors.length, + _inputData.callDatas.length == _length, "callDatas-length-invalid" ); // require _connectors[i] == "1INCH-A" || "ZEROX-A" || "PARASWAP-A" || similar connectors - for (uint256 i = 0; i < _connectors.length; i++) { + for (uint256 i = 0; i < _length; i++) { bytes4 swapData = bytes4( keccak256("swap(address,address,uint256,uint256,bytes,uint256)") ); - string memory _1INCH = "1INCH-A"; - if (keccak256(bytes(_connectors[i])) == keccak256(bytes(_1INCH))) { + if (keccak256(bytes(_connectors[i])) == keccak256(bytes("1INCH-A"))) { swapData = bytes4( keccak256( "sell(address,address,uint256,uint256,bytes,uint256)" diff --git a/contracts/polygon/connectors/swap/main.sol b/contracts/polygon/connectors/swap/main.sol index 93a6d6af..857423dd 100644 --- a/contracts/polygon/connectors/swap/main.sol +++ b/contracts/polygon/connectors/swap/main.sol @@ -60,14 +60,13 @@ abstract contract Swap is SwapHelpers, Events { (_buyAmt, _sellAmt) = decodeEvents(_connector, returnData); } - _eventName = "LogSwap(string,address,address,uint256,uint256,uint256,uint256)"; + _eventName = "LogSwapAggregator(string,address,address,uint256,uint256,uint256)"; _eventParam = abi.encode( _connector, buyAddr, sellAddr, _buyAmt, _sellAmt, - 0, setId ); } diff --git a/test/avalanche/swap/swap-test.ts b/test/avalanche/swap/swap-test.ts index 6490777b..7abcc5c9 100644 --- a/test/avalanche/swap/swap-test.ts +++ b/test/avalanche/swap/swap-test.ts @@ -9,7 +9,7 @@ import { encodeSpells } from "../../../scripts/tests/encodeSpells"; import { getMasterSigner } from "../../../scripts/tests/getMasterSigner"; import { addresses } from "../../../scripts/tests/avalanche/addresses"; import { abis } from "../../../scripts/constant/abis"; -import { ConnectV2SwapAvalanche__factory } from "../../../typechain"; +import { ConnectV2SwapAggregatorAvalanche__factory } from "../../../typechain"; import er20abi from "../../../scripts/constant/abi/basics/erc20.json"; import type { Signer, Contract } from "ethers"; @@ -40,7 +40,7 @@ describe("Swap | Avalanche", function () { instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); connector = await deployAndEnableConnector({ connectorName, - contractArtifact: ConnectV2SwapAvalanche__factory, + contractArtifact: ConnectV2SwapAggregatorAvalanche__factory, signer: masterSigner, connectors: instaConnectorsV2 }); diff --git a/test/mainnet/swap/swap-test.ts b/test/mainnet/swap/swap-test.ts index a64c0831..dde35cf3 100644 --- a/test/mainnet/swap/swap-test.ts +++ b/test/mainnet/swap/swap-test.ts @@ -9,7 +9,7 @@ import { encodeSpells } from "../../../scripts/tests/encodeSpells"; import { getMasterSigner } from "../../../scripts/tests/getMasterSigner"; import { addresses } from "../../../scripts/tests/mainnet/addresses"; import { abis } from "../../../scripts/constant/abis"; -import { ConnectV2Swap__factory } from "../../../typechain"; +import { ConnectV2SwapAggregator__factory } from "../../../typechain"; import er20abi from "../../../scripts/constant/abi/basics/erc20.json"; import type { Signer, Contract } from "ethers"; @@ -40,7 +40,7 @@ describe("Swap | Mainnet", function () { instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); connector = await deployAndEnableConnector({ connectorName, - contractArtifact: ConnectV2Swap__factory, + contractArtifact: ConnectV2SwapAggregator__factory, signer: masterSigner, connectors: instaConnectorsV2 }); diff --git a/test/polygon/swap/swap-test.ts b/test/polygon/swap/swap-test.ts index 80090ea8..25c8bce6 100644 --- a/test/polygon/swap/swap-test.ts +++ b/test/polygon/swap/swap-test.ts @@ -9,7 +9,7 @@ import { encodeSpells } from "../../../scripts/tests/encodeSpells"; import { getMasterSigner } from "../../../scripts/tests/getMasterSigner"; import { addresses } from "../../../scripts/tests/polygon/addresses"; import { abis } from "../../../scripts/constant/abis"; -import { ConnectV2SwapPolygon__factory } from "../../../typechain"; +import { ConnectV2SwapAggregatorPolygon__factory } from "../../../typechain"; import er20abi from "../../../scripts/constant/abi/basics/erc20.json"; import type { Signer, Contract } from "ethers"; @@ -40,7 +40,7 @@ describe("Swap", function () { instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); connector = await deployAndEnableConnector({ connectorName, - contractArtifact: ConnectV2SwapPolygon__factory, + contractArtifact: ConnectV2SwapAggregatorPolygon__factory, signer: masterSigner, connectors: instaConnectorsV2 }); From 8e98da39fd3d3d54188ed8e253d7668d7084cda3 Mon Sep 17 00:00:00 2001 From: Richa-iitr Date: Mon, 13 Jun 2022 14:15:21 +0530 Subject: [PATCH 14/27] minor changes --- contracts/avalanche/connectors/swap/helpers.sol | 17 ++++++++--------- contracts/avalanche/connectors/swap/main.sol | 7 ++----- contracts/mainnet/connectors/swap/helpers.sol | 16 +++++++++------- contracts/mainnet/connectors/swap/main.sol | 7 ++----- contracts/polygon/connectors/swap/helpers.sol | 15 ++++++++------- contracts/polygon/connectors/swap/main.sol | 7 ++----- 6 files changed, 31 insertions(+), 38 deletions(-) diff --git a/contracts/avalanche/connectors/swap/helpers.sol b/contracts/avalanche/connectors/swap/helpers.sol index c51683b5..7b75e2ac 100644 --- a/contracts/avalanche/connectors/swap/helpers.sol +++ b/contracts/avalanche/connectors/swap/helpers.sol @@ -47,19 +47,18 @@ contract SwapHelpers { // require _connectors[i] == "1INCH-A" || "ZEROX-A" || "PARASWAP-A" || similar connectors for (uint256 i = 0; i < _length; i++) { - bytes4 swapData = bytes4( - keccak256("swap(address,address,uint256,uint256,bytes,uint256)") - ); - - if ( - keccak256(bytes(_connectors[i])) == keccak256(bytes("1INCH-A")) - ) { - swapData = bytes4( + bytes4 swapData = (keccak256(bytes(_connectors[i])) == + keccak256(bytes("1INCH-A"))) + ? bytes4( keccak256( "sell(address,address,uint256,uint256,bytes,uint256)" ) + ) + : bytes4( + keccak256( + "swap(address,address,uint256,uint256,bytes,uint256)" + ) ); - } bytes memory _data = abi.encodeWithSelector( swapData, diff --git a/contracts/avalanche/connectors/swap/main.sol b/contracts/avalanche/connectors/swap/main.sol index 198b663c..327699a8 100644 --- a/contracts/avalanche/connectors/swap/main.sol +++ b/contracts/avalanche/connectors/swap/main.sol @@ -54,11 +54,8 @@ abstract contract Swap is SwapHelpers, Events { uint256 _buyAmt; uint256 _sellAmt; - if (!success) { - revert("swap-failed"); - } else { - (_buyAmt, _sellAmt) = decodeEvents(_connector, returnData); - } + require(success, "swap-Aggregator-failed"); + (_buyAmt, _sellAmt) = decodeEvents(_connector, returnData); _eventName = "LogSwapAggregator(string,address,address,uint256,uint256,uint256)"; _eventParam = abi.encode( diff --git a/contracts/mainnet/connectors/swap/helpers.sol b/contracts/mainnet/connectors/swap/helpers.sol index 1e875145..81219b60 100644 --- a/contracts/mainnet/connectors/swap/helpers.sol +++ b/contracts/mainnet/connectors/swap/helpers.sol @@ -19,6 +19,7 @@ contract SwapHelpers { bytes[] callDatas; uint256 setId; } + /** *@dev Swap using the dex aggregators. *@param _connectors name of the connectors in preference order. @@ -46,17 +47,18 @@ contract SwapHelpers { // require _connectors[i] == "1INCH-A" || "ZEROX-A" || "PARASWAP-A" || similar connectors for (uint256 i = 0; i < _length; i++) { - bytes4 swapData = bytes4( - keccak256("swap(address,address,uint256,uint256,bytes,uint256)") - ); - - if (keccak256(bytes(_connectors[i])) == keccak256(bytes("1INCH-A"))) { - swapData = bytes4( + bytes4 swapData = (keccak256(bytes(_connectors[i])) == + keccak256(bytes("1INCH-A"))) + ? bytes4( keccak256( "sell(address,address,uint256,uint256,bytes,uint256)" ) + ) + : bytes4( + keccak256( + "swap(address,address,uint256,uint256,bytes,uint256)" + ) ); - } bytes memory _data = abi.encodeWithSelector( swapData, diff --git a/contracts/mainnet/connectors/swap/main.sol b/contracts/mainnet/connectors/swap/main.sol index 2f7bda18..6a25f3ae 100644 --- a/contracts/mainnet/connectors/swap/main.sol +++ b/contracts/mainnet/connectors/swap/main.sol @@ -54,11 +54,8 @@ abstract contract Swap is SwapHelpers, Events { uint256 _buyAmt; uint256 _sellAmt; - if (!success) { - revert("swap-failed"); - } else { - (_buyAmt, _sellAmt) = decodeEvents(_connector, returnData); - } + require(success, "swap-Aggregator-failed"); + (_buyAmt, _sellAmt) = decodeEvents(_connector, returnData); _eventName = "LogSwapAggregator(string,address,address,uint256,uint256,uint256)"; _eventParam = abi.encode( diff --git a/contracts/polygon/connectors/swap/helpers.sol b/contracts/polygon/connectors/swap/helpers.sol index f6729788..f25fc44b 100644 --- a/contracts/polygon/connectors/swap/helpers.sol +++ b/contracts/polygon/connectors/swap/helpers.sol @@ -47,17 +47,18 @@ contract SwapHelpers { // require _connectors[i] == "1INCH-A" || "ZEROX-A" || "PARASWAP-A" || similar connectors for (uint256 i = 0; i < _length; i++) { - bytes4 swapData = bytes4( - keccak256("swap(address,address,uint256,uint256,bytes,uint256)") - ); - - if (keccak256(bytes(_connectors[i])) == keccak256(bytes("1INCH-A"))) { - swapData = bytes4( + bytes4 swapData = (keccak256(bytes(_connectors[i])) == + keccak256(bytes("1INCH-A"))) + ? bytes4( keccak256( "sell(address,address,uint256,uint256,bytes,uint256)" ) + ) + : bytes4( + keccak256( + "swap(address,address,uint256,uint256,bytes,uint256)" + ) ); - } bytes memory _data = abi.encodeWithSelector( swapData, diff --git a/contracts/polygon/connectors/swap/main.sol b/contracts/polygon/connectors/swap/main.sol index 857423dd..6f33f846 100644 --- a/contracts/polygon/connectors/swap/main.sol +++ b/contracts/polygon/connectors/swap/main.sol @@ -54,11 +54,8 @@ abstract contract Swap is SwapHelpers, Events { uint256 _buyAmt; uint256 _sellAmt; - if (!success) { - revert("swap-failed"); - } else { - (_buyAmt, _sellAmt) = decodeEvents(_connector, returnData); - } + require(success, "swap-Aggregator-failed"); + (_buyAmt, _sellAmt) = decodeEvents(_connector, returnData); _eventName = "LogSwapAggregator(string,address,address,uint256,uint256,uint256)"; _eventParam = abi.encode( From 77caa8df6620fd29baf98fb8d301f273237e81e7 Mon Sep 17 00:00:00 2001 From: Richa-iitr Date: Tue, 14 Jun 2022 08:42:15 +0530 Subject: [PATCH 15/27] updated code --- .../avalanche/connectors/swap/helpers.sol | 46 +++------------ contracts/avalanche/connectors/swap/main.sol | 26 ++------- contracts/mainnet/connectors/swap/helpers.sol | 46 +++------------ contracts/mainnet/connectors/swap/main.sol | 26 ++------- contracts/polygon/connectors/swap/helpers.sol | 47 +++------------- contracts/polygon/connectors/swap/main.sol | 26 ++------- test/avalanche/swap/swap-test.ts | 29 ++++++++-- test/mainnet/swap/swap-test.ts | 56 +++++++++++++------ test/polygon/swap/swap-test.ts | 29 ++++++++-- 9 files changed, 126 insertions(+), 205 deletions(-) diff --git a/contracts/avalanche/connectors/swap/helpers.sol b/contracts/avalanche/connectors/swap/helpers.sol index 7b75e2ac..3d7b291b 100644 --- a/contracts/avalanche/connectors/swap/helpers.sol +++ b/contracts/avalanche/connectors/swap/helpers.sol @@ -16,6 +16,7 @@ contract SwapHelpers { address sellAddr; uint256 sellAmt; uint256[] unitAmts; + bytes4[] swapDatas; bytes[] callDatas; uint256 setId; } @@ -27,11 +28,7 @@ contract SwapHelpers { */ function _swap(string[] memory _connectors, InputData memory _inputData) internal - returns ( - bool success, - bytes memory returnData, - string memory _connector - ) + returns (bool success, bytes memory returnData) { uint256 _length = _connectors.length; require(_length > 0, "zero-length-not-allowed"); @@ -43,25 +40,16 @@ contract SwapHelpers { _inputData.callDatas.length == _length, "callDatas-length-invalid" ); + require( + _inputData.swapDatas.length == _length, + "swapDatas-length-invalid" + ); // require _connectors[i] == "1INCH-A" || "ZEROX-A" || "PARASWAP-A" || similar connectors for (uint256 i = 0; i < _length; i++) { - bytes4 swapData = (keccak256(bytes(_connectors[i])) == - keccak256(bytes("1INCH-A"))) - ? bytes4( - keccak256( - "sell(address,address,uint256,uint256,bytes,uint256)" - ) - ) - : bytes4( - keccak256( - "swap(address,address,uint256,uint256,bytes,uint256)" - ) - ); - bytes memory _data = abi.encodeWithSelector( - swapData, + _inputData.swapDatas[i], _inputData.buyAddr, _inputData.sellAddr, _inputData.sellAmt, @@ -74,28 +62,8 @@ contract SwapHelpers { .connectors(_connectors[i]) .delegatecall(_data); if (success) { - _connector = _connectors[i]; break; } } } - - function decodeEvents(string memory _connector, bytes memory returnData) - internal - view - returns (uint256 _buyAmt, uint256 _sellAmt) - { - (, bytes memory _eventParam) = abi.decode(returnData, (string, bytes)); - if (keccak256(bytes(_connector)) == keccak256(bytes("PARASWAP-A"))) { - (, , _buyAmt, _sellAmt, ) = abi.decode( - _eventParam, - (address, address, uint256, uint256, uint256) - ); - } else { - (, , _buyAmt, _sellAmt, , ) = abi.decode( - _eventParam, - (address, address, uint256, uint256, uint256, uint256) - ); - } - } } diff --git a/contracts/avalanche/connectors/swap/main.sol b/contracts/avalanche/connectors/swap/main.sol index 327699a8..452d1085 100644 --- a/contracts/avalanche/connectors/swap/main.sol +++ b/contracts/avalanche/connectors/swap/main.sol @@ -20,16 +20,18 @@ abstract contract Swap is SwapHelpers, Events { * @param sellAddr The address of the token to sell.(For MATIC: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) * @param sellAmt The amount of the token to sell. * @param unitAmts The amount of buyAmt/sellAmt with slippage for respective DEXs. + * @param swapDatas The function selectors of swap methods of the DEXs. * @param callDatas Data from APIs for respective DEXs. * @param setId ID stores the amount of token brought. */ function swap( - string[] memory _connectors, address buyAddr, address sellAddr, uint256 sellAmt, uint256[] memory unitAmts, + bytes4[] memory swapDatas, bytes[] calldata callDatas, + string[] memory _connectors, uint256 setId ) external @@ -41,31 +43,15 @@ abstract contract Swap is SwapHelpers, Events { sellAddr: sellAddr, sellAmt: sellAmt, unitAmts: unitAmts, + swapDatas: swapDatas, callDatas: callDatas, setId: setId }); - ( - bool success, - bytes memory returnData, - string memory _connector - ) = _swap(_connectors, inputData); - - uint256 _buyAmt; - uint256 _sellAmt; + (bool success, bytes memory returnData) = _swap(_connectors, inputData); require(success, "swap-Aggregator-failed"); - (_buyAmt, _sellAmt) = decodeEvents(_connector, returnData); - - _eventName = "LogSwapAggregator(string,address,address,uint256,uint256,uint256)"; - _eventParam = abi.encode( - _connector, - buyAddr, - sellAddr, - _buyAmt, - _sellAmt, - setId - ); + (_eventName, _eventParam) = abi.decode(returnData, (string, bytes)); } } diff --git a/contracts/mainnet/connectors/swap/helpers.sol b/contracts/mainnet/connectors/swap/helpers.sol index 81219b60..890ae9c0 100644 --- a/contracts/mainnet/connectors/swap/helpers.sol +++ b/contracts/mainnet/connectors/swap/helpers.sol @@ -16,6 +16,7 @@ contract SwapHelpers { address sellAddr; uint256 sellAmt; uint256[] unitAmts; + bytes4[] swapDatas; bytes[] callDatas; uint256 setId; } @@ -27,11 +28,7 @@ contract SwapHelpers { */ function _swap(string[] memory _connectors, InputData memory _inputData) internal - returns ( - bool success, - bytes memory returnData, - string memory _connector - ) + returns (bool success, bytes memory returnData) { uint256 _length = _connectors.length; require(_length > 0, "zero-length-not-allowed"); @@ -43,25 +40,16 @@ contract SwapHelpers { _inputData.callDatas.length == _length, "callDatas-length-invalid" ); + require( + _inputData.swapDatas.length == _length, + "swapDatas-length-invalid" + ); // require _connectors[i] == "1INCH-A" || "ZEROX-A" || "PARASWAP-A" || similar connectors for (uint256 i = 0; i < _length; i++) { - bytes4 swapData = (keccak256(bytes(_connectors[i])) == - keccak256(bytes("1INCH-A"))) - ? bytes4( - keccak256( - "sell(address,address,uint256,uint256,bytes,uint256)" - ) - ) - : bytes4( - keccak256( - "swap(address,address,uint256,uint256,bytes,uint256)" - ) - ); - bytes memory _data = abi.encodeWithSelector( - swapData, + _inputData.swapDatas[i], _inputData.buyAddr, _inputData.sellAddr, _inputData.sellAmt, @@ -74,28 +62,8 @@ contract SwapHelpers { .connectors(_connectors[i]) .delegatecall(_data); if (success) { - _connector = _connectors[i]; break; } } } - - function decodeEvents(string memory _connector, bytes memory returnData) - internal - view - returns (uint256 _buyAmt, uint256 _sellAmt) - { - (, bytes memory _eventParam) = abi.decode(returnData, (string, bytes)); - if (keccak256(bytes(_connector)) == keccak256(bytes("PARASWAP-A"))) { - (, , _buyAmt, _sellAmt, ) = abi.decode( - _eventParam, - (address, address, uint256, uint256, uint256) - ); - } else { - (, , _buyAmt, _sellAmt, , ) = abi.decode( - _eventParam, - (address, address, uint256, uint256, uint256, uint256) - ); - } - } } diff --git a/contracts/mainnet/connectors/swap/main.sol b/contracts/mainnet/connectors/swap/main.sol index 6a25f3ae..3f209a3d 100644 --- a/contracts/mainnet/connectors/swap/main.sol +++ b/contracts/mainnet/connectors/swap/main.sol @@ -20,16 +20,18 @@ abstract contract Swap is SwapHelpers, Events { * @param sellAddr The address of the token to sell.(For MATIC: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) * @param sellAmt The amount of the token to sell. * @param unitAmts The amount of buyAmt/sellAmt with slippage for respective DEXs. + * @param swapDatas The function selectors of swap methods of the DEXs. * @param callDatas Data from APIs for respective DEXs. * @param setId ID stores the amount of token brought. */ function swap( - string[] memory _connectors, address buyAddr, address sellAddr, uint256 sellAmt, uint256[] memory unitAmts, + bytes4[] memory swapDatas, bytes[] calldata callDatas, + string[] memory _connectors, uint256 setId ) external @@ -41,31 +43,15 @@ abstract contract Swap is SwapHelpers, Events { sellAddr: sellAddr, sellAmt: sellAmt, unitAmts: unitAmts, + swapDatas: swapDatas, callDatas: callDatas, setId: setId }); - ( - bool success, - bytes memory returnData, - string memory _connector - ) = _swap(_connectors, inputData); - - uint256 _buyAmt; - uint256 _sellAmt; + (bool success, bytes memory returnData) = _swap(_connectors, inputData); require(success, "swap-Aggregator-failed"); - (_buyAmt, _sellAmt) = decodeEvents(_connector, returnData); - - _eventName = "LogSwapAggregator(string,address,address,uint256,uint256,uint256)"; - _eventParam = abi.encode( - _connector, - buyAddr, - sellAddr, - _buyAmt, - _sellAmt, - setId - ); + (_eventName, _eventParam) = abi.decode(returnData, (string, bytes)); } } diff --git a/contracts/polygon/connectors/swap/helpers.sol b/contracts/polygon/connectors/swap/helpers.sol index f25fc44b..26e99514 100644 --- a/contracts/polygon/connectors/swap/helpers.sol +++ b/contracts/polygon/connectors/swap/helpers.sol @@ -16,6 +16,7 @@ contract SwapHelpers { address sellAddr; uint256 sellAmt; uint256[] unitAmts; + bytes4[] swapDatas; bytes[] callDatas; uint256 setId; } @@ -27,11 +28,7 @@ contract SwapHelpers { */ function _swap(string[] memory _connectors, InputData memory _inputData) internal - returns ( - bool success, - bytes memory returnData, - string memory _connector - ) + returns (bool success, bytes memory returnData) { uint256 _length = _connectors.length; require(_length > 0, "zero-length-not-allowed"); @@ -43,25 +40,16 @@ contract SwapHelpers { _inputData.callDatas.length == _length, "callDatas-length-invalid" ); + require( + _inputData.swapDatas.length == _length, + "swapDatas-length-invalid" + ); // require _connectors[i] == "1INCH-A" || "ZEROX-A" || "PARASWAP-A" || similar connectors for (uint256 i = 0; i < _length; i++) { - bytes4 swapData = (keccak256(bytes(_connectors[i])) == - keccak256(bytes("1INCH-A"))) - ? bytes4( - keccak256( - "sell(address,address,uint256,uint256,bytes,uint256)" - ) - ) - : bytes4( - keccak256( - "swap(address,address,uint256,uint256,bytes,uint256)" - ) - ); - bytes memory _data = abi.encodeWithSelector( - swapData, + _inputData.swapDatas[i], _inputData.buyAddr, _inputData.sellAddr, _inputData.sellAmt, @@ -73,30 +61,9 @@ contract SwapHelpers { (success, returnData) = instaConnectors .connectors(_connectors[i]) .delegatecall(_data); - if (success) { - _connector = _connectors[i]; break; } } } - - function decodeEvents(string memory _connector, bytes memory returnData) - internal - view - returns (uint256 _buyAmt, uint256 _sellAmt) - { - (, bytes memory _eventParam) = abi.decode(returnData, (string, bytes)); - if (keccak256(bytes(_connector)) == keccak256(bytes("PARASWAP-A"))) { - (, , _buyAmt, _sellAmt, ) = abi.decode( - _eventParam, - (address, address, uint256, uint256, uint256) - ); - } else { - (, , _buyAmt, _sellAmt, , ) = abi.decode( - _eventParam, - (address, address, uint256, uint256, uint256, uint256) - ); - } - } } diff --git a/contracts/polygon/connectors/swap/main.sol b/contracts/polygon/connectors/swap/main.sol index 6f33f846..24251a72 100644 --- a/contracts/polygon/connectors/swap/main.sol +++ b/contracts/polygon/connectors/swap/main.sol @@ -20,16 +20,18 @@ abstract contract Swap is SwapHelpers, Events { * @param sellAddr The address of the token to sell.(For MATIC: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) * @param sellAmt The amount of the token to sell. * @param unitAmts The amount of buyAmt/sellAmt with slippage for respective DEXs. + * @param swapDatas The function selectors of swap methods of the DEXs. * @param callDatas Data from APIs for respective DEXs. * @param setId ID stores the amount of token brought. */ function swap( - string[] memory _connectors, address buyAddr, address sellAddr, uint256 sellAmt, uint256[] memory unitAmts, + bytes4[] memory swapDatas, bytes[] calldata callDatas, + string[] memory _connectors, uint256 setId ) external @@ -41,31 +43,15 @@ abstract contract Swap is SwapHelpers, Events { sellAddr: sellAddr, sellAmt: sellAmt, unitAmts: unitAmts, + swapDatas: swapDatas, callDatas: callDatas, setId: setId }); - ( - bool success, - bytes memory returnData, - string memory _connector - ) = _swap(_connectors, inputData); - - uint256 _buyAmt; - uint256 _sellAmt; + (bool success, bytes memory returnData) = _swap(_connectors, inputData); require(success, "swap-Aggregator-failed"); - (_buyAmt, _sellAmt) = decodeEvents(_connector, returnData); - - _eventName = "LogSwapAggregator(string,address,address,uint256,uint256,uint256)"; - _eventParam = abi.encode( - _connector, - buyAddr, - sellAddr, - _buyAmt, - _sellAmt, - setId - ); + (_eventName, _eventParam) = abi.decode(returnData, (string, bytes)); } } diff --git a/test/avalanche/swap/swap-test.ts b/test/avalanche/swap/swap-test.ts index 7abcc5c9..a1f74a5d 100644 --- a/test/avalanche/swap/swap-test.ts +++ b/test/avalanche/swap/swap-test.ts @@ -75,6 +75,22 @@ describe("Swap | Avalanche", function () { let buyTokenAmountZeroX: any; // let buyTokenAmount1Inch: any; let buyTokenAmountParaswap: any; + + async function getSelector(connector: string) { + var abi = [ + "function swap(address,address,uint256,uint256,bytes,uint256)", + "function sell(address,address,uint256,uint256,bytes,uint256)" + ]; + var iface = new ethers.utils.Interface(abi); + var id; + if (connector == "1INCH-A") { + id = iface.getSighash("sell"); + } else { + id = iface.getSighash("swap"); + } + + return id; + } async function getArg() { // const slippage = 0.5; /* avax -> usdt */ @@ -90,7 +106,6 @@ describe("Swap | Avalanche", function () { let paraswapUrl1 = `https://apiv5.paraswap.io/prices/`; let paraswapUrl2 = `https://apiv5.paraswap.io/transactions/43114?ignoreChecks=true`; - //paraswap let paramsPara = { srcToken: sellTokenAddress, @@ -117,7 +132,7 @@ describe("Swap | Avalanche", function () { userAddress: dsaWallet0.address }; const calldataPara = (await axios.post(paraswapUrl2, txConfig)).data.data; - + // zeroX const paramsZeroX = { buyToken: buyTokenAddress, @@ -142,13 +157,15 @@ describe("Swap | Avalanche", function () { }; let unitAmt0x = calculateUnitAmt(buyTokenAmountZeroX); let unitAmtParaswap = calculateUnitAmt(buyTokenAmountParaswap); - - let unitAmts = [ unitAmtParaswap, unitAmt0x]; - let calldatas = [ calldataPara, calldataZeroX]; + let swapDataPara = ethers.utils.hexlify(await getSelector("PARASWAP-A")); + let swapDataZeroX = ethers.utils.hexlify(await getSelector("ZEROX-A")); + let unitAmts = [unitAmtParaswap, unitAmt0x]; + let calldatas = [calldataPara, calldataZeroX]; + let swapDatas = [swapDataPara, swapDataZeroX]; let connectors = ["PARASWAP-A", "ZEROX-A"]; - return [connectors, buyTokenAddress, sellTokenAddress, srcAmount, unitAmts, calldatas, 0]; + return [buyTokenAddress, sellTokenAddress, srcAmount, unitAmts, swapDatas, calldatas, connectors, 0]; } let arg = await getArg(); diff --git a/test/mainnet/swap/swap-test.ts b/test/mainnet/swap/swap-test.ts index dde35cf3..eef0ea7c 100644 --- a/test/mainnet/swap/swap-test.ts +++ b/test/mainnet/swap/swap-test.ts @@ -75,6 +75,23 @@ describe("Swap | Mainnet", function () { let buyTokenAmountZeroX: any; let buyTokenAmount1Inch: any; let buyTokenAmountParaswap: any; + + async function getSelector(connector: string) { + var abi = [ + "function swap(address,address,uint256,uint256,bytes,uint256)", + "function sell(address,address,uint256,uint256,bytes,uint256)" + ]; + var iface = new ethers.utils.Interface(abi); + var id; + if (connector == "1INCH-A") { + id = iface.getSighash("sell"); + } else { + id = iface.getSighash("swap"); + } + + return id; + } + async function getArg() { const slippage = 0.5; /* eth -> dai */ @@ -131,21 +148,21 @@ describe("Swap | Mainnet", function () { //1inch const paramDaiUsdc = { - buyToken: buyTokenAddress, - sellToken: sellTokenAddress, - sellAmount: "1000000000000000000", - dsaAddress: dsaWallet0.address - } - const response1 = await axios.get("https://api.instadapp.io/defi/mainnet/1inch/swap", { - params: paramDaiUsdc - }); - - const data1 = response1.data; - // console.log(data1); - let unitAmt1Inch = data1.unitAmt; - const calldata1Inch = data1.calldata; - buyTokenAmount1Inch = data1.buyTokenAmount; - console.log(buyTokenAmount1Inch); + buyToken: buyTokenAddress, + sellToken: sellTokenAddress, + sellAmount: "1000000000000000000", + dsaAddress: dsaWallet0.address + }; + const response1 = await axios.get("https://api.instadapp.io/defi/mainnet/1inch/swap", { + params: paramDaiUsdc + }); + + const data1 = response1.data; + // console.log(data1); + let unitAmt1Inch = data1.unitAmt; + const calldata1Inch = data1.calldata; + buyTokenAmount1Inch = data1.buyTokenAmount; + console.log(buyTokenAmount1Inch); let calculateUnitAmt = (buyAmount: any) => { const buyTokenAmountRes = new BigNumber(buyAmount) @@ -161,12 +178,17 @@ describe("Swap | Mainnet", function () { let unitAmt0x = calculateUnitAmt(buyTokenAmountZeroX); let unitAmtParaswap = calculateUnitAmt(buyTokenAmountParaswap); + let swapDataPara = ethers.utils.hexlify(await getSelector("PARASWAP-A")); + let swapDataZeroX = ethers.utils.hexlify(await getSelector("ZEROX-A")); + let swapData1Inch = ethers.utils.hexlify(await getSelector("1INCH-A")); + let unitAmts = [unitAmt1Inch, unitAmt0x, unitAmtParaswap]; let calldatas = [calldata1Inch, calldataZeroX, calldataPara]; + let swapDatas = [swapData1Inch, swapDataZeroX, swapDataPara]; - let connectors = ["1INCH-A","ZEROX-A", "PARASWAP-A"]; + let connectors = ["1INCH-A", "ZEROX-A", "PARASWAP-A"]; - return [connectors, buyTokenAddress, sellTokenAddress, srcAmount, unitAmts, calldatas, 0]; + return [buyTokenAddress, sellTokenAddress, srcAmount, unitAmts, swapDatas, calldatas, connectors, 0]; } let arg = await getArg(); diff --git a/test/polygon/swap/swap-test.ts b/test/polygon/swap/swap-test.ts index 25c8bce6..0abbd569 100644 --- a/test/polygon/swap/swap-test.ts +++ b/test/polygon/swap/swap-test.ts @@ -63,7 +63,7 @@ describe("Swap", function () { it("Deposit matic into DSA wallet", async function () { await wallet0.sendTransaction({ to: dsaWallet0.address, - value: ethers.utils.parseEther("10") + value: ethers.utils.parseEther("50") }); expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); @@ -75,6 +75,23 @@ describe("Swap", function () { let buyTokenAmountZeroX: any; let buyTokenAmount1Inch: any; let buyTokenAmountParaswap: any; + + async function getSelector(connector: string) { + var abi = [ + "function swap(address,address,uint256,uint256,bytes,uint256)", + "function sell(address,address,uint256,uint256,bytes,uint256)" + ]; + var iface = new ethers.utils.Interface(abi); + var id; + if (connector == "1INCH-A") { + id = iface.getSighash("sell"); + } else { + id = iface.getSighash("swap"); + } + + return id; + } + async function getArg() { // const slippage = 0.5; /* matic -> usdt */ @@ -82,7 +99,7 @@ describe("Swap", function () { const sellTokenDecimals = 18; const buyTokenAddress = "0xc2132d05d31c914a87c6611c10748aeb04b58e8f"; // USDT, decimals 6 const buyTokenDecimals = 6; - const amount = 2; + const amount = 1; const srcAmount = new BigNumber(amount).times(new BigNumber(10).pow(sellTokenDecimals)).toFixed(0); @@ -94,7 +111,7 @@ describe("Swap", function () { const paramsZeroX = { buyToken: "USDT", sellToken: "MATIC", - sellAmount: "2000000000000000000" // Always denominated in wei + sellAmount: "1000000000000000000" // Always denominated in wei }; const responseZeroX = await axios.get(zeroXUrl, { params: paramsZeroX }).then((data: any) => data); @@ -142,12 +159,16 @@ describe("Swap", function () { let unitAmt0x = calculateUnitAmt(buyTokenAmountZeroX); let unitAmtParaswap = calculateUnitAmt(buyTokenAmountParaswap); + let swapDataPara = ethers.utils.hexlify(await getSelector("PARASWAP-A")); + let swapDataZeroX = ethers.utils.hexlify(await getSelector("ZEROX-A")); + let unitAmts = [unitAmt0x, unitAmtParaswap]; let calldatas = [calldataZeroX, calldataPara]; + let swapDatas = [swapDataZeroX, swapDataPara]; let connectors = ["ZEROX-A", "PARASWAP-A"]; - return [connectors, buyTokenAddress, sellTokenAddress, srcAmount, unitAmts, calldatas, 0]; + return [buyTokenAddress, sellTokenAddress, srcAmount, unitAmts, swapDatas, calldatas, connectors, 0]; } let arg = await getArg(); From c650bc0392bde4268299f737b8e4344d24c81893 Mon Sep 17 00:00:00 2001 From: Richa-iitr Date: Tue, 14 Jun 2022 09:29:01 +0530 Subject: [PATCH 16/27] updated events --- contracts/avalanche/connectors/swap/events.sol | 13 ------------- contracts/avalanche/connectors/swap/main.sol | 3 +-- contracts/mainnet/connectors/swap/events.sol | 13 ------------- contracts/mainnet/connectors/swap/main.sol | 3 +-- contracts/polygon/connectors/swap/events.sol | 13 ------------- contracts/polygon/connectors/swap/main.sol | 3 +-- 6 files changed, 3 insertions(+), 45 deletions(-) delete mode 100644 contracts/avalanche/connectors/swap/events.sol delete mode 100644 contracts/mainnet/connectors/swap/events.sol delete mode 100644 contracts/polygon/connectors/swap/events.sol diff --git a/contracts/avalanche/connectors/swap/events.sol b/contracts/avalanche/connectors/swap/events.sol deleted file mode 100644 index da92aeb2..00000000 --- a/contracts/avalanche/connectors/swap/events.sol +++ /dev/null @@ -1,13 +0,0 @@ -//SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -contract Events { - event LogSwapAggregator( - string _connector, - address indexed buyToken, - address indexed sellToken, - uint256 buyAmt, - uint256 sellAmt, - uint256 setId - ); -} diff --git a/contracts/avalanche/connectors/swap/main.sol b/contracts/avalanche/connectors/swap/main.sol index 452d1085..0cfa98ef 100644 --- a/contracts/avalanche/connectors/swap/main.sol +++ b/contracts/avalanche/connectors/swap/main.sol @@ -9,9 +9,8 @@ pragma experimental ABIEncoderV2; // import files import { SwapHelpers } from "./helpers.sol"; -import { Events } from "./events.sol"; -abstract contract Swap is SwapHelpers, Events { +abstract contract Swap is SwapHelpers { /** * @dev Swap ETH/ERC20_Token using dex aggregators. * @notice Swap tokens from exchanges like 1INCH, 0x etc, with calculation done off-chain. diff --git a/contracts/mainnet/connectors/swap/events.sol b/contracts/mainnet/connectors/swap/events.sol deleted file mode 100644 index da92aeb2..00000000 --- a/contracts/mainnet/connectors/swap/events.sol +++ /dev/null @@ -1,13 +0,0 @@ -//SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -contract Events { - event LogSwapAggregator( - string _connector, - address indexed buyToken, - address indexed sellToken, - uint256 buyAmt, - uint256 sellAmt, - uint256 setId - ); -} diff --git a/contracts/mainnet/connectors/swap/main.sol b/contracts/mainnet/connectors/swap/main.sol index 3f209a3d..a76c2432 100644 --- a/contracts/mainnet/connectors/swap/main.sol +++ b/contracts/mainnet/connectors/swap/main.sol @@ -9,9 +9,8 @@ pragma experimental ABIEncoderV2; // import files import { SwapHelpers } from "./helpers.sol"; -import { Events } from "./events.sol"; -abstract contract Swap is SwapHelpers, Events { +abstract contract Swap is SwapHelpers { /** * @dev Swap ETH/ERC20_Token using dex aggregators. * @notice Swap tokens from exchanges like 1INCH, 0x etc, with calculation done off-chain. diff --git a/contracts/polygon/connectors/swap/events.sol b/contracts/polygon/connectors/swap/events.sol deleted file mode 100644 index da92aeb2..00000000 --- a/contracts/polygon/connectors/swap/events.sol +++ /dev/null @@ -1,13 +0,0 @@ -//SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -contract Events { - event LogSwapAggregator( - string _connector, - address indexed buyToken, - address indexed sellToken, - uint256 buyAmt, - uint256 sellAmt, - uint256 setId - ); -} diff --git a/contracts/polygon/connectors/swap/main.sol b/contracts/polygon/connectors/swap/main.sol index 24251a72..ada14dc6 100644 --- a/contracts/polygon/connectors/swap/main.sol +++ b/contracts/polygon/connectors/swap/main.sol @@ -9,9 +9,8 @@ pragma experimental ABIEncoderV2; // import files import { SwapHelpers } from "./helpers.sol"; -import { Events } from "./events.sol"; -abstract contract Swap is SwapHelpers, Events { +abstract contract Swap is SwapHelpers { /** * @dev Swap ETH/ERC20_Token using dex aggregators. * @notice Swap tokens from exchanges like 1INCH, 0x etc, with calculation done off-chain. From f6fbe8614da6c6b815bb37bb6776cbc77deffea2 Mon Sep 17 00:00:00 2001 From: Richa-iitr Date: Tue, 14 Jun 2022 13:12:10 +0530 Subject: [PATCH 17/27] calldata as param --- .../avalanche/connectors/swap/helpers.sol | 41 ++----------- contracts/avalanche/connectors/swap/main.sol | 28 +-------- contracts/mainnet/connectors/swap/helpers.sol | 41 ++----------- contracts/mainnet/connectors/swap/main.sol | 31 +--------- contracts/polygon/connectors/swap/helpers.sol | 41 ++----------- contracts/polygon/connectors/swap/main.sol | 31 +--------- test/avalanche/swap/swap-test.ts | 57 +++++++++++------- test/mainnet/swap/swap-test.ts | 59 +++++++++++-------- test/polygon/swap/swap-test.ts | 41 ++++++++++--- 9 files changed, 125 insertions(+), 245 deletions(-) diff --git a/contracts/avalanche/connectors/swap/helpers.sol b/contracts/avalanche/connectors/swap/helpers.sol index 3d7b291b..7775be61 100644 --- a/contracts/avalanche/connectors/swap/helpers.sol +++ b/contracts/avalanche/connectors/swap/helpers.sol @@ -11,56 +11,23 @@ contract SwapHelpers { InstaConnectors internal constant instaConnectors = InstaConnectors(0x127d8cD0E2b2E0366D522DeA53A787bfE9002C14); - struct InputData { - address buyAddr; - address sellAddr; - uint256 sellAmt; - uint256[] unitAmts; - bytes4[] swapDatas; - bytes[] callDatas; - uint256 setId; - } - /** *@dev Swap using the dex aggregators. *@param _connectors name of the connectors in preference order. - *@param _inputData data for the swap cast. + *@param _data data for the swap cast. */ - function _swap(string[] memory _connectors, InputData memory _inputData) + function _swap(string[] memory _connectors, bytes[] memory _data) internal returns (bool success, bytes memory returnData) { uint256 _length = _connectors.length; require(_length > 0, "zero-length-not-allowed"); - require( - _inputData.unitAmts.length == _length, - "unitAmts-length-invalid" - ); - require( - _inputData.callDatas.length == _length, - "callDatas-length-invalid" - ); - require( - _inputData.swapDatas.length == _length, - "swapDatas-length-invalid" - ); - - // require _connectors[i] == "1INCH-A" || "ZEROX-A" || "PARASWAP-A" || similar connectors + require(_data.length == _length, "calldata-length-invalid"); for (uint256 i = 0; i < _length; i++) { - bytes memory _data = abi.encodeWithSelector( - _inputData.swapDatas[i], - _inputData.buyAddr, - _inputData.sellAddr, - _inputData.sellAmt, - _inputData.unitAmts[i], - _inputData.callDatas[i], - _inputData.setId - ); - (success, returnData) = instaConnectors .connectors(_connectors[i]) - .delegatecall(_data); + .delegatecall(_data[i]); if (success) { break; } diff --git a/contracts/avalanche/connectors/swap/main.sol b/contracts/avalanche/connectors/swap/main.sol index 0cfa98ef..83ce0c26 100644 --- a/contracts/avalanche/connectors/swap/main.sol +++ b/contracts/avalanche/connectors/swap/main.sol @@ -15,39 +15,17 @@ abstract contract Swap is SwapHelpers { * @dev Swap ETH/ERC20_Token using dex aggregators. * @notice Swap tokens from exchanges like 1INCH, 0x etc, with calculation done off-chain. * @param _connectors The name of the connectors like 1INCH-A, 0x etc, in order of their priority. - * @param buyAddr The address of the token to buy.(For MATIC: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) - * @param sellAddr The address of the token to sell.(For MATIC: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) - * @param sellAmt The amount of the token to sell. - * @param unitAmts The amount of buyAmt/sellAmt with slippage for respective DEXs. - * @param swapDatas The function selectors of swap methods of the DEXs. - * @param callDatas Data from APIs for respective DEXs. - * @param setId ID stores the amount of token brought. + * @param _data Encoded function call data including function selector encoded with parameters. */ function swap( - address buyAddr, - address sellAddr, - uint256 sellAmt, - uint256[] memory unitAmts, - bytes4[] memory swapDatas, - bytes[] calldata callDatas, string[] memory _connectors, - uint256 setId + bytes[] memory _data ) external payable returns (string memory _eventName, bytes memory _eventParam) { - InputData memory inputData = InputData({ - buyAddr: buyAddr, - sellAddr: sellAddr, - sellAmt: sellAmt, - unitAmts: unitAmts, - swapDatas: swapDatas, - callDatas: callDatas, - setId: setId - }); - - (bool success, bytes memory returnData) = _swap(_connectors, inputData); + (bool success, bytes memory returnData) = _swap(_connectors, _data); require(success, "swap-Aggregator-failed"); (_eventName, _eventParam) = abi.decode(returnData, (string, bytes)); diff --git a/contracts/mainnet/connectors/swap/helpers.sol b/contracts/mainnet/connectors/swap/helpers.sol index 890ae9c0..68b37832 100644 --- a/contracts/mainnet/connectors/swap/helpers.sol +++ b/contracts/mainnet/connectors/swap/helpers.sol @@ -11,56 +11,23 @@ contract SwapHelpers { InstaConnectors internal constant instaConnectors = InstaConnectors(0x97b0B3A8bDeFE8cB9563a3c610019Ad10DB8aD11); - struct InputData { - address buyAddr; - address sellAddr; - uint256 sellAmt; - uint256[] unitAmts; - bytes4[] swapDatas; - bytes[] callDatas; - uint256 setId; - } - /** *@dev Swap using the dex aggregators. *@param _connectors name of the connectors in preference order. - *@param _inputData data for the swap cast. + *@param _data data for the swap cast. */ - function _swap(string[] memory _connectors, InputData memory _inputData) + function _swap(string[] memory _connectors, bytes[] memory _data) internal returns (bool success, bytes memory returnData) { uint256 _length = _connectors.length; require(_length > 0, "zero-length-not-allowed"); - require( - _inputData.unitAmts.length == _length, - "unitAmts-length-invalid" - ); - require( - _inputData.callDatas.length == _length, - "callDatas-length-invalid" - ); - require( - _inputData.swapDatas.length == _length, - "swapDatas-length-invalid" - ); - - // require _connectors[i] == "1INCH-A" || "ZEROX-A" || "PARASWAP-A" || similar connectors + require(_data.length == _length, "calldata-length-invalid"); for (uint256 i = 0; i < _length; i++) { - bytes memory _data = abi.encodeWithSelector( - _inputData.swapDatas[i], - _inputData.buyAddr, - _inputData.sellAddr, - _inputData.sellAmt, - _inputData.unitAmts[i], - _inputData.callDatas[i], - _inputData.setId - ); - (success, returnData) = instaConnectors .connectors(_connectors[i]) - .delegatecall(_data); + .delegatecall(_data[i]); if (success) { break; } diff --git a/contracts/mainnet/connectors/swap/main.sol b/contracts/mainnet/connectors/swap/main.sol index a76c2432..a98ee841 100644 --- a/contracts/mainnet/connectors/swap/main.sol +++ b/contracts/mainnet/connectors/swap/main.sol @@ -15,39 +15,14 @@ abstract contract Swap is SwapHelpers { * @dev Swap ETH/ERC20_Token using dex aggregators. * @notice Swap tokens from exchanges like 1INCH, 0x etc, with calculation done off-chain. * @param _connectors The name of the connectors like 1INCH-A, 0x etc, in order of their priority. - * @param buyAddr The address of the token to buy.(For MATIC: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) - * @param sellAddr The address of the token to sell.(For MATIC: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) - * @param sellAmt The amount of the token to sell. - * @param unitAmts The amount of buyAmt/sellAmt with slippage for respective DEXs. - * @param swapDatas The function selectors of swap methods of the DEXs. - * @param callDatas Data from APIs for respective DEXs. - * @param setId ID stores the amount of token brought. + * @param _data Encoded function call data including function selector encoded with parameters. */ - function swap( - address buyAddr, - address sellAddr, - uint256 sellAmt, - uint256[] memory unitAmts, - bytes4[] memory swapDatas, - bytes[] calldata callDatas, - string[] memory _connectors, - uint256 setId - ) + function swap(string[] memory _connectors, bytes[] memory _data) external payable returns (string memory _eventName, bytes memory _eventParam) { - InputData memory inputData = InputData({ - buyAddr: buyAddr, - sellAddr: sellAddr, - sellAmt: sellAmt, - unitAmts: unitAmts, - swapDatas: swapDatas, - callDatas: callDatas, - setId: setId - }); - - (bool success, bytes memory returnData) = _swap(_connectors, inputData); + (bool success, bytes memory returnData) = _swap(_connectors, _data); require(success, "swap-Aggregator-failed"); (_eventName, _eventParam) = abi.decode(returnData, (string, bytes)); diff --git a/contracts/polygon/connectors/swap/helpers.sol b/contracts/polygon/connectors/swap/helpers.sol index 26e99514..788a746b 100644 --- a/contracts/polygon/connectors/swap/helpers.sol +++ b/contracts/polygon/connectors/swap/helpers.sol @@ -11,56 +11,23 @@ contract SwapHelpers { InstaConnectors internal constant instaConnectors = InstaConnectors(0x2A00684bFAb9717C21271E0751BCcb7d2D763c88); - struct InputData { - address buyAddr; - address sellAddr; - uint256 sellAmt; - uint256[] unitAmts; - bytes4[] swapDatas; - bytes[] callDatas; - uint256 setId; - } - /** *@dev Swap using the dex aggregators. *@param _connectors name of the connectors in preference order. - *@param _inputData data for the swap cast. + *@param _data data for the swap cast. */ - function _swap(string[] memory _connectors, InputData memory _inputData) + function _swap(string[] memory _connectors, bytes[] memory _data) internal returns (bool success, bytes memory returnData) { uint256 _length = _connectors.length; require(_length > 0, "zero-length-not-allowed"); - require( - _inputData.unitAmts.length == _length, - "unitAmts-length-invalid" - ); - require( - _inputData.callDatas.length == _length, - "callDatas-length-invalid" - ); - require( - _inputData.swapDatas.length == _length, - "swapDatas-length-invalid" - ); - - // require _connectors[i] == "1INCH-A" || "ZEROX-A" || "PARASWAP-A" || similar connectors + require(_data.length == _length, "calldata-length-invalid"); for (uint256 i = 0; i < _length; i++) { - bytes memory _data = abi.encodeWithSelector( - _inputData.swapDatas[i], - _inputData.buyAddr, - _inputData.sellAddr, - _inputData.sellAmt, - _inputData.unitAmts[i], - _inputData.callDatas[i], - _inputData.setId - ); - (success, returnData) = instaConnectors .connectors(_connectors[i]) - .delegatecall(_data); + .delegatecall(_data[i]); if (success) { break; } diff --git a/contracts/polygon/connectors/swap/main.sol b/contracts/polygon/connectors/swap/main.sol index ada14dc6..e8c79a42 100644 --- a/contracts/polygon/connectors/swap/main.sol +++ b/contracts/polygon/connectors/swap/main.sol @@ -15,39 +15,14 @@ abstract contract Swap is SwapHelpers { * @dev Swap ETH/ERC20_Token using dex aggregators. * @notice Swap tokens from exchanges like 1INCH, 0x etc, with calculation done off-chain. * @param _connectors The name of the connectors like 1INCH-A, 0x etc, in order of their priority. - * @param buyAddr The address of the token to buy.(For MATIC: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) - * @param sellAddr The address of the token to sell.(For MATIC: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) - * @param sellAmt The amount of the token to sell. - * @param unitAmts The amount of buyAmt/sellAmt with slippage for respective DEXs. - * @param swapDatas The function selectors of swap methods of the DEXs. - * @param callDatas Data from APIs for respective DEXs. - * @param setId ID stores the amount of token brought. + * @param _data Encoded function call data including function selector encoded with parameters. */ - function swap( - address buyAddr, - address sellAddr, - uint256 sellAmt, - uint256[] memory unitAmts, - bytes4[] memory swapDatas, - bytes[] calldata callDatas, - string[] memory _connectors, - uint256 setId - ) + function swap(string[] memory _connectors, bytes[] memory _data) external payable returns (string memory _eventName, bytes memory _eventParam) { - InputData memory inputData = InputData({ - buyAddr: buyAddr, - sellAddr: sellAddr, - sellAmt: sellAmt, - unitAmts: unitAmts, - swapDatas: swapDatas, - callDatas: callDatas, - setId: setId - }); - - (bool success, bytes memory returnData) = _swap(_connectors, inputData); + (bool success, bytes memory returnData) = _swap(_connectors, _data); require(success, "swap-Aggregator-failed"); (_eventName, _eventParam) = abi.decode(returnData, (string, bytes)); diff --git a/test/avalanche/swap/swap-test.ts b/test/avalanche/swap/swap-test.ts index a1f74a5d..8dc4efb0 100644 --- a/test/avalanche/swap/swap-test.ts +++ b/test/avalanche/swap/swap-test.ts @@ -73,24 +73,11 @@ describe("Swap | Avalanche", function () { describe("Main", function () { it("should swap the tokens", async function () { let buyTokenAmountZeroX: any; + let unitAmount1Inch: any; + let calldata1Inch: any; // let buyTokenAmount1Inch: any; let buyTokenAmountParaswap: any; - async function getSelector(connector: string) { - var abi = [ - "function swap(address,address,uint256,uint256,bytes,uint256)", - "function sell(address,address,uint256,uint256,bytes,uint256)" - ]; - var iface = new ethers.utils.Interface(abi); - var id; - if (connector == "1INCH-A") { - id = iface.getSighash("sell"); - } else { - id = iface.getSighash("swap"); - } - - return id; - } async function getArg() { // const slippage = 0.5; /* avax -> usdt */ @@ -155,17 +142,45 @@ describe("Swap | Avalanche", function () { unitAmt = unitAmt.multipliedBy(1e18).toFixed(0); return unitAmt; }; + let unitAmt0x = calculateUnitAmt(buyTokenAmountZeroX); let unitAmtParaswap = calculateUnitAmt(buyTokenAmountParaswap); - let swapDataPara = ethers.utils.hexlify(await getSelector("PARASWAP-A")); - let swapDataZeroX = ethers.utils.hexlify(await getSelector("ZEROX-A")); - let unitAmts = [unitAmtParaswap, unitAmt0x]; - let calldatas = [calldataPara, calldataZeroX]; - let swapDatas = [swapDataPara, swapDataZeroX]; + + function getSelector(connector: string, unitAmt: any, callData: any) { + var abi = [ + "function swap(address,address,uint256,uint256,bytes,uint256)", + "function sell(address,address,uint256,uint256,bytes,uint256)" + ]; + var iface = new ethers.utils.Interface(abi); + var data; + if (connector == "1INCH-A") { + data = iface.encodeFunctionData("sell", [ + buyTokenAddress, + sellTokenAddress, + srcAmount, + unitAmt, + callData, + 0 + ]); + } else { + data = iface.encodeFunctionData("swap", [ + buyTokenAddress, + sellTokenAddress, + srcAmount, + unitAmt, + callData, + 0 + ]); + } + return data; + } + let dataPara = ethers.utils.hexlify(await getSelector("PARASWAP-A", unitAmtParaswap, calldataPara)); + let dataZeroX = ethers.utils.hexlify(await getSelector("ZEROX-A", unitAmt0x, calldataZeroX)); + let datas = [dataPara, dataZeroX]; let connectors = ["PARASWAP-A", "ZEROX-A"]; - return [buyTokenAddress, sellTokenAddress, srcAmount, unitAmts, swapDatas, calldatas, connectors, 0]; + return [connectors, datas]; } let arg = await getArg(); diff --git a/test/mainnet/swap/swap-test.ts b/test/mainnet/swap/swap-test.ts index eef0ea7c..69d4dad4 100644 --- a/test/mainnet/swap/swap-test.ts +++ b/test/mainnet/swap/swap-test.ts @@ -76,22 +76,6 @@ describe("Swap | Mainnet", function () { let buyTokenAmount1Inch: any; let buyTokenAmountParaswap: any; - async function getSelector(connector: string) { - var abi = [ - "function swap(address,address,uint256,uint256,bytes,uint256)", - "function sell(address,address,uint256,uint256,bytes,uint256)" - ]; - var iface = new ethers.utils.Interface(abi); - var id; - if (connector == "1INCH-A") { - id = iface.getSighash("sell"); - } else { - id = iface.getSighash("swap"); - } - - return id; - } - async function getArg() { const slippage = 0.5; /* eth -> dai */ @@ -178,17 +162,42 @@ describe("Swap | Mainnet", function () { let unitAmt0x = calculateUnitAmt(buyTokenAmountZeroX); let unitAmtParaswap = calculateUnitAmt(buyTokenAmountParaswap); - let swapDataPara = ethers.utils.hexlify(await getSelector("PARASWAP-A")); - let swapDataZeroX = ethers.utils.hexlify(await getSelector("ZEROX-A")); - let swapData1Inch = ethers.utils.hexlify(await getSelector("1INCH-A")); + function getSelector(connector: string, unitAmt: any, callData: any) { + var abi = [ + "function swap(address,address,uint256,uint256,bytes,uint256)", + "function sell(address,address,uint256,uint256,bytes,uint256)" + ]; + var iface = new ethers.utils.Interface(abi); + var data; + if (connector == "1INCH-A") { + data = iface.encodeFunctionData("sell", [ + buyTokenAddress, + sellTokenAddress, + srcAmount, + unitAmt, + callData, + 0 + ]); + } else { + data = iface.encodeFunctionData("swap", [ + buyTokenAddress, + sellTokenAddress, + srcAmount, + unitAmt, + callData, + 0 + ]); + } + return data; + } + let data1Inch = ethers.utils.hexlify(await getSelector("1INCH-A", unitAmt1Inch, calldata1Inch)); + let dataPara = ethers.utils.hexlify(await getSelector("PARASWAP-A", unitAmtParaswap, calldataPara)); + let dataZeroX = ethers.utils.hexlify(await getSelector("ZEROX-A", unitAmt0x, calldataZeroX)); + let datas = [data1Inch, dataPara, dataZeroX]; - let unitAmts = [unitAmt1Inch, unitAmt0x, unitAmtParaswap]; - let calldatas = [calldata1Inch, calldataZeroX, calldataPara]; - let swapDatas = [swapData1Inch, swapDataZeroX, swapDataPara]; + let connectors = ["1INCH-A", "PARASWAP-A", "ZEROX-A"]; - let connectors = ["1INCH-A", "ZEROX-A", "PARASWAP-A"]; - - return [buyTokenAddress, sellTokenAddress, srcAmount, unitAmts, swapDatas, calldatas, connectors, 0]; + return [connectors, datas]; } let arg = await getArg(); diff --git a/test/polygon/swap/swap-test.ts b/test/polygon/swap/swap-test.ts index 0abbd569..2b54e70a 100644 --- a/test/polygon/swap/swap-test.ts +++ b/test/polygon/swap/swap-test.ts @@ -75,6 +75,8 @@ describe("Swap", function () { let buyTokenAmountZeroX: any; let buyTokenAmount1Inch: any; let buyTokenAmountParaswap: any; + let unitAmount1Inch: any; + let calldata1Inch: any; async function getSelector(connector: string) { var abi = [ @@ -159,16 +161,41 @@ describe("Swap", function () { let unitAmt0x = calculateUnitAmt(buyTokenAmountZeroX); let unitAmtParaswap = calculateUnitAmt(buyTokenAmountParaswap); - let swapDataPara = ethers.utils.hexlify(await getSelector("PARASWAP-A")); - let swapDataZeroX = ethers.utils.hexlify(await getSelector("ZEROX-A")); - - let unitAmts = [unitAmt0x, unitAmtParaswap]; - let calldatas = [calldataZeroX, calldataPara]; - let swapDatas = [swapDataZeroX, swapDataPara]; + function getCallData(connector: string, unitAmt: any, callData: any) { + var abi = [ + "function swap(address,address,uint256,uint256,bytes,uint256)", + "function sell(address,address,uint256,uint256,bytes,uint256)" + ]; + var iface = new ethers.utils.Interface(abi); + var data; + if (connector == "1INCH-A") { + data = iface.encodeFunctionData("sell", [ + buyTokenAddress, + sellTokenAddress, + srcAmount, + unitAmt, + callData, + 0 + ]); + } else { + data = iface.encodeFunctionData("swap", [ + buyTokenAddress, + sellTokenAddress, + srcAmount, + unitAmt, + callData, + 0 + ]); + } + return data; + } + let dataPara = ethers.utils.hexlify(await getCallData("PARASWAP-A", unitAmtParaswap, calldataPara)); + let dataZeroX = ethers.utils.hexlify(await getCallData("ZEROX-A", unitAmt0x, calldataZeroX)); + let datas = [dataZeroX, dataPara]; let connectors = ["ZEROX-A", "PARASWAP-A"]; - return [buyTokenAddress, sellTokenAddress, srcAmount, unitAmts, swapDatas, calldatas, connectors, 0]; + return [connectors, datas]; } let arg = await getArg(); From 78e6a3a1369bcfe28b1cf894651ea428f9dbb9a4 Mon Sep 17 00:00:00 2001 From: Richa-iitr Date: Tue, 14 Jun 2022 13:25:48 +0530 Subject: [PATCH 18/27] minor change --- contracts/avalanche/connectors/swap/helpers.sol | 4 +--- contracts/mainnet/connectors/swap/helpers.sol | 4 +--- contracts/polygon/connectors/swap/helpers.sol | 4 +--- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/contracts/avalanche/connectors/swap/helpers.sol b/contracts/avalanche/connectors/swap/helpers.sol index 7775be61..bc117d50 100644 --- a/contracts/avalanche/connectors/swap/helpers.sol +++ b/contracts/avalanche/connectors/swap/helpers.sol @@ -28,9 +28,7 @@ contract SwapHelpers { (success, returnData) = instaConnectors .connectors(_connectors[i]) .delegatecall(_data[i]); - if (success) { - break; - } + if (success) break; } } } diff --git a/contracts/mainnet/connectors/swap/helpers.sol b/contracts/mainnet/connectors/swap/helpers.sol index 68b37832..3e055a61 100644 --- a/contracts/mainnet/connectors/swap/helpers.sol +++ b/contracts/mainnet/connectors/swap/helpers.sol @@ -28,9 +28,7 @@ contract SwapHelpers { (success, returnData) = instaConnectors .connectors(_connectors[i]) .delegatecall(_data[i]); - if (success) { - break; - } + if (success) break; } } } diff --git a/contracts/polygon/connectors/swap/helpers.sol b/contracts/polygon/connectors/swap/helpers.sol index 788a746b..54aa6e43 100644 --- a/contracts/polygon/connectors/swap/helpers.sol +++ b/contracts/polygon/connectors/swap/helpers.sol @@ -28,9 +28,7 @@ contract SwapHelpers { (success, returnData) = instaConnectors .connectors(_connectors[i]) .delegatecall(_data[i]); - if (success) { - break; - } + if (success) break; } } } From 16ef3fc9f4e4b3019a883eb0599ac1cf9cb5cf1e Mon Sep 17 00:00:00 2001 From: Richa-iitr Date: Tue, 14 Jun 2022 13:46:38 +0530 Subject: [PATCH 19/27] tests update --- test/avalanche/swap/swap-test.ts | 28 +++++----------------------- test/mainnet/swap/swap-test.ts | 30 ++++++------------------------ test/polygon/swap/swap-test.ts | 22 ++-------------------- 3 files changed, 13 insertions(+), 67 deletions(-) diff --git a/test/avalanche/swap/swap-test.ts b/test/avalanche/swap/swap-test.ts index 8dc4efb0..e1aee935 100644 --- a/test/avalanche/swap/swap-test.ts +++ b/test/avalanche/swap/swap-test.ts @@ -146,36 +146,18 @@ describe("Swap | Avalanche", function () { let unitAmt0x = calculateUnitAmt(buyTokenAmountZeroX); let unitAmtParaswap = calculateUnitAmt(buyTokenAmountParaswap); - function getSelector(connector: string, unitAmt: any, callData: any) { + function getCallData(connector: string, unitAmt: any, callData: any) { var abi = [ "function swap(address,address,uint256,uint256,bytes,uint256)", "function sell(address,address,uint256,uint256,bytes,uint256)" ]; var iface = new ethers.utils.Interface(abi); - var data; - if (connector == "1INCH-A") { - data = iface.encodeFunctionData("sell", [ - buyTokenAddress, - sellTokenAddress, - srcAmount, - unitAmt, - callData, - 0 - ]); - } else { - data = iface.encodeFunctionData("swap", [ - buyTokenAddress, - sellTokenAddress, - srcAmount, - unitAmt, - callData, - 0 - ]); - } + const spell = connector === "1INCH-A" ? "sell" : "swap"; + let data = iface.encodeFunctionData(spell, [buyTokenAddress, sellTokenAddress, srcAmount, unitAmt, callData, 0]); return data; } - let dataPara = ethers.utils.hexlify(await getSelector("PARASWAP-A", unitAmtParaswap, calldataPara)); - let dataZeroX = ethers.utils.hexlify(await getSelector("ZEROX-A", unitAmt0x, calldataZeroX)); + let dataPara = ethers.utils.hexlify(await getCallData("PARASWAP-A", unitAmtParaswap, calldataPara)); + let dataZeroX = ethers.utils.hexlify(await getCallData("ZEROX-A", unitAmt0x, calldataZeroX)); let datas = [dataPara, dataZeroX]; let connectors = ["PARASWAP-A", "ZEROX-A"]; diff --git a/test/mainnet/swap/swap-test.ts b/test/mainnet/swap/swap-test.ts index 69d4dad4..b7f38fd3 100644 --- a/test/mainnet/swap/swap-test.ts +++ b/test/mainnet/swap/swap-test.ts @@ -162,37 +162,19 @@ describe("Swap | Mainnet", function () { let unitAmt0x = calculateUnitAmt(buyTokenAmountZeroX); let unitAmtParaswap = calculateUnitAmt(buyTokenAmountParaswap); - function getSelector(connector: string, unitAmt: any, callData: any) { + function getCallData(connector: string, unitAmt: any, callData: any) { var abi = [ "function swap(address,address,uint256,uint256,bytes,uint256)", "function sell(address,address,uint256,uint256,bytes,uint256)" ]; var iface = new ethers.utils.Interface(abi); - var data; - if (connector == "1INCH-A") { - data = iface.encodeFunctionData("sell", [ - buyTokenAddress, - sellTokenAddress, - srcAmount, - unitAmt, - callData, - 0 - ]); - } else { - data = iface.encodeFunctionData("swap", [ - buyTokenAddress, - sellTokenAddress, - srcAmount, - unitAmt, - callData, - 0 - ]); - } + const spell = connector === "1INCH-A" ? "sell" : "swap"; + let data = iface.encodeFunctionData(spell, [buyTokenAddress, sellTokenAddress, srcAmount, unitAmt, callData, 0]); return data; } - let data1Inch = ethers.utils.hexlify(await getSelector("1INCH-A", unitAmt1Inch, calldata1Inch)); - let dataPara = ethers.utils.hexlify(await getSelector("PARASWAP-A", unitAmtParaswap, calldataPara)); - let dataZeroX = ethers.utils.hexlify(await getSelector("ZEROX-A", unitAmt0x, calldataZeroX)); + let data1Inch = ethers.utils.hexlify(await getCallData("1INCH-A", unitAmt1Inch, calldata1Inch)); + let dataPara = ethers.utils.hexlify(await getCallData("PARASWAP-A", unitAmtParaswap, calldataPara)); + let dataZeroX = ethers.utils.hexlify(await getCallData("ZEROX-A", unitAmt0x, calldataZeroX)); let datas = [data1Inch, dataPara, dataZeroX]; let connectors = ["1INCH-A", "PARASWAP-A", "ZEROX-A"]; diff --git a/test/polygon/swap/swap-test.ts b/test/polygon/swap/swap-test.ts index 2b54e70a..0e7cb9a3 100644 --- a/test/polygon/swap/swap-test.ts +++ b/test/polygon/swap/swap-test.ts @@ -167,26 +167,8 @@ describe("Swap", function () { "function sell(address,address,uint256,uint256,bytes,uint256)" ]; var iface = new ethers.utils.Interface(abi); - var data; - if (connector == "1INCH-A") { - data = iface.encodeFunctionData("sell", [ - buyTokenAddress, - sellTokenAddress, - srcAmount, - unitAmt, - callData, - 0 - ]); - } else { - data = iface.encodeFunctionData("swap", [ - buyTokenAddress, - sellTokenAddress, - srcAmount, - unitAmt, - callData, - 0 - ]); - } + const spell = connector === "1INCH-A" ? "sell" : "swap"; + let data = iface.encodeFunctionData(spell, [buyTokenAddress, sellTokenAddress, srcAmount, unitAmt, callData, 0]); return data; } let dataPara = ethers.utils.hexlify(await getCallData("PARASWAP-A", unitAmtParaswap, calldataPara)); From e90fcd590a3349fad11486770582c06d85534c7b Mon Sep 17 00:00:00 2001 From: Richa-iitr Date: Wed, 15 Jun 2022 03:38:28 +0530 Subject: [PATCH 20/27] updated events --- .../avalanche/connectors/swap/events.sol | 12 +++++++++++ .../avalanche/connectors/swap/helpers.sol | 11 ++++++++-- contracts/avalanche/connectors/swap/main.sol | 21 ++++++++++++------- contracts/mainnet/connectors/swap/events.sol | 12 +++++++++++ contracts/mainnet/connectors/swap/helpers.sol | 11 ++++++++-- contracts/mainnet/connectors/swap/main.sol | 16 +++++++++++--- contracts/polygon/connectors/swap/events.sol | 12 +++++++++++ contracts/polygon/connectors/swap/helpers.sol | 11 ++++++++-- contracts/polygon/connectors/swap/main.sol | 16 +++++++++++--- 9 files changed, 103 insertions(+), 19 deletions(-) create mode 100644 contracts/avalanche/connectors/swap/events.sol create mode 100644 contracts/mainnet/connectors/swap/events.sol create mode 100644 contracts/polygon/connectors/swap/events.sol diff --git a/contracts/avalanche/connectors/swap/events.sol b/contracts/avalanche/connectors/swap/events.sol new file mode 100644 index 00000000..45e71522 --- /dev/null +++ b/contracts/avalanche/connectors/swap/events.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; +pragma abicoder v2; + +contract Events { + event LogSwapAggregator( + string[] connectors, + string connectorName, + string eventName, + bytes eventParam + ); +} diff --git a/contracts/avalanche/connectors/swap/helpers.sol b/contracts/avalanche/connectors/swap/helpers.sol index bc117d50..0d2292bf 100644 --- a/contracts/avalanche/connectors/swap/helpers.sol +++ b/contracts/avalanche/connectors/swap/helpers.sol @@ -18,7 +18,11 @@ contract SwapHelpers { */ function _swap(string[] memory _connectors, bytes[] memory _data) internal - returns (bool success, bytes memory returnData) + returns ( + bool success, + bytes memory returnData, + string memory connector + ) { uint256 _length = _connectors.length; require(_length > 0, "zero-length-not-allowed"); @@ -28,7 +32,10 @@ contract SwapHelpers { (success, returnData) = instaConnectors .connectors(_connectors[i]) .delegatecall(_data[i]); - if (success) break; + if (success) { + connector = _connectors[i]; + break; + } } } } diff --git a/contracts/avalanche/connectors/swap/main.sol b/contracts/avalanche/connectors/swap/main.sol index 83ce0c26..70deb981 100644 --- a/contracts/avalanche/connectors/swap/main.sol +++ b/contracts/avalanche/connectors/swap/main.sol @@ -9,26 +9,33 @@ pragma experimental ABIEncoderV2; // import files import { SwapHelpers } from "./helpers.sol"; +import { Events } from "./events.sol"; -abstract contract Swap is SwapHelpers { +abstract contract Swap is SwapHelpers, Events { /** * @dev Swap ETH/ERC20_Token using dex aggregators. * @notice Swap tokens from exchanges like 1INCH, 0x etc, with calculation done off-chain. * @param _connectors The name of the connectors like 1INCH-A, 0x etc, in order of their priority. * @param _data Encoded function call data including function selector encoded with parameters. */ - function swap( - string[] memory _connectors, - bytes[] memory _data - ) + function swap(string[] memory _connectors, bytes[] memory _data) external payable returns (string memory _eventName, bytes memory _eventParam) { - (bool success, bytes memory returnData) = _swap(_connectors, _data); + (bool success, bytes memory returnData, string memory connector) = _swap( + _connectors, + _data + ); require(success, "swap-Aggregator-failed"); - (_eventName, _eventParam) = abi.decode(returnData, (string, bytes)); + (string memory eventName, bytes memory eventParam) = abi.decode( + returnData, + (string, bytes) + ); + + _eventName = "LogSwapAggregator(string[],string,string,bytes)"; + _eventParam = abi.encode(_connectors, connector, eventName, eventParam); } } diff --git a/contracts/mainnet/connectors/swap/events.sol b/contracts/mainnet/connectors/swap/events.sol new file mode 100644 index 00000000..cc9ce02e --- /dev/null +++ b/contracts/mainnet/connectors/swap/events.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; +pragma abicoder v2; + +contract Events { + event SwapAggregator( + string[] connectors, + string connectorName, + string eventName, + bytes eventParam + ); +} diff --git a/contracts/mainnet/connectors/swap/helpers.sol b/contracts/mainnet/connectors/swap/helpers.sol index 3e055a61..4cebf70d 100644 --- a/contracts/mainnet/connectors/swap/helpers.sol +++ b/contracts/mainnet/connectors/swap/helpers.sol @@ -18,7 +18,11 @@ contract SwapHelpers { */ function _swap(string[] memory _connectors, bytes[] memory _data) internal - returns (bool success, bytes memory returnData) + returns ( + bool success, + bytes memory returnData, + string memory connector + ) { uint256 _length = _connectors.length; require(_length > 0, "zero-length-not-allowed"); @@ -28,7 +32,10 @@ contract SwapHelpers { (success, returnData) = instaConnectors .connectors(_connectors[i]) .delegatecall(_data[i]); - if (success) break; + if (success) { + connector = _connectors[i]; + break; + } } } } diff --git a/contracts/mainnet/connectors/swap/main.sol b/contracts/mainnet/connectors/swap/main.sol index a98ee841..dac0f835 100644 --- a/contracts/mainnet/connectors/swap/main.sol +++ b/contracts/mainnet/connectors/swap/main.sol @@ -9,8 +9,9 @@ pragma experimental ABIEncoderV2; // import files import { SwapHelpers } from "./helpers.sol"; +import { Events } from "./events.sol"; -abstract contract Swap is SwapHelpers { +abstract contract Swap is SwapHelpers, Events { /** * @dev Swap ETH/ERC20_Token using dex aggregators. * @notice Swap tokens from exchanges like 1INCH, 0x etc, with calculation done off-chain. @@ -22,10 +23,19 @@ abstract contract Swap is SwapHelpers { payable returns (string memory _eventName, bytes memory _eventParam) { - (bool success, bytes memory returnData) = _swap(_connectors, _data); + (bool success, bytes memory returnData, string memory connector) = _swap( + _connectors, + _data + ); require(success, "swap-Aggregator-failed"); - (_eventName, _eventParam) = abi.decode(returnData, (string, bytes)); + (string memory eventName, bytes memory eventParam) = abi.decode( + returnData, + (string, bytes) + ); + + _eventName = "LogSwapAggregator(string[],string,string,bytes)"; + _eventParam = abi.encode(_connectors, connector, eventName, eventParam); } } diff --git a/contracts/polygon/connectors/swap/events.sol b/contracts/polygon/connectors/swap/events.sol new file mode 100644 index 00000000..cc9ce02e --- /dev/null +++ b/contracts/polygon/connectors/swap/events.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; +pragma abicoder v2; + +contract Events { + event SwapAggregator( + string[] connectors, + string connectorName, + string eventName, + bytes eventParam + ); +} diff --git a/contracts/polygon/connectors/swap/helpers.sol b/contracts/polygon/connectors/swap/helpers.sol index 54aa6e43..7e9e133a 100644 --- a/contracts/polygon/connectors/swap/helpers.sol +++ b/contracts/polygon/connectors/swap/helpers.sol @@ -18,7 +18,11 @@ contract SwapHelpers { */ function _swap(string[] memory _connectors, bytes[] memory _data) internal - returns (bool success, bytes memory returnData) + returns ( + bool success, + bytes memory returnData, + string memory connector + ) { uint256 _length = _connectors.length; require(_length > 0, "zero-length-not-allowed"); @@ -28,7 +32,10 @@ contract SwapHelpers { (success, returnData) = instaConnectors .connectors(_connectors[i]) .delegatecall(_data[i]); - if (success) break; + if (success) { + connector = _connectors[i]; + break; + } } } } diff --git a/contracts/polygon/connectors/swap/main.sol b/contracts/polygon/connectors/swap/main.sol index e8c79a42..31ba300e 100644 --- a/contracts/polygon/connectors/swap/main.sol +++ b/contracts/polygon/connectors/swap/main.sol @@ -9,8 +9,9 @@ pragma experimental ABIEncoderV2; // import files import { SwapHelpers } from "./helpers.sol"; +import { Events } from "./events.sol"; -abstract contract Swap is SwapHelpers { +abstract contract Swap is SwapHelpers, Events { /** * @dev Swap ETH/ERC20_Token using dex aggregators. * @notice Swap tokens from exchanges like 1INCH, 0x etc, with calculation done off-chain. @@ -22,10 +23,19 @@ abstract contract Swap is SwapHelpers { payable returns (string memory _eventName, bytes memory _eventParam) { - (bool success, bytes memory returnData) = _swap(_connectors, _data); + (bool success, bytes memory returnData, string memory connector) = _swap( + _connectors, + _data + ); require(success, "swap-Aggregator-failed"); - (_eventName, _eventParam) = abi.decode(returnData, (string, bytes)); + (string memory eventName, bytes memory eventParam) = abi.decode( + returnData, + (string, bytes) + ); + + _eventName = "LogSwapAggregator(string[],string,string,bytes)"; + _eventParam = abi.encode(_connectors, connector, eventName, eventParam); } } From fb79ade8fea1fbd79a1fd80e025e18b3a6e6468a Mon Sep 17 00:00:00 2001 From: Richa-iitr Date: Wed, 15 Jun 2022 03:40:23 +0530 Subject: [PATCH 21/27] minor change --- contracts/mainnet/connectors/swap/events.sol | 2 +- contracts/polygon/connectors/swap/events.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/mainnet/connectors/swap/events.sol b/contracts/mainnet/connectors/swap/events.sol index cc9ce02e..45e71522 100644 --- a/contracts/mainnet/connectors/swap/events.sol +++ b/contracts/mainnet/connectors/swap/events.sol @@ -3,7 +3,7 @@ pragma solidity ^0.7.0; pragma abicoder v2; contract Events { - event SwapAggregator( + event LogSwapAggregator( string[] connectors, string connectorName, string eventName, diff --git a/contracts/polygon/connectors/swap/events.sol b/contracts/polygon/connectors/swap/events.sol index cc9ce02e..45e71522 100644 --- a/contracts/polygon/connectors/swap/events.sol +++ b/contracts/polygon/connectors/swap/events.sol @@ -3,7 +3,7 @@ pragma solidity ^0.7.0; pragma abicoder v2; contract Events { - event SwapAggregator( + event LogSwapAggregator( string[] connectors, string connectorName, string eventName, From f8e65363c91a4b28bcc06d57dedc1d918b8fec0c Mon Sep 17 00:00:00 2001 From: Richa-iitr Date: Wed, 15 Jun 2022 14:07:35 +0530 Subject: [PATCH 22/27] minor changes --- contracts/avalanche/connectors/swap/helpers.sol | 8 ++++---- contracts/avalanche/connectors/swap/main.sol | 6 +++--- contracts/mainnet/connectors/swap/helpers.sol | 8 ++++---- contracts/mainnet/connectors/swap/main.sol | 6 +++--- contracts/polygon/connectors/swap/helpers.sol | 8 ++++---- contracts/polygon/connectors/swap/main.sol | 6 +++--- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/contracts/avalanche/connectors/swap/helpers.sol b/contracts/avalanche/connectors/swap/helpers.sol index 0d2292bf..dabc32d7 100644 --- a/contracts/avalanche/connectors/swap/helpers.sol +++ b/contracts/avalanche/connectors/swap/helpers.sol @@ -14,9 +14,9 @@ contract SwapHelpers { /** *@dev Swap using the dex aggregators. *@param _connectors name of the connectors in preference order. - *@param _data data for the swap cast. + *@param _datas data for the swap cast. */ - function _swap(string[] memory _connectors, bytes[] memory _data) + function _swap(string[] memory _connectors, bytes[] memory _datas) internal returns ( bool success, @@ -26,12 +26,12 @@ contract SwapHelpers { { uint256 _length = _connectors.length; require(_length > 0, "zero-length-not-allowed"); - require(_data.length == _length, "calldata-length-invalid"); + require(_datas.length == _length, "calldata-length-invalid"); for (uint256 i = 0; i < _length; i++) { (success, returnData) = instaConnectors .connectors(_connectors[i]) - .delegatecall(_data[i]); + .delegatecall(_datas[i]); if (success) { connector = _connectors[i]; break; diff --git a/contracts/avalanche/connectors/swap/main.sol b/contracts/avalanche/connectors/swap/main.sol index 70deb981..a14a0ddd 100644 --- a/contracts/avalanche/connectors/swap/main.sol +++ b/contracts/avalanche/connectors/swap/main.sol @@ -16,16 +16,16 @@ abstract contract Swap is SwapHelpers, Events { * @dev Swap ETH/ERC20_Token using dex aggregators. * @notice Swap tokens from exchanges like 1INCH, 0x etc, with calculation done off-chain. * @param _connectors The name of the connectors like 1INCH-A, 0x etc, in order of their priority. - * @param _data Encoded function call data including function selector encoded with parameters. + * @param _datas Encoded function call data including function selector encoded with parameters. */ - function swap(string[] memory _connectors, bytes[] memory _data) + function swap(string[] memory _connectors, bytes[] memory _datas) external payable returns (string memory _eventName, bytes memory _eventParam) { (bool success, bytes memory returnData, string memory connector) = _swap( _connectors, - _data + _datas ); require(success, "swap-Aggregator-failed"); diff --git a/contracts/mainnet/connectors/swap/helpers.sol b/contracts/mainnet/connectors/swap/helpers.sol index 4cebf70d..edf49e1f 100644 --- a/contracts/mainnet/connectors/swap/helpers.sol +++ b/contracts/mainnet/connectors/swap/helpers.sol @@ -14,9 +14,9 @@ contract SwapHelpers { /** *@dev Swap using the dex aggregators. *@param _connectors name of the connectors in preference order. - *@param _data data for the swap cast. + *@param _datas data for the swap cast. */ - function _swap(string[] memory _connectors, bytes[] memory _data) + function _swap(string[] memory _connectors, bytes[] memory _datas) internal returns ( bool success, @@ -26,12 +26,12 @@ contract SwapHelpers { { uint256 _length = _connectors.length; require(_length > 0, "zero-length-not-allowed"); - require(_data.length == _length, "calldata-length-invalid"); + require(_datas.length == _length, "calldata-length-invalid"); for (uint256 i = 0; i < _length; i++) { (success, returnData) = instaConnectors .connectors(_connectors[i]) - .delegatecall(_data[i]); + .delegatecall(_datas[i]); if (success) { connector = _connectors[i]; break; diff --git a/contracts/mainnet/connectors/swap/main.sol b/contracts/mainnet/connectors/swap/main.sol index dac0f835..1b539fa7 100644 --- a/contracts/mainnet/connectors/swap/main.sol +++ b/contracts/mainnet/connectors/swap/main.sol @@ -16,16 +16,16 @@ abstract contract Swap is SwapHelpers, Events { * @dev Swap ETH/ERC20_Token using dex aggregators. * @notice Swap tokens from exchanges like 1INCH, 0x etc, with calculation done off-chain. * @param _connectors The name of the connectors like 1INCH-A, 0x etc, in order of their priority. - * @param _data Encoded function call data including function selector encoded with parameters. + * @param _datas Encoded function call data including function selector encoded with parameters. */ - function swap(string[] memory _connectors, bytes[] memory _data) + function swap(string[] memory _connectors, bytes[] memory _datas) external payable returns (string memory _eventName, bytes memory _eventParam) { (bool success, bytes memory returnData, string memory connector) = _swap( _connectors, - _data + _datas ); require(success, "swap-Aggregator-failed"); diff --git a/contracts/polygon/connectors/swap/helpers.sol b/contracts/polygon/connectors/swap/helpers.sol index 7e9e133a..acecb5b5 100644 --- a/contracts/polygon/connectors/swap/helpers.sol +++ b/contracts/polygon/connectors/swap/helpers.sol @@ -14,9 +14,9 @@ contract SwapHelpers { /** *@dev Swap using the dex aggregators. *@param _connectors name of the connectors in preference order. - *@param _data data for the swap cast. + *@param _datas data for the swap cast. */ - function _swap(string[] memory _connectors, bytes[] memory _data) + function _swap(string[] memory _connectors, bytes[] memory _datas) internal returns ( bool success, @@ -26,12 +26,12 @@ contract SwapHelpers { { uint256 _length = _connectors.length; require(_length > 0, "zero-length-not-allowed"); - require(_data.length == _length, "calldata-length-invalid"); + require(_datas.length == _length, "calldata-length-invalid"); for (uint256 i = 0; i < _length; i++) { (success, returnData) = instaConnectors .connectors(_connectors[i]) - .delegatecall(_data[i]); + .delegatecall(_datas[i]); if (success) { connector = _connectors[i]; break; diff --git a/contracts/polygon/connectors/swap/main.sol b/contracts/polygon/connectors/swap/main.sol index 31ba300e..8d6e8dad 100644 --- a/contracts/polygon/connectors/swap/main.sol +++ b/contracts/polygon/connectors/swap/main.sol @@ -16,16 +16,16 @@ abstract contract Swap is SwapHelpers, Events { * @dev Swap ETH/ERC20_Token using dex aggregators. * @notice Swap tokens from exchanges like 1INCH, 0x etc, with calculation done off-chain. * @param _connectors The name of the connectors like 1INCH-A, 0x etc, in order of their priority. - * @param _data Encoded function call data including function selector encoded with parameters. + * @param _datas Encoded function call data including function selector encoded with parameters. */ - function swap(string[] memory _connectors, bytes[] memory _data) + function swap(string[] memory _connectors, bytes[] memory _datas) external payable returns (string memory _eventName, bytes memory _eventParam) { (bool success, bytes memory returnData, string memory connector) = _swap( _connectors, - _data + _datas ); require(success, "swap-Aggregator-failed"); From f3aaea677b59321d5251229733fcbda48c03bdc5 Mon Sep 17 00:00:00 2001 From: Richa-iitr Date: Wed, 15 Jun 2022 14:44:49 +0530 Subject: [PATCH 23/27] code refactor --- contracts/avalanche/common/interfaces.sol | 3 ++- contracts/avalanche/connectors/swap/helpers.sol | 9 ++++++--- contracts/mainnet/common/interfaces.sol | 5 +++-- contracts/mainnet/connectors/swap/helpers.sol | 9 ++++++--- contracts/polygon/common/interfaces.sol | 4 +++- contracts/polygon/connectors/swap/helpers.sol | 9 ++++++--- 6 files changed, 26 insertions(+), 13 deletions(-) diff --git a/contracts/avalanche/common/interfaces.sol b/contracts/avalanche/common/interfaces.sol index e9a3b0c1..912e57b1 100644 --- a/contracts/avalanche/common/interfaces.sol +++ b/contracts/avalanche/common/interfaces.sol @@ -1,5 +1,6 @@ //SPDX-License-Identifier: MIT pragma solidity ^0.7.0; +pragma abicoder v2; interface TokenInterface { function approve(address, uint256) external; @@ -23,5 +24,5 @@ interface AccountInterface { } interface InstaConnectors { - function connectors(string memory) external returns (address); + function isConnectors(string[] calldata) external returns (bool, address[] memory); } diff --git a/contracts/avalanche/connectors/swap/helpers.sol b/contracts/avalanche/connectors/swap/helpers.sol index dabc32d7..b9207a26 100644 --- a/contracts/avalanche/connectors/swap/helpers.sol +++ b/contracts/avalanche/connectors/swap/helpers.sol @@ -28,10 +28,13 @@ contract SwapHelpers { require(_length > 0, "zero-length-not-allowed"); require(_datas.length == _length, "calldata-length-invalid"); + (bool isOk, address[] memory connectors) = instaConnectors.isConnectors( + _connectors + ); + require(isOk, "connector-names-invalid"); + for (uint256 i = 0; i < _length; i++) { - (success, returnData) = instaConnectors - .connectors(_connectors[i]) - .delegatecall(_datas[i]); + (success, returnData) = connectors[i].delegatecall(_datas[i]); if (success) { connector = _connectors[i]; break; diff --git a/contracts/mainnet/common/interfaces.sol b/contracts/mainnet/common/interfaces.sol index e1ed2ca2..29f60e4b 100644 --- a/contracts/mainnet/common/interfaces.sol +++ b/contracts/mainnet/common/interfaces.sol @@ -1,5 +1,6 @@ //SPDX-License-Identifier: MIT pragma solidity ^0.7.0; +pragma abicoder v2; interface TokenInterface { function approve(address, uint256) external; @@ -29,5 +30,5 @@ interface AccountInterface { } interface InstaConnectors { - function connectors(string memory) external returns (address); -} \ No newline at end of file + function isConnectors(string[] calldata) external returns (bool, address[] memory); +} diff --git a/contracts/mainnet/connectors/swap/helpers.sol b/contracts/mainnet/connectors/swap/helpers.sol index edf49e1f..1405be37 100644 --- a/contracts/mainnet/connectors/swap/helpers.sol +++ b/contracts/mainnet/connectors/swap/helpers.sol @@ -28,10 +28,13 @@ contract SwapHelpers { require(_length > 0, "zero-length-not-allowed"); require(_datas.length == _length, "calldata-length-invalid"); + (bool isOk, address[] memory connectors) = instaConnectors.isConnectors( + _connectors + ); + require(isOk, "connector-names-invalid"); + for (uint256 i = 0; i < _length; i++) { - (success, returnData) = instaConnectors - .connectors(_connectors[i]) - .delegatecall(_datas[i]); + (success, returnData) = connectors[i].delegatecall(_datas[i]); if (success) { connector = _connectors[i]; break; diff --git a/contracts/polygon/common/interfaces.sol b/contracts/polygon/common/interfaces.sol index e395b83c..94f054e1 100644 --- a/contracts/polygon/common/interfaces.sol +++ b/contracts/polygon/common/interfaces.sol @@ -1,5 +1,6 @@ //SPDX-License-Identifier: MIT pragma solidity ^0.7.0; +pragma abicoder v2; interface TokenInterface { function approve(address, uint256) external; @@ -28,5 +29,6 @@ interface AccountInterface { } interface InstaConnectors { - function connectors(string memory) external returns (address); + function isConnectors(string[] calldata) external returns (bool, address[] memory); } + diff --git a/contracts/polygon/connectors/swap/helpers.sol b/contracts/polygon/connectors/swap/helpers.sol index acecb5b5..b1badc57 100644 --- a/contracts/polygon/connectors/swap/helpers.sol +++ b/contracts/polygon/connectors/swap/helpers.sol @@ -28,10 +28,13 @@ contract SwapHelpers { require(_length > 0, "zero-length-not-allowed"); require(_datas.length == _length, "calldata-length-invalid"); + (bool isOk, address[] memory connectors) = instaConnectors.isConnectors( + _connectors + ); + require(isOk, "connector-names-invalid"); + for (uint256 i = 0; i < _length; i++) { - (success, returnData) = instaConnectors - .connectors(_connectors[i]) - .delegatecall(_datas[i]); + (success, returnData) = connectors[i].delegatecall(_datas[i]); if (success) { connector = _connectors[i]; break; From c61d69682ddc257c9d951bf953d2fd1ad447e708 Mon Sep 17 00:00:00 2001 From: Richa-iitr Date: Wed, 15 Jun 2022 20:54:05 +0530 Subject: [PATCH 24/27] contracts-opt,arb,ftm --- contracts/arbitrum/common/interfaces.sol | 5 +++ contracts/arbitrum/connectors/swap/events.sol | 12 +++++ .../arbitrum/connectors/swap/helpers.sol | 44 +++++++++++++++++++ contracts/arbitrum/connectors/swap/main.sol | 44 +++++++++++++++++++ contracts/fantom/common/interfaces.sol | 7 +++ contracts/fantom/connectors/swap/events.sol | 12 +++++ contracts/fantom/connectors/swap/helpers.sol | 44 +++++++++++++++++++ contracts/fantom/connectors/swap/main.sol | 44 +++++++++++++++++++ contracts/optimism/common/interfaces.sol | 5 +++ contracts/optimism/connectors/swap/events.sol | 12 +++++ .../optimism/connectors/swap/helpers.sol | 44 +++++++++++++++++++ contracts/optimism/connectors/swap/main.sol | 44 +++++++++++++++++++ 12 files changed, 317 insertions(+) create mode 100644 contracts/arbitrum/connectors/swap/events.sol create mode 100644 contracts/arbitrum/connectors/swap/helpers.sol create mode 100644 contracts/arbitrum/connectors/swap/main.sol create mode 100644 contracts/fantom/connectors/swap/events.sol create mode 100644 contracts/fantom/connectors/swap/helpers.sol create mode 100644 contracts/fantom/connectors/swap/main.sol create mode 100644 contracts/optimism/connectors/swap/events.sol create mode 100644 contracts/optimism/connectors/swap/helpers.sol create mode 100644 contracts/optimism/connectors/swap/main.sol diff --git a/contracts/arbitrum/common/interfaces.sol b/contracts/arbitrum/common/interfaces.sol index f843d5fb..5fbd1b6d 100644 --- a/contracts/arbitrum/common/interfaces.sol +++ b/contracts/arbitrum/common/interfaces.sol @@ -1,5 +1,6 @@ //SPDX-License-Identifier: MIT pragma solidity ^0.7.0; +pragma abicoder v2; interface TokenInterface { function approve(address, uint256) external; @@ -26,3 +27,7 @@ interface AccountInterface { function disable(address) external; function isAuth(address) external view returns (bool); } + +interface InstaConnectors { + function isConnectors(string[] calldata) external returns (bool, address[] memory); +} diff --git a/contracts/arbitrum/connectors/swap/events.sol b/contracts/arbitrum/connectors/swap/events.sol new file mode 100644 index 00000000..45e71522 --- /dev/null +++ b/contracts/arbitrum/connectors/swap/events.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; +pragma abicoder v2; + +contract Events { + event LogSwapAggregator( + string[] connectors, + string connectorName, + string eventName, + bytes eventParam + ); +} diff --git a/contracts/arbitrum/connectors/swap/helpers.sol b/contracts/arbitrum/connectors/swap/helpers.sol new file mode 100644 index 00000000..e35584c2 --- /dev/null +++ b/contracts/arbitrum/connectors/swap/helpers.sol @@ -0,0 +1,44 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; +pragma abicoder v2; + +import { InstaConnectors } from "../../common/interfaces.sol"; + +contract SwapHelpers { + /** + * @dev Instadapp Connectors Registry + */ + InstaConnectors internal constant instaConnectors = + InstaConnectors(0x67fCE99Dd6d8d659eea2a1ac1b8881c57eb6592B); + + /** + *@dev Swap using the dex aggregators. + *@param _connectors name of the connectors in preference order. + *@param _datas data for the swap cast. + */ + function _swap(string[] memory _connectors, bytes[] memory _datas) + internal + returns ( + bool success, + bytes memory returnData, + string memory connector + ) + { + uint256 _length = _connectors.length; + require(_length > 0, "zero-length-not-allowed"); + require(_datas.length == _length, "calldata-length-invalid"); + + (bool isOk, address[] memory connectors) = instaConnectors.isConnectors( + _connectors + ); + require(isOk, "connector-names-invalid"); + + for (uint256 i = 0; i < _length; i++) { + (success, returnData) = connectors[i].delegatecall(_datas[i]); + if (success) { + connector = _connectors[i]; + break; + } + } + } +} diff --git a/contracts/arbitrum/connectors/swap/main.sol b/contracts/arbitrum/connectors/swap/main.sol new file mode 100644 index 00000000..cf6014c9 --- /dev/null +++ b/contracts/arbitrum/connectors/swap/main.sol @@ -0,0 +1,44 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; + +/** + * @title Swap. + * @dev Swap integration for DEX Aggregators. + */ + +// import files +import { SwapHelpers } from "./helpers.sol"; +import { Events } from "./events.sol"; + +abstract contract Swap is SwapHelpers, Events { + /** + * @dev Swap ETH/ERC20_Token using dex aggregators. + * @notice Swap tokens from exchanges like 1INCH, 0x etc, with calculation done off-chain. + * @param _connectors The name of the connectors like 1INCH-A, 0x etc, in order of their priority. + * @param _datas Encoded function call data including function selector encoded with parameters. + */ + function swap(string[] memory _connectors, bytes[] memory _datas) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + (bool success, bytes memory returnData, string memory connector) = _swap( + _connectors, + _datas + ); + + require(success, "swap-Aggregator-failed"); + (string memory eventName, bytes memory eventParam) = abi.decode( + returnData, + (string, bytes) + ); + + _eventName = "LogSwapAggregator(string[],string,string,bytes)"; + _eventParam = abi.encode(_connectors, connector, eventName, eventParam); + } +} + +contract ConnectV2SwapAggregatorArbitrum is Swap { + string public name = "Swap-Aggregator-v1"; +} diff --git a/contracts/fantom/common/interfaces.sol b/contracts/fantom/common/interfaces.sol index 93042689..cf1abfee 100644 --- a/contracts/fantom/common/interfaces.sol +++ b/contracts/fantom/common/interfaces.sol @@ -1,5 +1,6 @@ //SPDX-License-Identifier: MIT pragma solidity ^0.7.0; +pragma abicoder v2; interface TokenInterface { function approve(address, uint256) external; @@ -34,3 +35,9 @@ interface AccountInterface { function isAuth(address) external view returns (bool); } + +interface InstaConnectors { + function isConnectors(string[] calldata) + external + returns (bool, address[] memory); +} diff --git a/contracts/fantom/connectors/swap/events.sol b/contracts/fantom/connectors/swap/events.sol new file mode 100644 index 00000000..45e71522 --- /dev/null +++ b/contracts/fantom/connectors/swap/events.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; +pragma abicoder v2; + +contract Events { + event LogSwapAggregator( + string[] connectors, + string connectorName, + string eventName, + bytes eventParam + ); +} diff --git a/contracts/fantom/connectors/swap/helpers.sol b/contracts/fantom/connectors/swap/helpers.sol new file mode 100644 index 00000000..c6c07ad3 --- /dev/null +++ b/contracts/fantom/connectors/swap/helpers.sol @@ -0,0 +1,44 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; +pragma abicoder v2; + +import { InstaConnectors } from "../../common/interfaces.sol"; + +contract SwapHelpers { + /** + * @dev Instadapp Connectors Registry + */ + InstaConnectors internal constant instaConnectors = + InstaConnectors(0x819910794a030403F69247E1e5C0bBfF1593B968); + + /** + *@dev Swap using the dex aggregators. + *@param _connectors name of the connectors in preference order. + *@param _datas data for the swap cast. + */ + function _swap(string[] memory _connectors, bytes[] memory _datas) + internal + returns ( + bool success, + bytes memory returnData, + string memory connector + ) + { + uint256 _length = _connectors.length; + require(_length > 0, "zero-length-not-allowed"); + require(_datas.length == _length, "calldata-length-invalid"); + + (bool isOk, address[] memory connectors) = instaConnectors.isConnectors( + _connectors + ); + require(isOk, "connector-names-invalid"); + + for (uint256 i = 0; i < _length; i++) { + (success, returnData) = connectors[i].delegatecall(_datas[i]); + if (success) { + connector = _connectors[i]; + break; + } + } + } +} diff --git a/contracts/fantom/connectors/swap/main.sol b/contracts/fantom/connectors/swap/main.sol new file mode 100644 index 00000000..e8784945 --- /dev/null +++ b/contracts/fantom/connectors/swap/main.sol @@ -0,0 +1,44 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; + +/** + * @title Swap. + * @dev Swap integration for DEX Aggregators. + */ + +// import files +import { SwapHelpers } from "./helpers.sol"; +import { Events } from "./events.sol"; + +abstract contract Swap is SwapHelpers, Events { + /** + * @dev Swap ETH/ERC20_Token using dex aggregators. + * @notice Swap tokens from exchanges like 1INCH, 0x etc, with calculation done off-chain. + * @param _connectors The name of the connectors like 1INCH-A, 0x etc, in order of their priority. + * @param _datas Encoded function call data including function selector encoded with parameters. + */ + function swap(string[] memory _connectors, bytes[] memory _datas) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + (bool success, bytes memory returnData, string memory connector) = _swap( + _connectors, + _datas + ); + + require(success, "swap-Aggregator-failed"); + (string memory eventName, bytes memory eventParam) = abi.decode( + returnData, + (string, bytes) + ); + + _eventName = "LogSwapAggregator(string[],string,string,bytes)"; + _eventParam = abi.encode(_connectors, connector, eventName, eventParam); + } +} + +contract ConnectV2SwapAggregatorFantom is Swap { + string public name = "Swap-Aggregator-v1"; +} diff --git a/contracts/optimism/common/interfaces.sol b/contracts/optimism/common/interfaces.sol index 03211b06..797bce15 100644 --- a/contracts/optimism/common/interfaces.sol +++ b/contracts/optimism/common/interfaces.sol @@ -1,5 +1,6 @@ //SPDX-License-Identifier: MIT pragma solidity ^0.7.0; +pragma abicoder v2; interface TokenInterface { function approve(address, uint256) external; @@ -23,3 +24,7 @@ interface AccountInterface { function disable(address) external; function isAuth(address) external view returns (bool); } + +interface InstaConnectors { + function isConnectors(string[] calldata) external returns (bool, address[] memory); +} \ No newline at end of file diff --git a/contracts/optimism/connectors/swap/events.sol b/contracts/optimism/connectors/swap/events.sol new file mode 100644 index 00000000..45e71522 --- /dev/null +++ b/contracts/optimism/connectors/swap/events.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; +pragma abicoder v2; + +contract Events { + event LogSwapAggregator( + string[] connectors, + string connectorName, + string eventName, + bytes eventParam + ); +} diff --git a/contracts/optimism/connectors/swap/helpers.sol b/contracts/optimism/connectors/swap/helpers.sol new file mode 100644 index 00000000..b9207a26 --- /dev/null +++ b/contracts/optimism/connectors/swap/helpers.sol @@ -0,0 +1,44 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; +pragma abicoder v2; + +import { InstaConnectors } from "../../common/interfaces.sol"; + +contract SwapHelpers { + /** + * @dev Instadapp Connectors Registry + */ + InstaConnectors internal constant instaConnectors = + InstaConnectors(0x127d8cD0E2b2E0366D522DeA53A787bfE9002C14); + + /** + *@dev Swap using the dex aggregators. + *@param _connectors name of the connectors in preference order. + *@param _datas data for the swap cast. + */ + function _swap(string[] memory _connectors, bytes[] memory _datas) + internal + returns ( + bool success, + bytes memory returnData, + string memory connector + ) + { + uint256 _length = _connectors.length; + require(_length > 0, "zero-length-not-allowed"); + require(_datas.length == _length, "calldata-length-invalid"); + + (bool isOk, address[] memory connectors) = instaConnectors.isConnectors( + _connectors + ); + require(isOk, "connector-names-invalid"); + + for (uint256 i = 0; i < _length; i++) { + (success, returnData) = connectors[i].delegatecall(_datas[i]); + if (success) { + connector = _connectors[i]; + break; + } + } + } +} diff --git a/contracts/optimism/connectors/swap/main.sol b/contracts/optimism/connectors/swap/main.sol new file mode 100644 index 00000000..008fa4b9 --- /dev/null +++ b/contracts/optimism/connectors/swap/main.sol @@ -0,0 +1,44 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; + +/** + * @title Swap. + * @dev Swap integration for DEX Aggregators. + */ + +// import files +import { SwapHelpers } from "./helpers.sol"; +import { Events } from "./events.sol"; + +abstract contract Swap is SwapHelpers, Events { + /** + * @dev Swap ETH/ERC20_Token using dex aggregators. + * @notice Swap tokens from exchanges like 1INCH, 0x etc, with calculation done off-chain. + * @param _connectors The name of the connectors like 1INCH-A, 0x etc, in order of their priority. + * @param _datas Encoded function call data including function selector encoded with parameters. + */ + function swap(string[] memory _connectors, bytes[] memory _datas) + external + payable + returns (string memory _eventName, bytes memory _eventParam) + { + (bool success, bytes memory returnData, string memory connector) = _swap( + _connectors, + _datas + ); + + require(success, "swap-Aggregator-failed"); + (string memory eventName, bytes memory eventParam) = abi.decode( + returnData, + (string, bytes) + ); + + _eventName = "LogSwapAggregator(string[],string,string,bytes)"; + _eventParam = abi.encode(_connectors, connector, eventName, eventParam); + } +} + +contract ConnectV2SwapAggregatorOptimism is Swap { + string public name = "Swap-Aggregator-v1"; +} From 3cc14fadce4fdd0d21e7e45f7f548b007d414ade Mon Sep 17 00:00:00 2001 From: Richa-iitr Date: Wed, 15 Jun 2022 20:55:14 +0530 Subject: [PATCH 25/27] tests-opt,arb,ftm --- test/arbitrum/swap/swap-test.ts | 151 +++++++++++++++++++++++++++ test/fantom/swap/swap-test.ts | 175 +++++++++++++++++++++++++++++++ test/optimism/swap/swap-test.ts | 179 ++++++++++++++++++++++++++++++++ 3 files changed, 505 insertions(+) create mode 100644 test/arbitrum/swap/swap-test.ts create mode 100644 test/fantom/swap/swap-test.ts create mode 100644 test/optimism/swap/swap-test.ts diff --git a/test/arbitrum/swap/swap-test.ts b/test/arbitrum/swap/swap-test.ts new file mode 100644 index 00000000..7ea8416e --- /dev/null +++ b/test/arbitrum/swap/swap-test.ts @@ -0,0 +1,151 @@ +import hre from "hardhat"; +import axios from "axios"; +import { expect } from "chai"; +const { ethers } = hre; //check +import { BigNumber } from "bignumber.js"; +import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector"; +import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2"; +import { encodeSpells } from "../../../scripts/tests/encodeSpells"; +import { getMasterSigner } from "../../../scripts/tests/getMasterSigner"; +import { addresses } from "../../../scripts/tests/arbitrum/addresses"; +import { abis } from "../../../scripts/constant/abis"; +import { ConnectV2SwapAggregatorArbitrum__factory } from "../../../typechain"; +import er20abi from "../../../scripts/constant/abi/basics/erc20.json"; +import type { Signer, Contract } from "ethers"; + +describe("Swap | Arbitrum", function () { + const connectorName = "swap-test"; + + let dsaWallet0: Contract; + let wallet0: Signer, wallet1: Signer; + let masterSigner: Signer; + let instaConnectorsV2: Contract; + let connector: Contract; + + before(async () => { + await hre.network.provider.request({ + method: "hardhat_reset", + params: [ + { + forking: { + // @ts-ignore + jsonRpcUrl: hre.config.networks.hardhat.forking.url + } + } + ] + }); + [wallet0, wallet1] = await ethers.getSigners(); + + masterSigner = await getMasterSigner(); + instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); + connector = await deployAndEnableConnector({ + connectorName, + contractArtifact: ConnectV2SwapAggregatorArbitrum__factory, + signer: masterSigner, + connectors: instaConnectorsV2 + }); + console.log("Connector address", connector.address); + }); + + it("Should have contracts deployed.", async function () { + expect(!!instaConnectorsV2.address).to.be.true; + expect(!!connector.address).to.be.true; + expect(!!(await masterSigner.getAddress())).to.be.true; + }); + + describe("DSA wallet setup", function () { + it("Should build DSA v2", async function () { + dsaWallet0 = await buildDSAv2(await wallet0.getAddress()); + console.log(dsaWallet0.address); + expect(!!dsaWallet0.address).to.be.true; + }); + + it("Deposit matic into DSA wallet", async function () { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: ethers.utils.parseEther("10") + }); + + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); + }); + }); + + describe("Main", function () { + it("should swap the tokens", async function () { + let buyTokenAmount1Inch: any; + let buyTokenAmountParaswap: any; + + async function getArg() { + const slippage = 0.5; + /* eth -> dai */ + const sellTokenAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; // eth, decimals 18 + const sellTokenDecimals = 18; + const buyTokenAddress = "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1"; // DAI, decimals 18 + const buyTokenDecimals = 18; + const amount = 1; + + const srcAmount = new BigNumber(amount).times(new BigNumber(10).pow(sellTokenDecimals)).toFixed(0); + + //1inch + const paramDaiUsdc = { + buyToken: buyTokenAddress, + sellToken: sellTokenAddress, + sellAmount: "1000000000000000000", + dsaAddress: dsaWallet0.address + }; + const response1 = await axios.get("https://api.instadapp.io/defi/arbitrum/1inch/swap", { + params: paramDaiUsdc + }); + + const data1 = response1.data; + // console.log(data1); + let unitAmt1Inch = data1.unitAmt; + const calldata1Inch = data1.calldata; + buyTokenAmount1Inch = data1.buyTokenAmount; + console.log(buyTokenAmount1Inch); + + function getCallData(connector: string, unitAmt: any, callData: any) { + var abi = [ + "function swap(address,address,uint256,uint256,bytes,uint256)", + "function sell(address,address,uint256,uint256,bytes,uint256)" + ]; + var iface = new ethers.utils.Interface(abi); + const spell = connector === "1INCH-A" ? "sell" : "swap"; + let data = iface.encodeFunctionData(spell, [ + buyTokenAddress, + sellTokenAddress, + srcAmount, + unitAmt, + callData, + 0 + ]); + return data; + } + let data1Inch = ethers.utils.hexlify(await getCallData("1INCH-A", unitAmt1Inch, calldata1Inch)); + let datas = [data1Inch]; + + let connectors = ["1INCH-A"]; + return [connectors, datas]; + } + + let arg = await getArg(); + const spells = [ + { + connector: connectorName, + method: "swap", + args: arg + } + ]; + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), await wallet1.getAddress()); + const receipt = await tx.wait(); + + const daiToken = await ethers.getContractAt( + er20abi, + "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1" // dai address + ); + + expect(await daiToken.balanceOf(dsaWallet0.address)).to.be.gte(buyTokenAmount1Inch); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(ethers.utils.parseEther("9")); + }); + }); +}); diff --git a/test/fantom/swap/swap-test.ts b/test/fantom/swap/swap-test.ts new file mode 100644 index 00000000..dacfdd02 --- /dev/null +++ b/test/fantom/swap/swap-test.ts @@ -0,0 +1,175 @@ +import hre from "hardhat"; +import axios from "axios"; +import { expect } from "chai"; +const { ethers } = hre; //check +import { BigNumber } from "bignumber.js"; +import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector"; +import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2"; +import { encodeSpells } from "../../../scripts/tests/encodeSpells"; +import { getMasterSigner } from "../../../scripts/tests/getMasterSigner"; +import { addresses } from "../../../scripts/tests/fantom/addresses"; +import { abis } from "../../../scripts/constant/abis"; +import { ConnectV2SwapAggregatorFantom__factory } from "../../../typechain"; +import er20abi from "../../../scripts/constant/abi/basics/erc20.json"; +import type { Signer, Contract } from "ethers"; + +describe("Swap | Fantom", function () { + const connectorName = "swap-test"; + + let dsaWallet0: Contract; + let wallet0: Signer, wallet1: Signer; + let masterSigner: Signer; + let instaConnectorsV2: Contract; + let connector: Contract; + + before(async () => { + await hre.network.provider.request({ + method: "hardhat_reset", + params: [ + { + forking: { + // @ts-ignore + jsonRpcUrl: hre.config.networks.hardhat.forking.url + } + } + ] + }); + [wallet0, wallet1] = await ethers.getSigners(); + + masterSigner = await getMasterSigner(); + instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); + connector = await deployAndEnableConnector({ + connectorName, + contractArtifact: ConnectV2SwapAggregatorFantom__factory, + signer: masterSigner, + connectors: instaConnectorsV2 + }); + console.log("Connector address", connector.address); + }); + + it("Should have contracts deployed.", async function () { + expect(!!instaConnectorsV2.address).to.be.true; + expect(!!connector.address).to.be.true; + expect(!!(await masterSigner.getAddress())).to.be.true; + }); + + describe("DSA wallet setup", function () { + it("Should build DSA v2", async function () { + dsaWallet0 = await buildDSAv2(await wallet0.getAddress()); + console.log(dsaWallet0.address); + expect(!!dsaWallet0.address).to.be.true; + }); + + it("Deposit fantom into DSA wallet", async function () { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: ethers.utils.parseEther("10") + }); + + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); + }); + }); + + describe("Main", function () { + it("should swap the tokens", async function () { + let buyTokenAmountParaswap: any; + + async function getArg() { + const slippage = 0.5; + /* eth -> dai */ + const sellTokenAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; // FTM, decimals 18 + const sellTokenDecimals = 18; + const buyTokenAddress = "0x8D11eC38a3EB5E956B052f67Da8Bdc9bef8Abf3E"; // DAI, decimals 18 + const buyTokenDecimals = 18; + const amount = 1; + + const srcAmount = new BigNumber(amount).times(new BigNumber(10).pow(sellTokenDecimals)).toFixed(0); + + let paraswapUrl1 = `https://apiv5.paraswap.io/prices/`; + let paraswapUrl2 = `https://apiv5.paraswap.io/transactions/250?ignoreChecks=true`; + + //paraswap + let paramsPara = { + srcToken: sellTokenAddress, + destToken: buyTokenAddress, + srcDecimals: sellTokenDecimals, + destDecimals: buyTokenDecimals, + amount: srcAmount, + side: "SELL", + network: 250 + }; + + const priceRoute = (await axios.get(paraswapUrl1, { params: paramsPara })).data.priceRoute; + buyTokenAmountParaswap = priceRoute.destAmount; + let minAmount = new BigNumber(priceRoute.destAmount).times((100 - 1) / 100).toFixed(0); + + let txConfig = { + priceRoute: priceRoute, + srcToken: sellTokenAddress, + destToken: buyTokenAddress, + srcDecimals: sellTokenDecimals, + destDecimals: buyTokenDecimals, + srcAmount: srcAmount, + destAmount: minAmount, + userAddress: dsaWallet0.address + }; + const calldataPara = (await axios.post(paraswapUrl2, txConfig)).data.data; + + let calculateUnitAmt = (buyAmount: any) => { + const buyTokenAmountRes = new BigNumber(buyAmount) + .dividedBy(new BigNumber(10).pow(buyTokenDecimals)) + .toFixed(8); + + let unitAmt: any = new BigNumber(buyTokenAmountRes).dividedBy(new BigNumber(amount)); + + unitAmt = unitAmt.multipliedBy((100 - 1) / 100); + unitAmt = unitAmt.multipliedBy(1e18).toFixed(0); + return unitAmt; + }; + let unitAmtParaswap = calculateUnitAmt(buyTokenAmountParaswap); + + function getCallData(connector: string, unitAmt: any, callData: any) { + var abi = [ + "function swap(address,address,uint256,uint256,bytes,uint256)", + "function sell(address,address,uint256,uint256,bytes,uint256)" + ]; + var iface = new ethers.utils.Interface(abi); + const spell = connector === "1INCH-A" ? "sell" : "swap"; + let data = iface.encodeFunctionData(spell, [ + buyTokenAddress, + sellTokenAddress, + srcAmount, + unitAmt, + callData, + 0 + ]); + return data; + } + let dataPara = ethers.utils.hexlify(await getCallData("PARASWAP-A", unitAmtParaswap, calldataPara)); + let datas = [dataPara]; + + let connectors = ["PARASWAP-A"]; + return [connectors, datas]; + } + + let arg = await getArg(); + const spells = [ + { + connector: connectorName, + method: "swap", + args: arg + } + ]; + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), await wallet1.getAddress()); + const receipt = await tx.wait(); + + const daiToken = await ethers.getContractAt( + er20abi, + "0x8D11eC38a3EB5E956B052f67Da8Bdc9bef8Abf3E" // dai address + ); + + expect(await daiToken.balanceOf(dsaWallet0.address)).to.be.gte(buyTokenAmountParaswap); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(ethers.utils.parseEther("9")); + }); + }); +}); diff --git a/test/optimism/swap/swap-test.ts b/test/optimism/swap/swap-test.ts new file mode 100644 index 00000000..90949d16 --- /dev/null +++ b/test/optimism/swap/swap-test.ts @@ -0,0 +1,179 @@ +import hre from "hardhat"; +import axios from "axios"; +import { expect } from "chai"; +const { ethers } = hre; //check +import { BigNumber } from "bignumber.js"; +import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector"; +import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2"; +import { encodeSpells } from "../../../scripts/tests/encodeSpells"; +import { getMasterSigner } from "../../../scripts/tests/getMasterSigner"; +import { addresses } from "../../../scripts/tests/optimism/addresses"; +import { abis } from "../../../scripts/constant/abis"; +import { ConnectV2SwapAggregatorOptimism__factory } from "../../../typechain"; +import er20abi from "../../../scripts/constant/abi/basics/erc20.json"; +import type { Signer, Contract } from "ethers"; + +describe("Swap | Optimism", function () { + const connectorName = "swap-test"; + + let dsaWallet0: Contract; + let wallet0: Signer, wallet1: Signer; + let masterSigner: Signer; + let instaConnectorsV2: Contract; + let connector: Contract; + + before(async () => { + await hre.network.provider.request({ + method: "hardhat_reset", + params: [ + { + forking: { + // @ts-ignore + jsonRpcUrl: hre.config.networks.hardhat.forking.url + } + } + ] + }); + [wallet0, wallet1] = await ethers.getSigners(); + + masterSigner = await getMasterSigner(); + instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); + connector = await deployAndEnableConnector({ + connectorName, + contractArtifact: ConnectV2SwapAggregatorOptimism__factory, + signer: masterSigner, + connectors: instaConnectorsV2 + }); + console.log("Connector address", connector.address); + }); + + it("Should have contracts deployed.", async function () { + expect(!!instaConnectorsV2.address).to.be.true; + expect(!!connector.address).to.be.true; + expect(!!(await masterSigner.getAddress())).to.be.true; + }); + + describe("DSA wallet setup", function () { + it("Should build DSA v2", async function () { + dsaWallet0 = await buildDSAv2(await wallet0.getAddress()); + console.log(dsaWallet0.address); + expect(!!dsaWallet0.address).to.be.true; + }); + + it("Deposit matic into DSA wallet", async function () { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: ethers.utils.parseEther("10") + }); + + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10")); + }); + }); + + describe("Main", function () { + it("should swap the tokens", async function () { + let buyTokenAmountZeroX: any; + let buyTokenAmount1Inch: any; + let buyTokenAmountParaswap: any; + + async function getArg() { + const slippage = 0.5; + /* eth -> dai */ + const sellTokenAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; // eth, decimals 18 + const sellTokenDecimals = 18; + const buyTokenAddress = "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1"; // DAI, decimals 6 + const buyTokenDecimals = 18; + const amount = 1; + + const srcAmount = new BigNumber(amount).times(new BigNumber(10).pow(sellTokenDecimals)).toFixed(0); + + let zeroXUrl = `https://optimism.api.0x.org/swap/v1/quote`; + + //zeroX + const paramsZeroX = { + buyToken: "DAI", + sellToken: "ETH", + sellAmount: "1000000000000000000" // Always denominated in wei + }; + + const responseZeroX = await axios.get(zeroXUrl, { params: paramsZeroX }).then((data: any) => data); + buyTokenAmountZeroX = responseZeroX.data.buyAmount; + const calldataZeroX = responseZeroX.data.data; + + //1inch + const paramDaiUsdc = { + buyToken: buyTokenAddress, + sellToken: sellTokenAddress, + sellAmount: "1000000000000000000", + dsaAddress: dsaWallet0.address + }; + const response1 = await axios.get("https://api.instadapp.io/defi/optimism/1inch/swap", { + params: paramDaiUsdc + }); + + const data1 = response1.data; + let unitAmt1Inch = data1.unitAmt; + const calldata1Inch = data1.calldata; + buyTokenAmount1Inch = data1.buyTokenAmount; + console.log(buyTokenAmount1Inch); + + let calculateUnitAmt = (buyAmount: any) => { + const buyTokenAmountRes = new BigNumber(buyAmount) + .dividedBy(new BigNumber(10).pow(buyTokenDecimals)) + .toFixed(8); + + let unitAmt: any = new BigNumber(buyTokenAmountRes).dividedBy(new BigNumber(amount)); + + unitAmt = unitAmt.multipliedBy((100 - 1) / 100); + unitAmt = unitAmt.multipliedBy(1e18).toFixed(0); + return unitAmt; + }; + let unitAmt0x = calculateUnitAmt(buyTokenAmountZeroX); + let unitAmtParaswap = calculateUnitAmt(buyTokenAmountParaswap); + + function getCallData(connector: string, unitAmt: any, callData: any) { + var abi = [ + "function swap(address,address,uint256,uint256,bytes,uint256)", + "function sell(address,address,uint256,uint256,bytes,uint256)" + ]; + var iface = new ethers.utils.Interface(abi); + const spell = connector === "1INCH-A" ? "sell" : "swap"; + let data = iface.encodeFunctionData(spell, [ + buyTokenAddress, + sellTokenAddress, + srcAmount, + unitAmt, + callData, + 0 + ]); + return data; + } + let data1Inch = ethers.utils.hexlify(await getCallData("1INCH-A", unitAmt1Inch, calldata1Inch)); + let dataZeroX = ethers.utils.hexlify(await getCallData("ZEROX-A", unitAmt0x, calldataZeroX)); + let datas = [data1Inch]; + + let connectors = ["1INCH-A"]; + return [connectors, datas]; + } + + let arg = await getArg(); + const spells = [ + { + connector: connectorName, + method: "swap", + args: arg + } + ]; + const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), await wallet1.getAddress()); + const receipt = await tx.wait(); + + const daiToken = await ethers.getContractAt( + er20abi, + "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1" // dai address + ); + + expect(await daiToken.balanceOf(dsaWallet0.address)).to.be.gte(buyTokenAmount1Inch); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte(ethers.utils.parseEther("9")); + }); + }); +}); From e8ee380321a8ef8c741b3e77e2493fa9d50868b6 Mon Sep 17 00:00:00 2001 From: Richa-iitr Date: Wed, 15 Jun 2022 20:56:46 +0530 Subject: [PATCH 26/27] fantom test support --- scripts/tests/addLiquidity.ts | 4 +- scripts/tests/buildDSAv2.ts | 2 + scripts/tests/deployAndEnableConnector.ts | 2 + scripts/tests/fantom/addresses.ts | 11 ++++ scripts/tests/fantom/tokens.ts | 64 +++++++++++++++++++++++ scripts/tests/getMasterSigner.ts | 2 + scripts/tests/run-tests.ts | 2 +- 7 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 scripts/tests/fantom/addresses.ts create mode 100644 scripts/tests/fantom/tokens.ts diff --git a/scripts/tests/addLiquidity.ts b/scripts/tests/addLiquidity.ts index 057f384b..7263e786 100644 --- a/scripts/tests/addLiquidity.ts +++ b/scripts/tests/addLiquidity.ts @@ -6,6 +6,7 @@ import { tokenMapping as polygonMapping } from "./polygon/tokens"; import { tokenMapping as avalancheMapping } from "./avalanche/tokens"; import { tokenMapping as optimismMapping } from "./optimism/tokens"; import { tokenMapping as arbitrumMapping } from "./arbitrum/tokens"; +import { tokenMapping as fantomMapping } from "./fantom/tokens"; const mineTx = async (tx: any) => { await (await tx).wait(); @@ -16,7 +17,8 @@ const tokenMapping: Record> = { polygon: polygonMapping, avalanche: avalancheMapping, optimism: optimismMapping, - arbitrum: arbitrumMapping + arbitrum: arbitrumMapping, + fantom: fantomMapping }; export async function addLiquidity(tokenName: string, address: any, amt: any) { diff --git a/scripts/tests/buildDSAv2.ts b/scripts/tests/buildDSAv2.ts index e54dd68d..311a5f0e 100644 --- a/scripts/tests/buildDSAv2.ts +++ b/scripts/tests/buildDSAv2.ts @@ -4,6 +4,7 @@ import { addresses as addressesPolygon } from "./polygon/addresses"; import { addresses as addressesArbitrum } from "./arbitrum/addresses"; import { addresses as addressesAvalanche } from "./avalanche/addresses"; import { addresses as addressesOptimism } from "./optimism/addresses"; +import { addresses as addressesFantom } from "./fantom/addresses"; import { addresses } from "./mainnet/addresses"; import { abis } from "../constant/abis"; import { abi } from "../../deployements/mainnet/Implementation_m1.sol/InstaImplementationM1.json"; @@ -13,6 +14,7 @@ function getAddress(network: string | undefined) { else if (network === "arbitrum") return addressesArbitrum.core.instaIndex; else if (network === "avalanche") return addressesAvalanche.core.instaIndex; else if (network === "optimism") return addressesOptimism.core.instaIndex; + else if (network === "fantom") return addressesFantom.core.instaIndex; else return addresses.core.instaIndex; } diff --git a/scripts/tests/deployAndEnableConnector.ts b/scripts/tests/deployAndEnableConnector.ts index fe3d71dd..7a713c69 100644 --- a/scripts/tests/deployAndEnableConnector.ts +++ b/scripts/tests/deployAndEnableConnector.ts @@ -4,6 +4,7 @@ import { abis } from "../constant/abis"; import { addresses as addressesArbitrum } from "./arbitrum/addresses"; import { addresses as addressesAvalanche } from "./avalanche/addresses"; import { addresses as addressesOptimism } from "./optimism/addresses"; +import { addresses as addressesFantom } from "./fantom/addresses"; import hre from "hardhat"; import type { Signer, Contract } from "ethers"; @@ -24,6 +25,7 @@ function getAddress(network: string | undefined) { else if (network === "arbitrum") return addressesArbitrum; else if (network === "avalanche") return addressesAvalanche; else if (network === "optimism") return addressesOptimism; + else if (network === "fantom") return addressesFantom; else return addresses; } diff --git a/scripts/tests/fantom/addresses.ts b/scripts/tests/fantom/addresses.ts new file mode 100644 index 00000000..53113e1d --- /dev/null +++ b/scripts/tests/fantom/addresses.ts @@ -0,0 +1,11 @@ +export const addresses: Record = { + connectors: { + // basic: "0x6214f9c4F9700fc7a50B5f9aEEB819d647406Ac7", + // auth: "0xD6daA927ad756a4022858dddcc4E26137b30DB4D", + // "INSTAPOOL-A": "0x8f1e38c53af7bD2b2bE01b9580911b7Cca504F1b", + }, + core: { + connectorsV2: "0x819910794a030403F69247E1e5C0bBfF1593B968", + instaIndex: "0x2fa042BEEB7A40A7078EaA5aC755e3842248292b", + }, +}; diff --git a/scripts/tests/fantom/tokens.ts b/scripts/tests/fantom/tokens.ts new file mode 100644 index 00000000..17523914 --- /dev/null +++ b/scripts/tests/fantom/tokens.ts @@ -0,0 +1,64 @@ +import { Provider } from "@ethersproject/abstract-provider"; +import { Signer } from "@ethersproject/abstract-signer"; +import { ethers } from "hardhat"; + +const mineTx = async (tx: any) => { + await (await tx).wait(); +}; + +export const tokens = { + ftm: { + type: "token", + symbol: "FTM", + name: "Fantom", + address: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + decimals: 18, + }, + dai: { + type: "token", + symbol: "DAI", + name: "DAI Stable", + address: "0x8D11eC38a3EB5E956B052f67Da8Bdc9bef8Abf3E", + decimals: 18, + }, + usdc: { + type: "token", + symbol: "USDC", + name: "USD Coin", + address: "0x04068DA6C83AFCFA0e13ba15A6696662335D5B75", + decimals: 6, + }, +}; + +export const tokenMapping: Record = { + usdc: { + impersonateSigner: "0x4188663a85C92EEa35b5AD3AA5cA7CeB237C6fe9", + address: "0x04068DA6C83AFCFA0e13ba15A6696662335D5B75", + abi: [ + "function mint(address _to, uint256 _amount) external returns (bool);", + ], + process: async function (owner: Signer | Provider, to: any, amt: any) { + const contract = new ethers.Contract(this.address, this.abi, owner); + + await mineTx(contract.mint(to, amt)); + }, + }, + dai: { + impersonateSigner: "0x9bdB521a97E95177BF252C253E256A60C3e14447", + address: "0x8D11eC38a3EB5E956B052f67Da8Bdc9bef8Abf3E", + abi: ["function transfer(address to, uint value)"], + process: async function (owner: Signer | Provider, to: any, amt: any) { + const contract = new ethers.Contract(this.address, this.abi, owner); + await mineTx(contract.transfer(to, amt)); + }, + }, + // inst: { + // impersonateSigner: "0x75e89d5979E4f6Fba9F97c104c2F0AFB3F1dcB88", + // address: "0x6f40d4a6237c257fff2db00fa0510deeecd303eb", + // abi: ["function transfer(address to, uint value)"], + // process: async function (owner: Signer | Provider, address: any, amt: any) { + // const contract = new ethers.Contract(this.address, this.abi, owner); + // await mineTx(contract.transfer(address, amt)); + // }, + // }, +}; diff --git a/scripts/tests/getMasterSigner.ts b/scripts/tests/getMasterSigner.ts index 040e4e4f..f97a21d0 100644 --- a/scripts/tests/getMasterSigner.ts +++ b/scripts/tests/getMasterSigner.ts @@ -4,6 +4,7 @@ import { addresses as addressesPolygon } from "./polygon/addresses"; import { addresses as addressesArbitrum } from "./arbitrum/addresses"; import { addresses as addressesAvalanche } from "./avalanche/addresses"; import { addresses as addressesOptimism } from "./optimism/addresses"; +import { addresses as addressesFantom } from "./fantom/addresses"; import { abis } from "../constant/abis"; function getAddress(network: string | undefined) { @@ -11,6 +12,7 @@ function getAddress(network: string | undefined) { else if (network === "arbitrum") return addressesArbitrum.core.instaIndex; else if (network === "avalanche") return addressesAvalanche.core.instaIndex; else if (network === "optimism") return addressesOptimism.core.instaIndex; + else if (network === "fantom") return addressesFantom.core.instaIndex; else return addresses.core.instaIndex; } diff --git a/scripts/tests/run-tests.ts b/scripts/tests/run-tests.ts index 5b2f22bd..d8edc081 100644 --- a/scripts/tests/run-tests.ts +++ b/scripts/tests/run-tests.ts @@ -12,7 +12,7 @@ async function testRunner() { name: "chain", message: "What chain do you want to run tests on?", type: "list", - choices: ["mainnet", "polygon", "avalanche", "arbitrum", "optimism"], + choices: ["mainnet", "polygon", "avalanche", "arbitrum", "optimism", "fantom"], }, ]); const testsPath = join(__dirname, "../../test", chain); From a2cba36e768e47632d7bc36bfd6604444ae18a7a Mon Sep 17 00:00:00 2001 From: Richa-iitr Date: Wed, 15 Jun 2022 20:57:13 +0530 Subject: [PATCH 27/27] minor change --- test/mainnet/swap/swap-test.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/test/mainnet/swap/swap-test.ts b/test/mainnet/swap/swap-test.ts index b7f38fd3..3c9102f1 100644 --- a/test/mainnet/swap/swap-test.ts +++ b/test/mainnet/swap/swap-test.ts @@ -81,7 +81,7 @@ describe("Swap | Mainnet", function () { /* eth -> dai */ const sellTokenAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; // eth, decimals 18 const sellTokenDecimals = 18; - const buyTokenAddress = "0x6B175474E89094C44Da98b954EedeAC495271d0F"; // DAI, decimals 6 + const buyTokenAddress = "0x6B175474E89094C44Da98b954EedeAC495271d0F"; // DAI, decimals 18 const buyTokenDecimals = 18; const amount = 1; @@ -169,7 +169,14 @@ describe("Swap | Mainnet", function () { ]; var iface = new ethers.utils.Interface(abi); const spell = connector === "1INCH-A" ? "sell" : "swap"; - let data = iface.encodeFunctionData(spell, [buyTokenAddress, sellTokenAddress, srcAmount, unitAmt, callData, 0]); + let data = iface.encodeFunctionData(spell, [ + buyTokenAddress, + sellTokenAddress, + srcAmount, + unitAmt, + callData, + 0 + ]); return data; } let data1Inch = ethers.utils.hexlify(await getCallData("1INCH-A", unitAmt1Inch, calldata1Inch)); @@ -178,7 +185,6 @@ describe("Swap | Mainnet", function () { let datas = [data1Inch, dataPara, dataZeroX]; let connectors = ["1INCH-A", "PARASWAP-A", "ZEROX-A"]; - return [connectors, datas]; }