# 开始我的第一个闪电贷

## 第一步，添加所需要的接口

根据自己需求添加:

```
import { ILendingPoolAddressesProvider } from "./ILendingPoolAddressesProvider.sol"; // 通过该接口获取LendingPool地址
import { FlashLoanReceiverBase } from "./FlashLoanReceiverBase.sol";   // 接收闪电贷金额的合约必须通过IFlashLoanReceiver 接口实现的 executeOperation() 
import { ILendingPool } from "./ILendingPool.sol";        // 通过该接口调用flashloan
import { IERC20 } from "./IERC20.sol";                    // 涉及到ERC20代币所需
```

{% hint style="info" %}
请注意闪电贷将扣取一定量的手续费，平台手续费为0.09%
{% endhint %}

## 第二步，设置FlashLoanReceiverBase

{% code title="FlashLoanReceiverBase.sol" %}

```bash

abstract contract FlashLoanReceiverBase is IFlashLoanReceiver {
  using SafeERC20 for IERC20;
  using SafeMath for uint256;

  ILendingPoolAddressesProvider public immutable override ADDRESSES_PROVIDER;
  ILendingPool public immutable override LENDING_POOL;

  constructor(ILendingPoolAddressesProvider provider) public {
    ADDRESSES_PROVIDER = provider;
    LENDING_POOL = ILendingPool(provider.getLendingPool());
  }
}
```

{% endcode %}

另请注意，由于欠款将从你的策略同中提取，您的合同必须为 LendingPool 提供补贴以提取这些资金以偿还闪贷债务 + 保费。

## 第三步，完善策略合约

接收闪贷金额的合约必须通过实现相关的 executeOperation() 函数。 在下面的示例中，我们策略将继承FlashLoanReceiverBase。&#x20;

{% hint style="info" %}
以下代码未提供策略代码，仅贷款还款操作，往合约转代币才可成功完成一笔闪电贷。
{% endhint %}

```bash

contract MyfirstFlashLoan is FlashLoanReceiverBase {

    /**
        在你的策略合约收到闪电贷金额后将调用此函数
     */
    function executeOperation(
        address[] calldata assets,
        uint256[] calldata amounts,
        uint256[] calldata premiums,
        address initiator,
        bytes calldata params
    )
        external
        override
        returns (bool)
    {

        // 该策略合约此时已获得所需资金
        // 策略逻辑可以写在这里
        
        // 在上述逻辑的最后，该合约欠闪电贷额度 + 手续费。
        // 因此，请确保您的合同有足够的资金来偿还这些金额。
        
        // 授权 LendingPool 合约提前欠款额度
        for (uint i = 0; i < assets.length; i++) {
            uint amountOwing = amounts[i].add(premiums[i]);
            IERC20(assets[i]).approve(address(LENDING_POOL), amountOwing);
        }
        
        return true;
    }
    
    function myfirstFlashLoanCall() public {
        // 接收贷款地址
        address receiverAddress = address(this);

        // 贷款币币种,仅贷一个币种
        address[] memory assets = new address[](1);
        assets[0] = address(INSERT_ASSET_ONE_ADDRESS);

        // 贷款币数量
        uint256[] memory amounts = new uint256[](1);
        amounts[0] = INSERT_ASSET_ONE_AMOUNT;

        // 贷款模式
        uint256[] memory modes = new uint256[](1);
        modes[0] = INSERT_ASSET_ONE_MODE;

        address onBehalfOf = address(this);
        bytes memory params = "";
        uint16 referralCode = 0;

        LENDING_POOL.flashLoan(
            receiverAddress,
            assets,
            amounts,
            modes,
            onBehalfOf,
            params,
            referralCode
        );
    }
}
```

## 第四步，合约部署

部署工具可自由选择，remix，truffle，hardhat

部署参数初始值设置为LendingPoolAddressesProvider合约地址:

0xF7CeaE542b00d8CBa6D7bcb3a5AbcA7A2E19829a&#x20;

MyfirstFlashLoan合约已部署在heco链上并在浏览器验证，任何人都可以调用，准备好手续费即可

{% embed url="<https://hecoinfo.com/address/0xea58a27da4f1df9cac54207ce82935017af4534a#code>" %}

## 第五步，调用闪电贷

调用myfirstFlashLoanCall(address asset, uint256 num, uint256 mode)函数:

参考交易：

{% embed url="<https://hecoinfo.com/tx/0xc073b742baa262bddd0a5574f658d73a1fa44cdff2006f0da4e6b707bc6257fe>" %}

## 编码和解码参数

如果您想将参数传递到您的闪电贷函数中，您首先需要对它们进行编码，然后在您的 executeOperation() 中对其进行解码。

#### **编码**

如果您要进行编码，则可以使用内置的`abi.encode()`:

```bash
// Encoding an address and a uint
bytes memory params = abi.encode(address(this), 1234);
```

####

如果是链下操作，例如 `web3.js` 可以调用[`abi.encodeParameters()`](https://web3js.readthedocs.io/en/v1.3.0/web3-eth-abi.html?highlight=encodeParameters#encodeparameters):

```javascript
const params = web3.eth.abi.encodeParameters(
	["bytes32"],
	[
		web3.utils.utf8ToHex("some_value")
	]
)
```

#### 解码

在你的 executeOperation() 中解码时，你需要使用 `abi.decode()`:

```javascript
(bytes32 someValue) = abi.decode(params, (bytes32));
```

用法可参考闪电贷清算合约代码

## 预留提币接口

```javascript
function rescueTokens(IERC20 token) external onlyOwner {
    token.transfer(owner(), token.balanceOf(address(this)));
  }
```

##


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://xiangganzi.gitbook.io/flashloan/shan-dian-dai-jiao-cheng/di-yi-bi-shan-dian-dai.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
