这是一个非常有意思的概念。
参考资料
- 图解 DeFi 闪电贷原理与常见用例
- 智能合约 + 闪电贷 初体验
- 闪电贷套利机器人开发教程(一)
- 闪电贷套利机器人开发教程(二)
- 如何使用Aave进行闪电贷
- 崔棉大师教你玩转闪电贷(上集)
- 崔棉大师教你玩转闪电贷(下集)
- flashloan
- pancake-bakery-arbitrage
讲解
其实上面的参考资料已经讲的非常好了,我在这里再讲一下,并且说一下上面那些资料中没说的细节。
本闪电贷主要是针对通过 swap 进行借贷。
关于借贷方式请参考
这里我们以 pancakeswap 作为例子。
首先参考 pair 中的一段代码。
PancakePair.sol
1 | // this low-level function should be called from a contract which performs important safety checks |
第 12 和 第 13 行
if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens
if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens如果 amount0Out、amount1Out 大于 0,就会先把币打到账户上。
注意,这里用的方法是
_safeTransfer即,假设池子中只有 500 BNB ,你不能借 600 BNB。
所以,在借的时候,一定要区分好,你借的币是 token0 还是 token1。
接着,第 14 行
if (data.length > 0) IPancakeCallee(to).pancakeCall(msg.sender, amount0Out, amount1Out, data);如果 data 的长度大于 0,就会执行
IPancakeCallee(to).pancakeCall(msg.sender, amount0Out, amount1Out, data);这个方法。data 是一个 bytes,无所谓是什么,只需要让它的长度大于 0 就好了。
这里要注意 IPancakeCallee(to) 这个 to 是你的合约地址,所以,如果你要是有 pancakeCall 这个方法,这个时候会调用该方法。
所以说,假设你实现了这个方法,那么,进入到你账户执行的时候,由于你之前已经借出了 token ,所以,可以在 pancakeCall 这个方法中继续使用。
其他的 dex 平台原理差不多都是这样子,但是,方法名可能不一样,比如 biswap 叫 bisCall 。
执行 swap
我们借出币是通过 pair 借出的。
我们拿着借出的币,进行 dex 的 swapToken 方法。
可以参考
OK,这里假设你已经兑换了。并且
AB你借出了BBC你兑换了CCA你兑换了A
那么,如何归还呢?
归还
对于 AB 来说,如果你借出 B ,你是归还 A 还是 B 呢?
答案是,两个都可以。
如果你借出 B,归还 B,那么,你只是拿着这个 B 执行了执行了一圈然后还回去而已,你借出 50 个 B 还回 50 个 B 就好了。
如果你借出 B ,归还的是 A,那么,相当于你执行了 swapTokenForToken,用 A 去购买 B。只不过,B 是先打给你,然后你后付的 A 而已。但是,这个时候你就要付手续费了。因为,你本质上就是执行了 swapTokenForToken 的操作,所以要收取手续费。
那么,如何归还,归还给谁?
只需要对 AB 的 pair 转对应数量的 A 即可。
参考
1 | uint[] memory backamounts = functionContract(backRouter).getAmountsIn(receiveAmountIn, backPaths); |
其中
receiveAmountIn- 借出
B的数量
- 借出
backPathsA兑换B的路径
backTokenA的合约地址
functionContract- 接口合约,放置了一些接口函数
其中 getAmountsIn 的方法,就可以知道你借出多少的 B,需要归还多少的 A。
上面的就是归还了。
具体细节可以参考一下 pancakeswap 的公开的方法。
下面说一下整体的手续费的计算,以
AB你借出了BBC你兑换了CCA你兑换了A
来说,实际上,上面相当于执行了 3 次 swapTokenForToken 方法。也就是会收 3 次手续费。
盈利
后面就把归还后剩余的 A 发送到相应账户就好了。
我将所有的代码放在了
相对于公开的代码,我写的代码可以适应于大部分的场景。