diff --git a/contracts/mainnet/connectors/euler/helpers.sol b/contracts/mainnet/connectors/euler/helpers.sol index a885d34e..f3779ea4 100644 --- a/contracts/mainnet/connectors/euler/helpers.sol +++ b/contracts/mainnet/connectors/euler/helpers.sol @@ -1,13 +1,9 @@ //SPDX-License-Identifier: MIT pragma solidity ^0.7.0; -import "./interface.sol"; +import "./variables.sol"; import { Basic } from "../../common/basic.sol"; -contract Helpers is Basic { - - address internal constant EULER_MAINNET = 0x27182842E098f60e3D576794A5bFFb0777E025d3; - address internal constant EULER_MAINNET_MARKETS = 0x3520d5a913427E6F0D6A83E07ccD4A4da316e4d3; - IEulerMarkets markets = IEulerMarkets(EULER_MAINNET_MARKETS); +contract Helpers is Basic, Variables { /** * @dev Get total collateral balance for an asset diff --git a/contracts/mainnet/connectors/euler/interface.sol b/contracts/mainnet/connectors/euler/interface.sol index dbd38561..57519465 100644 --- a/contracts/mainnet/connectors/euler/interface.sol +++ b/contracts/mainnet/connectors/euler/interface.sol @@ -1,5 +1,6 @@ //SPDX-License-Identifier: MIT pragma solidity ^0.7.0; +pragma experimental ABIEncoderV2; interface IEulerMarkets { function enterMarket(uint subAccountId, address newMarket) external; @@ -26,3 +27,29 @@ interface IEulerDToken { function balanceOf(address account) external view returns (uint); function transfer(address to, uint amount) external returns (bool); } + +interface IEulerSwap { + struct SwapUniExactInputSingleParams { + uint subAccountIdIn; + uint subAccountIdOut; + address underlyingIn; + address underlyingOut; + uint amountIn; + uint amountOutMinimum; + uint deadline; + uint24 fee; + uint160 sqrtPriceLimitX96; + } + + struct Swap1InchParams { + uint subAccountIdIn; + uint subAccountIdOut; + address underlyingIn; + address underlyingOut; + uint amount; + uint amountOutMinimum; + bytes payload; + } + + function swap1Inch(Swap1InchParams memory) external; +} diff --git a/contracts/mainnet/connectors/euler/main.sol b/contracts/mainnet/connectors/euler/main.sol index 420c4218..2dd82c6f 100644 --- a/contracts/mainnet/connectors/euler/main.sol +++ b/contracts/mainnet/connectors/euler/main.sol @@ -49,13 +49,11 @@ abstract contract Euler is Helpers { approve(tokenContract, EULER_MAINNET, _amt); IEulerEToken eToken = IEulerEToken(markets.underlyingToEToken(_token)); - - eToken.deposit(subAccount, (_amt * eToken.decimals()));//0 for primary + eToken.deposit(subAccount, _amt);//0 for primary if (enableCollateral) { markets.enterMarket(subAccount, _token); } - setUint(setId, _amt); _eventName = "LogDeposit(uint256,address,uint256,bool,uint256,uint256)"; @@ -89,7 +87,6 @@ abstract contract Euler is Helpers { TokenInterface tokenContract = TokenInterface(_token); - IEulerMarkets markets = IEulerMarkets(markets); IEulerEToken eToken = IEulerEToken(markets.underlyingToEToken(_token)); uint256 initialBal = tokenContract.balanceOf(address(this)); @@ -132,7 +129,7 @@ abstract contract Euler is Helpers { address _token = isEth ? wethAddr : token; IEulerDToken borrowedDToken = IEulerDToken(markets.underlyingToDToken(_token)); - borrowedDToken.borrow(subAccount, (amt * borrowedDToken.decimals())); + borrowedDToken.borrow(subAccount, amt); convertWethToEth(isEth, TokenInterface(_token), _amt); @@ -202,7 +199,6 @@ abstract contract Euler is Helpers { returns (string memory _eventName, bytes memory _eventParam) { uint256 _amt = getUint(getId, amt); - //should have some deposit first? bool isEth = token == ethAddr ? true : false; address _token = isEth ? wethAddr : token; IEulerEToken eToken = IEulerEToken(markets.underlyingToEToken(_token)); @@ -338,4 +334,8 @@ abstract contract Euler is Helpers { _eventName = "LogDTransfer(uint256,uint256,address,uint256,uint256,uint256)"; _eventParam = abi.encode(subAccount1, subAccount2, token, _amt, getId, setId); } -} \ No newline at end of file +} + +contract ConnectV2Euler is Euler { + string public constant name = "Euler-v1.0"; +} diff --git a/contracts/mainnet/connectors/euler/variables.sol b/contracts/mainnet/connectors/euler/variables.sol new file mode 100644 index 00000000..0c083be4 --- /dev/null +++ b/contracts/mainnet/connectors/euler/variables.sol @@ -0,0 +1,8 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; +import "./interface.sol"; + +contract Variables { + address internal constant EULER_MAINNET = 0x27182842E098f60e3D576794A5bFFb0777E025d3; + IEulerMarkets internal constant markets = IEulerMarkets(0x3520d5a913427E6F0D6A83E07ccD4A4da316e4d3); +} diff --git a/test/mainnet/euler/euler.test.ts b/test/mainnet/euler/euler.test.ts new file mode 100644 index 00000000..bd8e8c02 --- /dev/null +++ b/test/mainnet/euler/euler.test.ts @@ -0,0 +1,144 @@ +import { expect } from "chai"; +import hre from "hardhat"; +import { abis } from "../../../scripts/constant/abis"; +import { addresses } from "../../../scripts/tests/mainnet/addresses"; +import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector"; +import { getMasterSigner } from "../../../scripts/tests/getMasterSigner"; +import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2"; +import { ConnectV2Euler, ConnectV2Euler__factory, IERC20__factory } from "../../../typechain"; +import { parseEther } from "@ethersproject/units"; +import { encodeSpells } from "../../../scripts/tests/encodeSpells"; +import { tokens } from "../../../scripts/tests/mainnet/tokens"; +import { constants } from "../../../scripts/constant/constant"; +import { addLiquidity } from "../../../scripts/tests/addLiquidity"; +const { ethers } = hre; +import type { Signer, Contract } from "ethers"; + +describe("Euler", function () { + const connectorName = "EULER-TEST-A"; + let connector: any; + + let wallet0: Signer, wallet1:Signer; + let dsaWallet0: any; + let instaConnectorsV2: Contract; + let masterSigner: Signer; + + const USDC = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' + const ACC_USDC = '0xe78388b4ce79068e89bf8aa7f218ef6b9ab0e9d0' + const Usdc = ethers.utils.parseUnits('5000', 6) + + before(async () => { + await hre.network.provider.request({ + method: "hardhat_reset", + params: [ + { + forking: { + // @ts-ignore + jsonRpcUrl: hre.config.networks.hardhat.forking.url, + blockNumber: 15078000, + }, + }, + ], + }); + [wallet0, wallet1] = await ethers.getSigners(); + masterSigner = await getMasterSigner(); + instaConnectorsV2 = await ethers.getContractAt( + abis.core.connectorsV2, + addresses.core.connectorsV2 + ); + connector = await deployAndEnableConnector({ + connectorName, + contractArtifact: ConnectV2Euler__factory, + signer: masterSigner, + connectors: instaConnectorsV2, + }); + console.log("Connector address", connector.address); + }); + + it("should have contracts deployed", async () => { + 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(wallet0.getAddress()); + expect(!!dsaWallet0.address).to.be.true; + }); + + it("Deposit ETH into DSA wallet", async function () { + await wallet0.sendTransaction({ + to: dsaWallet0.address, + value: parseEther("10"), + }); + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte( + parseEther("10") + ); + }); + + it("Deposit USDC into DSA wallet", async function () { + const token_usdc = new ethers.Contract( + USDC, + IERC20__factory.abi, + ethers.provider, + ) + + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [ACC_USDC], + }) + + const signer_usdc = await ethers.getSigner(ACC_USDC) + await token_usdc.connect(signer_usdc).transfer(wallet0.getAddress(), Usdc) + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_USDC], + }) + + await token_usdc.connect(wallet0).transfer(dsaWallet0.address, Usdc); + + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [ACC_USDC], + }) + expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte( + parseEther("10") + ); + }); + }); + + describe("Main", function () { + beforeEach(async function () { + const spells = [ + { + connector: connectorName, + method: "deposit", + args: ["0", tokens.usdc.address, "10000000", "true", "0", "0"], + }, + ]; + + const tx = await dsaWallet0 + .connect(wallet0) + .cast(...encodeSpells(spells), wallet1.getAddress()); + + await tx.wait(); + }); + it("Should borrow DAI into DSA wallet", async function () { + const spells = [ + { + connector: connectorName, + method: "borrow", + args: ["0", tokens.dai.address, "1000000", "0", "0"], + }, + ]; + + const tx = await dsaWallet0 + .connect(wallet0) + .cast(...encodeSpells(spells), wallet1.getAddress()); + + await tx.wait(); + }) + }); +});