文章目录
基于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的接口,不然就锁里面拿不出来了。
- 最好有脚本程序配合,发现套利机会直接发起交易套利。