# 用 Python 开发 DeFi 去中心化借贷应用（下）

By [quantbang](https://paragraph.com/@quantbang) · 2022-03-24

---

![](https://storage.googleapis.com/papyrus_images/58a8a1dcf46b0604a65911945b2f7cebc935c1973bf5199d608e03cf23f74863.jpg)

传统的金融科技世界充满了使用户能够制作复杂算法交易模型和系统的工具。而去中心化金融 (DeFi) 也同样为用户和开发人员提供了相同的工具，围绕底层金融协议和工具具有更高的透明度和灵活性，从而催生了 DeFi 量化交易和应用开发。DeFi 开发人员和 DeFi quants 甚至可以利用这些工具的衍生品，并将它们组合成新的服务，以建立在传统金融科技世界中没有的创新金融头寸。DeFi 开发人员的基本工具之一是能够以非托管方式借出和借入加密货币资产。阅读本文前请先查看：\\

[用 Python 开发 DeFi 去中心化借贷应用（上）](http://mp.weixin.qq.com/s?__biz=MzAxMjUyNDQ5OA%3D%3D&chksm=806e7382b719fa94b728a56f3034317036624771ca2ce60db4715b808cfcf3c1af5b21e7aa35&idx=1&mid=2653576511&scene=21&sn=f801e6fd57da1609a8a4f361d8fbc6cb#wechat_redirect)

[用 Python 开发 DeFi 去中心化借贷应用（中）](http://mp.weixin.qq.com/s?__biz=MzAxMjUyNDQ5OA%3D%3D&chksm=806e7325b719fa337d5e3a56fe324d6bcb24281d8e06871f6643ad3611d3a869aa332fce352b&idx=1&mid=2653576600&scene=21&sn=773dff58760c033db1426a9db08af622#wechat_redirect)

**获取可借资产价值**

现在，当我们借款时，我们会被告知我们拥有的以 ETH 表示的资产数量。然而，也许我们想借用一个不同的代币，比如 DAI。如果我们要以 ETH 为抵押借入 DAI，我们首先要得到 ETH -> DAI 的兑换率。

Chainlink 是 DeFi 和智能合约生态系统中获取数据和执行外部计算的标准，也是 Aave 用来获取费率的标准！他们有一个价格 Oracle 部分，描述了如何通过他们的智能合约 API 获取 Chainlink 数据。如果你学会了一般地使用 Chainlink 数据，你可以跨协议使用它，即使他们没有使用 Chainlink，或者没有价格预言机机制！

Chainlink 通过去中心化的预言机网络获取数据，其中多个节点将跨多个 API 和服务的数据聚合到一个去中心化的来源，该来源经过验证并记录在链上供我们使用。我们可以在 data.chain.link 页面或文档上看到当前可用数据提要的列表。如您所知，数据是大多数量化系统、算法交易者和整个 DeFi 生态系统的支柱，因此您要始终确保自己是从去中心化系统中提取的，这样您就可以获得最准确、最可靠和最安全的数据。

此外，如果您不想要某些数据，您可以从任何 API 调用您的智能合约，获得可证明的随机数以及许多其他不同的服务。这些使得智能合约数据安全、可靠和去中心化。

但是让我们回到 Python！

我们有一个名为 `get_asset_price` 的函数，它从 `dai_eth_price_feed` 中读取数据，如下所示：

    def get_asset_price():
       # For mainnet we can just do:
       # return Contract(f"{pair}.data.eth").latestAnswer() / 1e8
       dai_eth_price_feed = interface.AggregatorV3Interface(
           config["networks"][network.show_active()]["dai_eth_price_feed"]
       )
       latest_price = Web3.fromWei(dai_eth_price_feed.latestRoundData()[1], "ether")
       print(f"The DAI/ETH price is {latest_price}")
       return float(latest_price)
    

我们从接口中提取的 Chainlink 合约 `AggregatorV3Interface` 已存储在我们的配置文件中。在该合约中，我们调用 `latestRoundData` 函数。

你会注意到我们也不需要为这个做一个交易，这也是一个视图函数！

你会看到通过`brownie`获得 Chainlink 数据价格的另一种方式是：

    from brownie import Contract
    print(Contract(f"{pair}.data.eth").latestAnswer() / 1e8)
    

这是使用 ENS 来获取价格对的地址。ENS 是一种获取智能合约地址并使其可读的方法。例如，您可以执行以下操作：

    print(Contract(f"eth-usd.data.eth").latestAnswer() / 1e8)
    

以美元为单位获取以太坊的最新价格。请注意，ENS 仅适用于主网网络，因此您在运行 `brownie` 时必须使用 `--network mainnet` 或 `--network mainnet-fork`。

**将价值转换为借用**

现在我们有了抵押品和我们想要借入的资产之间的转换率，我们可以设置一个变量来确定我们想要借入多少。

    amount_erc20_to_borrow = (1 / erc20_eth_price) * (borrowable_eth * 0.95)
    

我们得到 ETH/DAI 价格的倒数，并将其乘以我们可以借入的金额（以 ETH 为单位）。为了安全起见，我们还将其乘以 0.95。然后，我们调用借用函数！

    borrow_erc20(lending_pool, amount_erc20_to_borrow, account)
    

    def borrow_erc20(lending_pool, amount, account, erc20_address=None):
       erc20_address = (
           erc20_address
           if erc20_address
           else config["networks"][network.show_active()]["aave_dai_token"]
       )
       # 1 is stable interest rate
       # 0 is the referral code
       transaction = lending_pool.borrow(
           erc20_address,
           Web3.toWei(amount, "ether"),
           1,
           0,
           account.address,
           {"from": account},
       )
       transaction.wait(1)
       print(f"Congratulations! We have just borrowed {amount}")
    

借用函数需要几个参数：

•资产的地址（在我们的例子中是 DAI 代币）•我们要借的金额，单位为 wei•`interestRateMode`，（0, 1, 2: 1 是稳定的，2 是可变的……现在不用担心 0）•推荐码（忽略）•`onBehalfOf` 值，即谁将承担债务

让我们看一下 Etherscan 上这笔交易的样本，以了解刚刚发生的事情。

![](https://storage.googleapis.com/papyrus_images/265cc75d3207e0159737f8ed24f27e58567a63130ffaba33b8b67a697fdec53e.png)

按顺序，代币转移的方向是：

•Aave 协议正在铸造一些 aDAI•我们的钱包正在铸造一些 `Aave Stable Debt Bearing DAI`•我们的钱包获得了一些 DAI

重要说明：Aave 有时会更改其测试网token。通过检查已部署的合约地址，确保您拥有正确的 testnet DAI 地址。并检查官方 json 列表。

这一次，我们得到了一种不同类型的计息代币，一种债务代币。这是我们必须偿还的金额，并且与 `aToken` 一样，它的价值也会增长。如果你欠更多的债务（用这个债务代币表示），有人可以清算你并拿走你所有的抵押品！所以要警惕你有多少债务。

通过添加新的代币地址，我们可以再次在我们的 MetaNask 中看到借入的资产。我们还可以通过添加债务token地址来查看我们的债务。

这才是真正有趣的地方。现在最简单的卖空方法之一就是出售我们的资产。如果资产价格下跌，我们将不得不偿还比借入的更少的钱。

然而，我越来越担心我会被清算。让我们偿还我们的债务。

**偿还我们的债务**

我们想弄清楚我们欠了多少，然后偿还！我们可以用这些函数做到这一点：

    borrowable_eth, total_debt_eth = get_borrowable_data(lending_pool, account)
    amount_erc20_to_repay = (1 / erc20_eth_price) * (total_debt_eth * 0.95)
    repay_all(amount_erc20_to_repay, lending_pool, account)
    

    def repay_all(amount, lending_pool, account):
       approve_erc20(
           Web3.toWei(amount, "ether"),
           lending_pool,
           config["networks"][network.show_active()]["aave_dai_token"],
           account,
       )
       tx = lending_pool.repay(
           config["networks"][network.show_active()]["aave_dai_token"],
           Web3.toWei(amount, "ether"),
           1,
           account.address,
           {"from": account},
       )
       tx.wait(1)
       print("Repaid!")
    

**总结**

我们已经完成了与 Aave 合作的所有步骤。

•抵押•拿出贷款•偿还贷款

您接下来还可以做一些事情，比如：

•使用 Synthetix 或 Bancor 等协议交易资产•申请闪贷•了解如何质押和参与治理

您还可以学习如何成为智能合约开发人员，在 Solidity 中构建去中心化协议，并发现智能合约的广泛功能。你的旅程才刚刚开始！

---

*Originally published on [quantbang](https://paragraph.com/@quantbang/python-defi-4)*
