文章目錄
基於DYDX閃電貸在Cofix和Uniswap之間套利
因爲在以太坊中的交易屬性,在一筆交易中能夠借出大量資金進行操做(不能超過gaslimit限制)。因此當各個交易平臺有利差的時候能夠進行套利(無風險套利),避免了準備大量資金。git
相關項目
Cofix
github:https://github.com/Computable-Financegithub
coifx中調用了NEST預言機的價格,完成作市、交易的操做而且去中心化。算法
Uniswap
github:https://github.com/Uniswap/uniswap-v2-coreapp
Uniswap根據交易擬合算法來完成交易,目前鎖倉量最大的去中心化交易平臺。oop
NEST
github:https://github.com/NEST-Protocolui
使用雙向報價機制,能夠在以太坊上生成去中心化的價格。this
這幾個項目以後會單獨細說,本篇只講述如何組合各個合約進行套利spa
流程
1.閃電貸WETH
2.WETH換ETH
3.ETH換USDT
4.USDT換ETH
5.ETH換WETH
6.WETH還款
DYDX
套利合約
WETH
Cofix
Uniswap
還款後剩餘資金爲所的利潤code
套利合約
github:https://github.com/MLY0813/FlashSwapForCofixAndUni/blob/main/Contract/Flash_Swap.soltoken
核心方法
// 實現操做 function callFunction( address sender, Account.Info memory account, bytes memory data ) public { MyCustomData memory mcd = abi.decode(data, (MyCustomData)); uint256 tokenBalanceBefore = IERC20(mcd.token).balanceOf(address(this)); // money // WETH->ETH WETH9(WETHAddress).withdraw(tokenBalanceBefore); // ETH->USDT uint256 loopTimes = address(this).balance.div(cofixETHSapn); for(uint256 i = 0; i < loopTimes; i++) { CoFiXRouter(cofixRouter).swapExactETHForTokens{ value:cofixETHSapn}(USDTAddress,cofixETHSapn.sub(nestPrice),1,address(this), address(this), uint256(block.timestamp).add(100)); } // USDT->ETH uint256 usdtBalance = IERC20(USDTAddress).balanceOf(address(this)); address[] memory uniData = new address[](2); uniData[0] = address(0xdAC17F958D2ee523a2206206994597C13D831ec7); uniData[1] = address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); UniswapV2Router(uniRouter).swapExactTokensForETH(usdtBalance,1,uniData,address(this),uint256(block.timestamp).add(100)); // ETH->WETH WETH9(WETHAddress).deposit{ value:tokenBalanceBefore.add(2)}; uint256 balOfLoanedToken = IERC20(mcd.token).balanceOf(address(this)); require( balOfLoanedToken >= mcd.repayAmount, "Not enough funds to repay dydx loan!" ); }
callFunction方法會在調用DYDX閃電貸過程當中被回調,在方法中實現收到貸款資金後須要的進行的操做。
1.WETH兌換成ETH
WETH9(WETHAddress).withdraw(tokenBalanceBefore);
2.ETH 在Cofix中兌換成USDT
uint256 loopTimes = address(this).balance.div(cofixETHSapn); for(uint256 i = 0; i < loopTimes; i++) { CoFiXRouter(cofixRouter).swapExactETHForTokens{ value:cofixETHSapn}(USDTAddress,cofixETHSapn.sub(nestPrice),1,address(this), address(this), uint256(block.timestamp).add(100)); }
這裏使用了循環操做,由於cofix中有衝擊成本的限制。單筆大額資金是虧錢的,因此要分紅小部分資金進行兌換。
3.USDT 在Uniswap中兌換成ETH
uint256 usdtBalance = IERC20(USDTAddress).balanceOf(address(this)); address[] memory uniData = new address[](2); uniData[0] = address(0xdAC17F958D2ee523a2206206994597C13D831ec7); uniData[1] = address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); UniswapV2Router(uniRouter).swapExactTokensForETH(usdtBalance,1,uniData,address(this),uint256(block.timestamp).add(100));
4.ETH兌換成WETH
WETH9(WETHAddress).deposit{ value:tokenBalanceBefore.add(2)};
注意dydx還款的時候須要加2wei的資金
整個操做完成後剩餘的ETH就是本身的了
function initiateFlashLoan(uint256 _amount) external { ISoloMargin solo = ISoloMargin(dydxAddress); uint256 marketId = _getMarketIdFromTokenAddress(dydxAddress, WETHAddress); uint256 repayAmount = _getRepaymentAmountInternal(_amount); IERC20(WETHAddress).approve(dydxAddress, repayAmount); Actions.ActionArgs[] memory operations = new Actions.ActionArgs[](3); operations[0] = _getWithdrawAction(marketId, _amount); operations[1] = _getCallAction( abi.encode(MyCustomData({ token: WETHAddress, repayAmount: repayAmount})) ); operations[2] = _getDepositAction(marketId, repayAmount); Account.Info[] memory accountInfos = new Account.Info[](1); accountInfos[0] = _getAccountInfo(); solo.operate(accountInfos, operations); }
使用dydx閃電貸的代碼,傳入參數就是想借多少WETH。大部分代碼都是按照dydx固定的參數拼接數據。
注意事項
- 只有出現利差的時候閃電貸套利纔有效,這種機會不多,可是也沒什麼成本。
- cofix交易會挖出cofi,合約中須要有取出cofi的接口,不然就鎖裏面拿不出來了。
- 最好有腳本程序配合,發現套利機會直接發起交易套利。