
JustLend DAO完成首轮JST回购
作者:Beosin安全研究专家Sivan
闪电贷是一种无抵押借款的服务,由于其拥有无需抵押便能借出资金的特性,使得资金利用率大大提高。在常见的以太坊闪电贷中,是通过以太坊交易机制来保证可以进行无抵押借出资金,以太坊中一个交易可以包含很多步骤,如:借款、兑换、使用、还款等,所有的步骤相辅相成,若其中某一个或多个步骤出现错误,都将导致本次的整个交易被回滚。
随着区块链生态发展,出现了大量公链以及合约编程语言,例如:除了Solidity之外最常见的Move和Rust,这些合约编程语言有本质上的区别,框架与编程理念也有所不同,本篇文章我们来对比一下Solidity闪电贷实现方式与Move以及Rust闪电贷实现方式有何不同,同时可以初步了解一下各种语言的编程理念。
Solidity相关闪电贷:
Solidity的闪电贷是基于Solidity支持动态调用这一特性来设计的,何为动态调用,也就是solidity支持在调用一个函数的过程中,动态传入需要调用的地址,如下例代码。每次调用都可以传入不同的地址,根据这个特点,便出现了solidity闪电贷的实现逻辑。
function callfun(address addr) public { addr.call();}
如下代码,将闪电贷抽象成了3个核心功能,
1、首先直接将资金发送给调用者;
2、再调用调用者合约,从而让调用者使用这些资金;
3、调用者使用结束,检查是否归还资金以及手续费,如果检查失败则回滚交易。(此处也可以直接使用transferfrom函数将调用则资金转移回来)
function flashloan(uint amount, address to) { transfer( to, amount); // 发送资金给调用者 to.call();//调用调用者的合约函数 check();//检查是否归还资金}
如下图,为Solidity语言中闪电贷的实现流程:

下列代码为真实项目Uniswap闪电贷逻辑。代码示例:
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external lock {require(amount0Out > 0 || amount1Out > 0, 'UniswapV2: INSUFFICIENT_OUTPUT_AMOUNT');(uint112 _reserve0, uint112 _reserve1,) = getReserves();require(amount0Out < _reserve0 && amount1Out < _reserve1, 'UniswapV2: INSUFFICIENT_LIQUIDITY');uint balance0;uint balance1;{address _token0 = token0;address _token1 = token1;require(to != _token0 && to != _token1, 'UniswapV2: INVALID_TO');/**将资金转给用户**/if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out);if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out);/**调用用户指定的目标函数**/if (data.length > 0) IUniswapV2Callee(to).uniswapV2Call(msg.sender, amount0Out, amount1Out, data);balance0 = IERC20(_token0).balanceOf(address(this));balance1 = IERC20(_token1).balanceOf(address(this));}uint amount0In = balance0 > _reserve0 - amount0Out ? balance0 - (_reserve0 - amount0Out) : 0;uint amount1In = balance1 > _reserve1 - amount1Out ? balance1 - (_reserve1 - amount1Out) : 0;require(amount0In > 0 || amount1In > 0, 'UniswapV2: INSUFFICIENT_INPUT_AMOUNT');{uint balance0Adjusted = balance0.mul(1000).sub(amount0In.mul(3));uint balance1Adjusted = balance1.mul(1000).sub(amount1In.mul(3));/**检查用户是否归还资金以及手续费**/require(balance0Adjusted.mul(balance1Adjusted)>=uint(_reserve0).mul(_reserve1).mul(1000**2), 'UniswapV2: K');}_update(balance0, balance1, _reserve0, _reserve1);emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);}
Move相关闪电贷:
Move闪电贷和solidity设计思想不同,move中没有动态调用这一个特性,在所有函数调用过程之前,都必须确定调用流程,明确调用合约地址是什么,所以无法像solidity里面那样动态传入地址再进行调用。
那么move能实现闪电贷功能吗?当然可以,move的特性使得人们设计出与solidity实现方式不同的闪电贷。
免责声明:数字资产交易涉及重大风险,本资料不应作为投资决策依据,亦不应被解释为从事投资交易的建议。请确保充分了解所涉及的风险并谨慎投资。OKEx学院仅提供信息参考,不构成任何投资建议,用户一切投资行为与本站无关。

和全球数字资产投资者交流讨论
扫码加入OKEx社群
industry-frontier