Skip to content

Commit

Permalink
Merge pull request #47 from yuichiroaoki/without-1inch
Browse files Browse the repository at this point in the history
Without 1inch
  • Loading branch information
yuichiroaoki authored May 29, 2022
2 parents f388897 + a7bf624 commit beef3b2
Show file tree
Hide file tree
Showing 16 changed files with 250 additions and 1,745 deletions.
2 changes: 1 addition & 1 deletion constants/bsc.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ERC20Map, PoolMap, RouterMap } from "./addresses";

export const BSC_WHALE = "0x5c9F6cA2e81EaEad3D9aFf26efca7Fa307403297";
export const BSC_WHALE = "0xB224228b0Fe71ceBf95EE25339166CD626759b52";

export const bscTokens: ERC20Map = {
DAI: "0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3",
Expand Down
45 changes: 12 additions & 33 deletions contracts/Flashloan.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,10 @@ contract Flashloan is IFlashloan, DodoBase, FlashloanValidation, Withdraw {
me: msg.sender,
flashLoanPool: params.flashLoanPool,
loanAmount: params.loanAmount,
firstRoutes: params.firstRoutes,
secondRoutes: params.secondRoutes
routes: params.routes
})
);
address loanToken = RouteUtils.getInitialToken(params.firstRoutes[0]);
address loanToken = RouteUtils.getInitialToken(params.routes[0]);
IDODO(params.flashLoanPool).flashLoan(
IDODO(params.flashLoanPool)._BASE_TOKEN_() == loanToken
? params.loanAmount
Expand All @@ -63,17 +62,14 @@ contract Flashloan is IFlashloan, DodoBase, FlashloanValidation, Withdraw {
(FlashCallbackData)
);

address loanToken = RouteUtils.getInitialToken(decoded.firstRoutes[0]);
address toToken = RouteUtils.getInitialToken(decoded.secondRoutes[0]);
address loanToken = RouteUtils.getInitialToken(decoded.routes[0]);

require(
IERC20(loanToken).balanceOf(address(this)) >= decoded.loanAmount,
"Failed to borrow loan token"
);

routeLoop(decoded.firstRoutes, decoded.loanAmount);
uint256 toTokenAmount = IERC20(toToken).balanceOf(address(this));
routeLoop(decoded.secondRoutes, toTokenAmount);
routeLoop(decoded.routes, decoded.loanAmount);

emit SwapFinished(
loanToken,
Expand Down Expand Up @@ -106,37 +102,20 @@ contract Flashloan is IFlashloan, DodoBase, FlashloanValidation, Withdraw {
function hopLoop(Route memory route, uint256 totalAmount) internal {
uint256 amountIn = totalAmount;
for (uint256 i = 0; i < route.hops.length; i++) {
amountIn = swapLoop(route.hops[i], amountIn);
amountIn = pickProtocol(route.hops[i], amountIn);
}
}

function swapLoop(Hop memory hop, uint256 totalAmount)
function pickProtocol(Hop memory hop, uint256 amountIn)
internal
checkTotalSwapPart(hop.swaps)
returns (uint256)
returns (uint256 amountOut)
{
uint256 amountOut = 0;
for (uint256 i = 0; i < hop.swaps.length; i++) {
uint256 amountIn = Part.partToAmountIn(
hop.swaps[i].part,
totalAmount
);
amountOut += pickProtocol(hop.swaps[i], amountIn, hop.path);
}
return amountOut;
}

function pickProtocol(
Swap memory swap,
uint256 amountIn,
address[] memory path
) internal checkRouteProtocol(swap) returns (uint256 amountOut) {
if (swap.protocol == 0) {
amountOut = uniswapV3(swap.data, amountIn, path);
} else if (swap.protocol < 8) {
amountOut = uniswapV2(swap.data, amountIn, path);
if (hop.protocol == 0) {
amountOut = uniswapV3(hop.data, amountIn, hop.path);
} else if (hop.protocol < 8) {
amountOut = uniswapV2(hop.data, amountIn, hop.path);
} else {
amountOut = dodoV2Swap(swap.data, amountIn, path);
amountOut = dodoV2Swap(hop.data, amountIn, hop.path);
}
}

Expand Down
14 changes: 8 additions & 6 deletions contracts/base/DodoBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,12 @@ contract DodoBase is IFlashloan {
) internal virtual {}

modifier checkParams(FlashParams memory params) {
address loanToken = RouteUtils.getInitialToken(params.firstRoutes[0]);
bool loanEqBase = loanToken == IDODO(params.flashLoanPool)._BASE_TOKEN_();
bool loanEqQuote = loanToken == IDODO(params.flashLoanPool)._QUOTE_TOKEN_();
address loanToken = RouteUtils.getInitialToken(params.routes[0]);
bool loanEqBase = loanToken ==
IDODO(params.flashLoanPool)._BASE_TOKEN_();
bool loanEqQuote = loanToken ==
IDODO(params.flashLoanPool)._QUOTE_TOKEN_();
require(loanEqBase || loanEqQuote, "Wrong flashloan pool address");
_;
}
}
_;
}
}
14 changes: 0 additions & 14 deletions contracts/base/FlashloanValidation.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,4 @@ abstract contract FlashloanValidation {
require(totalPart == 10000, "Route part error");
_;
}

modifier checkTotalSwapPart(IFlashloan.Swap[] memory swaps) {
uint16 totalPart = 0;
for (uint256 i = 0; i < uint256(swaps.length); i++) {
totalPart += swaps[i].part;
}
require(totalPart == 10000, "Swap part error");
_;
}

modifier checkRouteProtocol(IFlashloan.Swap memory swap) {
require(MAX_PROTOCOL >= swap.protocol, "Wrong protocol");
_;
}
}
13 changes: 3 additions & 10 deletions contracts/interfaces/IFlashloan.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,9 @@
pragma solidity ^0.8.0;

interface IFlashloan {
struct Swap {
struct Hop {
uint8 protocol;
uint16 part;
bytes data;
}

struct Hop {
Swap[] swaps;
address[] path;
}

Expand All @@ -21,15 +16,13 @@ interface IFlashloan {
struct FlashParams {
address flashLoanPool;
uint256 loanAmount;
Route[] firstRoutes;
Route[] secondRoutes;
Route[] routes;
}

struct FlashCallbackData {
address me;
address flashLoanPool;
uint256 loanAmount;
Route[] firstRoutes;
Route[] secondRoutes;
Route[] routes;
}
}
218 changes: 13 additions & 205 deletions test/bsc/flashloan.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,42 +50,25 @@ describe("Flashloan on BSC", () => {
{
flashLoanPool: dodoV2Pool.ETH_BUSD,
loanAmount: getBigNumber(1000),
firstRoutes: [
routes: [
{
hops: [
{
swaps: [
{
// sushiswap
protocol: 1,
part: 10000,
data: ethers.utils.defaultAbiCoder.encode(
["address"],
[uniswapRouter.BSC_SUSHISWAP]
),
},
],
// sushiswap
protocol: 1,
data: ethers.utils.defaultAbiCoder.encode(
["address"],
[uniswapRouter.BSC_SUSHISWAP]
),
path: [bscTokens.BUSD, bscTokens.USDC],
},
],
part: 10000,
},
],
secondRoutes: [
{
hops: [
{
swaps: [
{
// pancakeswap
protocol: 1,
part: 10000,
data: ethers.utils.defaultAbiCoder.encode(
["address"],
[uniswapRouter.BSC_PANCAKESWAP]
),
},
],
// pancakeswap
protocol: 1,
data: ethers.utils.defaultAbiCoder.encode(
["address"],
[uniswapRouter.BSC_PANCAKESWAP]
),
path: [bscTokens.USDC, bscTokens.BUSD],
},
],
Expand All @@ -101,180 +84,5 @@ describe("Flashloan on BSC", () => {
const balance = await BUSD.balanceOf(owner.address);
expect(balance.gt(getBigNumber(0))).to.be.true;
});

// it("USDC - WETH - WBTC", async () => {
// await expect(
// Flashloan.dodoFlashLoan(
// {
// flashLoanPool: dodoV2Pool.WETH_USDC,
// loanAmount: getBigNumber(1000, 6),
// firstRoutes: [
// {
// hops: [
// {
// swaps: [
// {
// protocol: 1,
// part: 10000,
// data: ethers.utils.defaultAbiCoder.encode(
// ["address"],
// [findRouterFromProtocol(1)]
// ),
// },
// ],
// path: [ERC20Token.USDC.address, ERC20Token.WETH.address],
// },
// {
// swaps: [
// {
// protocol: 2,
// part: 10000,
// data: ethers.utils.defaultAbiCoder.encode(
// ["address"],
// [findRouterFromProtocol(1)]
// ),
// },
// ],
// path: [ERC20Token.WETH.address, ERC20Token.WBTC.address],
// },
// ],
// part: 10000,
// },
// ],
// secondRoutes: [
// {
// hops: [
// {
// swaps: [
// {
// protocol: 3,
// part: 10000,
// data: ethers.utils.defaultAbiCoder.encode(
// ["address"],
// [findRouterFromProtocol(3)]
// ),
// },
// ],
// path: [ERC20Token.WBTC.address, ERC20Token.WETH.address],
// },
// {
// swaps: [
// {
// protocol: 3,
// part: 10000,
// data: ethers.utils.defaultAbiCoder.encode(
// ["address"],
// [findRouterFromProtocol(3)]
// ),
// },
// ],
// path: [ERC20Token.WETH.address, ERC20Token.USDC.address],
// },
// ],
// part: 10000,
// },
// ],
// },
// { gasLimit: 1000000 }
// )
// )
// .emit(Flashloan, "SwapFinished")
// .emit(Flashloan, "SentProfit");
// const balance = await USDC.balanceOf(owner.address);
// expect(balance.gt(getBigNumber(0))).to.be.true;
// });

// it("should execute a flashloan with multihop swaps.", async () => {
// await expect(
// Flashloan.dodoFlashLoan(
// {
// flashLoanPool: dodoV2Pool.WETH_USDC,
// loanAmount: getBigNumber(1000, 6),
// firstRoutes: [
// {
// hops: [
// {
// swaps: [
// {
// protocol: 1,
// part: 5000,
// data: ethers.utils.defaultAbiCoder.encode(
// ["address"],
// [findRouterFromProtocol(4)]
// ),
// },
// {
// protocol: 2,
// part: 5000,
// data: ethers.utils.defaultAbiCoder.encode(
// ["address"],
// [findRouterFromProtocol(5)]
// ),
// },
// ],
// path: [bscTokens.USDC, bscTokens.DAI],
// },
// {
// swaps: [
// {
// protocol: 2,
// part: 9000,
// data: ethers.utils.defaultAbiCoder.encode(
// ["address"],
// [findRouterFromProtocol(1)]
// ),
// },
// {
// protocol: 3,
// part: 1000,
// data: ethers.utils.defaultAbiCoder.encode(
// ["address"],
// [findRouterFromProtocol(2)]
// ),
// },
// ],
// path: [bscTokens.DAI, bscTokens.WETH],
// },
// ],
// part: 10000,
// },
// ],
// secondRoutes: [
// {
// hops: [
// {
// swaps: [
// {
// protocol: 1,
// part: 10000,
// data: ethers.utils.defaultAbiCoder.encode(
// ["address"],
// [findRouterFromProtocol(3)]
// ),
// },
// ],
// path: [bscTokens.WETH, bscTokens.USDC],
// },
// ],
// part: 10000,
// },
// ],
// },
// { gasLimit: 1000000 }
// )
// )
// .emit(Flashloan, "SwapFinished")
// .emit(Flashloan, "SentProfit");
// const balance = await USDC.balanceOf(owner.address);
// expect(balance.gt(getBigNumber(0))).to.be.true;
// expect(
// (await DAI.balanceOf(Flashloan.address)).lt(ethers.BigNumber.from(1000))
// ).to.be.true;
// expect(
// (await WETH.balanceOf(Flashloan.address)).lt(
// ethers.BigNumber.from(1000)
// )
// ).to.be.true;
// });
});
});
Loading

0 comments on commit beef3b2

Please sign in to comment.