复制成功

分享至

主页 > 数字货币 >

Solidity闪电贷实现方式与Move以及Rust闪电贷实现方式有何不同?

2023.10.26

作者: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语言中闪电贷的实现流程:

Solidity闪电贷实现方式与Move以及Rust闪电贷实现方式有何不同?

下列代码为真实项目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全球社群

和全球数字资产投资者交流讨论

扫码加入OKEx社群

相关推荐

industry-frontier