如何在Blast上构建自动生息合约

本文介绍了Blast L2区块链项目,它通过为ETH和稳定币存款提供原生收益而闻名。文章详细讲解了如何在Blast上创建、部署自动生息的保险库合约,包括Blast的独特功能、开发者设置、智能合约开发和部署,以及如何与已部署的保险库合约进行交互。

概述

目前大多数区块链都要求用户质押他们的代币或运行验证器,以便从协议中获得原生收益。Blast 是一个 Layer 2 (L2) 区块链项目,以其为已存入的 ETH 和稳定币提供原生收益的创新方法而闻名。在本指南中,你将了解更多关于 Blast 的信息,然后学习如何使用 Hardhat 在 Blast 上创建、部署和交互自动收益保管库合约。

你需要什么

你将做什么

  • 了解 Blast 区块链
  • 构建一个自动收益保管库智能合约
  • 在 Blast 区块链上部署智能合约
  • 与你部署的保管库合约交互

什么是 Blast?

Blast 是一个 EVM 兼容的、乐观 rollup 的 L2 区块链。它的独特之处在于原生整合了 ETH 质押和真实世界资产 (RWA) 协议的收益,为 ETH 提供 4% 的基准收益,为稳定币提供 5% 的基准收益。这种收益整合旨在抵消通货膨胀损失,并支持在其他 L2 上不可行的新型 DApp 商业模式。

让我们深入了解 Blast 的运作方式,以及它为何成为开发者和投资者的首选。

Blast 的独特功能

  1. 自动 Rebase: Blast 在其 L2 平台上为 ETH、WETH (Wrapped ETH) 和 USDB (Blast 的原生稳定币) 具有独特的自动 rebase 功能。这种 rebase 使这些资产能够无缝地从收益生成中受益,无论对于外部拥有的账户 (EOA) 还是智能合约。与 ETH 相比,ETH 的合约默认禁用收益,而 WETH 和 USDB 账户默认自动为 EOA 和智能合约生成收益。

  2. L1 质押收益: 在以太坊上海升级之后,Blast 利用来自 L1 质押的 ETH 收益(最初通过 Lido),并通过在 L2 上 rebase ETH 将其转移给用户。

  3. 稳定币的 T-Bill 收益: 桥接到 Blast 的稳定币将转换为 USDB,后者从 MakerDAO 的 T-Bill 协议中获得收益。这种机制允许生成稳定币收益。

  4. Gas 收入分享: 与其他 L2 不同,Blast 与 DApp 开发者分享净 gas 收入,提供额外的收入来源或补贴用户 gas 费用的选项。

开发者设置

你需要一个 API 端点来与 Blast 区块链通信。为此,与公共 API 端点相比,QuickNode 等服务提供更快、更可靠的 RPC 连接。在此处免费注册 (here),并为 Blast Sepolia 测试网创建一个端点。

QuickNode 端点

保留 HTTP Provider URL 以供稍后在合约部署中使用。

QuickNode 多链水龙头

在本指南中,我们将使用 Blast Sepolia 测试网。因此,你需要获得一些测试 ETH。

如果你使用你的 QuickNode 账户登录或发送一条推文,你可以获得额外的 ETH。

在下一节中,我们将开始使用 Hardhat 开发我们的自动收益保管库合约。

智能合约开发

项目设置

创建一个名为 Vault 的目录并安装所需的依赖项:

mkdir Vault && cd Vault
npm init -y
npm install --save-dev hardhat
npm install dotenv @nomicfoundation/hardhat-verify
npx hardhat init

在 Hardhat 提示时选择 Create a TypeScript project。此外,当被要求安装 @nomicfoundation/hardhat-toolbox 时,请说 Yes

在你的项目目录中创建一个 .env 文件。

环境变量用于存储敏感数据,例如密码、API 凭据和其他不应直接写入代码的信息。

echo > .env

如下修改你的 .env 文件。

YOUR_PRIVATE_KEYYOUR_QUICKNODE_BLAST_SEPOLIA_ENDPOINT_URL 占位符替换为你的钱包的私钥和你的 QuickNode Blast Sepolia 端点 HTTP URL。

PRIVATE_KEY="YOUR_PRIVATE_KEY"
QUICKNODE_ENDPOINT="YOUR_QUICKNODE_BLAST_SEPOLIA_ENDPOINT_URL"

如果你不知道如何获取你的私钥,请点击 here

此说明是为 MetaMask 准备的。

找你的私钥:

  • 点击浏览器上 MetaMask 的图标,一个程式化的狐狸头。如果没有看到,请检查浏览器的 扩展程序 页面。
  • 点击 符号,然后点击 账户详情
  • 然后,点击 显示私钥 并按照说明进行操作。

MetaMask 私钥

然后,如下配置你的 hardhat.config.ts 文件。任何与 Hardhat 相关的设置,例如网络、账户和 Solidity 版本,都在此文件中定义。

要阅读代码的解释 (强烈推荐),请点击 here

此代码是为 Blast 区块链量身定制的 Hardhat 项目的配置设置。

  1. 网络配置: networks 属性定义了两个环境 - 用于 Sepolia 测试网的 blast_sepolia 和使用分叉的本地开发环境的 hardhat。Sepolia 配置包括用于交易的 QuickNode 端点 URL 和私钥,以及指定的 gas 价格。本地环境配置 (hardhat) 设置了从特定区块号使用相同的 QuickNode 端点进行分叉。

  2. Etherscan 集成: 在 etherscan 下,虽然不需要唯一的 API 密钥,但它必须有一个值。因此,blast_sepolia 网络的 API 密钥设置为占位符。customChains 数组包括 blast_sepolia 网络的自定义配置,指定其链 ID 和 API 和区块浏览器的 URL。具体来说,customChains 中的 apiURL 指定了 API 服务的端点(在本例中为 https://api.routescan.io),Hardhat 可以使用该端点与指定的网络(此处为 blast_sepolia 测试网)进行交互。这允许与区块链进行无缝交互,并通过 Hardhat 验证 Blast 测试网上的合约。

import { HardhatUserConfig } from 'hardhat/config'
import '@nomicfoundation/hardhat-toolbox'
import '@nomicfoundation/hardhat-verify'
require('dotenv').config()

const config: HardhatUserConfig = {
    solidity: '0.8.20',
    networks: {
        // for Sepolia testnet
        blast_sepolia: {
            url: process.env.QUICKNODE_ENDPOINT as string,
            accounts: [process.env.PRIVATE_KEY as string],
            gasPrice: 1000000000,
        },
        // for local dev environment
        hardhat: {
            forking: {
                enabled: true,
                url: process.env.QUICKNODE_ENDPOINT as string,
                blockNumber: 423000,
            },
        },
    },
    etherscan: {
        apiKey: {
            blast_sepolia: 'blast_sepolia', // although a unique API key is not required, it must have a value, so just set a placeholder
        },
        customChains: [
            {
                network: 'blast_sepolia',
                chainId: 168587773,
                urls: {
                    apiURL:
                        'https://api.routescan.io/v2/network/testnet/evm/168587773/etherscan',
                    browserURL: 'https://testnet.blastscan.io',
                },
            },
        ],
    },
}

export default config

在 Blast 上构建智能合约

现在我们已经掌握了基础知识,让我们开始为 Blast 区块链构建我们的自动收益保管库智能合约。如果你是 Solidity 的新手,请查看我们 全面的初学者友好的 Solidity 指南

虽然用户的 ETH 余额会自动获得 ETH 收益,但智能合约具有三种用于 rebase 的收益模式。

  • Void (DEFAULT): ETH 余额永远不会改变;不赚取收益
  • Automatic: 原生 ETH 余额 rebase(仅增加)
  • Claimable: ETH 余额永远不会改变;收益单独累积

在本指南中,我们将选择收益模式为 automatic。因此,由于收益将自动添加,因此合约的 ETH 余额将自动增加。

智能合约必须与位于 0x4300000000000000000000000000000000000002 的 Blast 收益合约交互才能更改其收益模式 [source]。由于我们与 Blast 智能合约交互,我们需要将 Blast 智能合约的功能定义为一个 接口。为此,让我们在 contracts 目录中创建一个文件夹 interfaces,并在其中创建一个文件 IBlast.sol

在 Solidity 中,I 前缀用于将 Solidity 文件标识为 接口。因此,IBlast 文件是 Blast 合约的 接口 文件。

mkdir contracts/interfaces
echo > contracts/interfaces/IBlast.sol

打开 IBlast.sol 文件并如下修改。

// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

enum YieldMode {
    AUTOMATIC,
    VOID,
    CLAIMABLE
}

enum GasMode {
    VOID,
    CLAIMABLE
}

interface IBlast{
    // configure
    function configureContract(address contractAddress, YieldMode _yield, GasMode gasMode, address governor) external;
    function configure(YieldMode _yield, GasMode gasMode, address governor) external;

    // base configuration options
    function configureClaimableYield() external;
    function configureClaimableYieldOnBehalf(address contractAddress) external;
    function configureAutomaticYield() external;
    function configureAutomaticYieldOnBehalf(address contractAddress) external;
    function configureVoidYield() external;
    function configureVoidYieldOnBehalf(address contractAddress) external;
    function configureClaimableGas() external;
    function configureClaimableGasOnBehalf(address contractAddress) external;
    function configureVoidGas() external;
    function configureVoidGasOnBehalf(address contractAddress) external;
    function configureGovernor(address _governor) external;
    function configureGovernorOnBehalf(address _newGovernor, address contractAddress) external;

    // claim yield
    function claimYield(address contractAddress, address recipientOfYield, uint256 amount) external returns (uint256);
    function claimAllYield(address contractAddress, address recipientOfYield) external returns (uint256);

    // claim gas
    function claimAllGas(address contractAddress, address recipientOfGas) external returns (uint256);
    function claimGasAtMinClaimRate(address contractAddress, address recipientOfGas, uint256 minClaimRateBips) external returns (uint256);
    function claimMaxGas(address contractAddress, address recipientOfGas) external returns (uint256);
    function claimGas(address contractAddress, address recipientOfGas, uint256 gasToClaim, uint256 gasSecondsToConsume) external returns (uint256);

    // read functions
    function readClaimableYield(address contractAddress) external view returns (uint256);
    function readYieldConfiguration(address contractAddress) external view returns (uint8);
    function readGasParams(address contractAddress) external view returns (uint256 etherSeconds, uint256 etherBalance, uint256 lastUpdated, GasMode);
}

在你的 contracts 文件夹中创建一个名为 Vault.sol 的文件:

echo > contracts/Vault.sol

contracts 文件夹中可能还自动生成了其他文件;随意删除它们。

打开 Vault.sol 文件并如下修改。

要阅读代码的解释 (强烈推荐),请点击 here

此代码定义了一个名为 Vault 的智能合约,该合约旨在管理 ETH 的存款和取款,同时利用 Blast 的自动收益功能。

  1. 合约初始化: 构造函数接受 Blast 合约的地址 (_blast),并对其进行初始化。它使用 IBlast 接口来配置自动收益。

  2. 铸造和销毁份额: _mint_burn 内部函数管理合约的份额代币。当用户存入 ETH 时,会铸造份额,当他们取款时,会销毁份额。这种机制有助于跟踪每个用户在合约总 ETH 池中的份额。

  3. ETH 存款和取款: deposit 函数允许用户将 ETH 发送到合约,以换取基于当前 ETH 余额和份额总供应量的份额。相反,withdraw 函数允许用户以按比例的 ETH 赎回他们的份额,从而减少他们在总池中的份额。

  4. 检查余额和回退机制: getBalance 提供特定地址的以份额表示的余额。该合约还包括一个回退函数 (receive),用于处理直接 ETH 转账,当 ETH 直接发送到合约地址时,会自动调用 deposit 函数。

该合约是 Blast 生态系统的重要组成部分,使用户能够存入 ETH、自动赚取收益,并以公平的资产总额份额提取资金。

// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

import "./interfaces/IBlast.sol";

// Custom errors for better readability and debugging
error InsufficientShares();
error AmountMustBePositive();
error FailedToSendEther();
error InvalidYieldMode();

contract Vault {
    uint256 public totalSupply;
    mapping(address => uint256) public balanceOf;

    // IBlast interface for enabling automatic yield collection
    constructor(address _blast) {
        // Initialize the IBlast contract
        IBlast blast = IBlast(_blast);
        // The contract balance will grow automatically over time due to yield collection
        blast.configureAutomaticYield();
    }

    // Internal function to mint shares
    function _mint(address _to, uint256 _shares) private {
        totalSupply += _shares;
        balanceOf[_to] += _shares;
    }

    // Internal function to burn shares
    function _burn(address _from, uint256 _shares) private {
        totalSupply -= _shares;
        balanceOf[_from] -= _shares;
    }

    // Function to deposit ETH into the contract
    function deposit() public payable {
        if (msg.value == 0) {
            revert AmountMustBePositive();
        }

        uint256 shares;
        if (totalSupply == 0) {
            shares = msg.value;
        } else {
            shares = (msg.value * totalSupply) / address(this).balance;
        }

        _mint(msg.sender, shares);
    }

    // Function to withdraw ETH from the contract
    function withdraw(uint256 _shares) public {
        if (balanceOf[msg.sender] < _shares) {
            revert InsufficientShares();
        }

        uint256 amount = (_shares * address(this).balance) / totalSupply;
        _burn(msg.sender, _shares);

        (bool sent,) = payable(msg.sender).call{value: amount}("");
        if (!sent) {
            revert FailedToSendEther();
        }
    }

    // Function to get the balance of a specific address
    function getBalance(address _address) public view returns (uint256) {
        return balanceOf[_address];
    }

    // Fallback function to allow direct ETH transfers to the contract
    receive() external payable {
        deposit();
    }
}

在 Blast 上部署智能合约

现在,让我们将我们的合约部署到 Blast Sepolia 测试网。

在你的 scripts 文件夹中创建一个名为 deploy.ts 的文件:

echo > scripts/deploy.ts

如下修改它。

要阅读代码的解释 (强烈推荐),请点击 here

此 TypeScript 脚本旨在部署和验证使用 Hardhat 框架的 Vault 智能合约。

  1. 部署 Vault 合约: 该脚本首先定义 Blast 合约地址。然后,它部署 Vault 合约,并将 Blast 合约地址作为构造函数参数传递。await vault.waitForDeployment() 调用确保在继续之前完成部署过程。

  2. 控制台日志记录和合约验证: 部署后,脚本会记录已部署的 Vault 合约的地址。然后,它继续使用 Hardhat 的 run 函数和 verify:verify 任务在区块链上验证合约,确保合约的源代码和部署参数可公开访问和验证。

  3. 读取和记录收益配置: 该脚本通过获取新部署的 Vault 合约的收益配置来与已部署的 Blast 合约进行交互。此步骤对于确认 Vault 合约已正确设置为与 Blast 协议的收益生成功能进行交互至关重要。

  4. 错误处理: 该脚本包括一个用于错误处理的 catch 块,确保记录执行期间抛出的任何异常,并且该过程以适当的错误代码退出。

总而言之,此脚本自动化了 Blast 区块链上 Vault 合约的部署和验证过程,以及确认其与 Blast 收益配置的集成。这种自动化简化了开发工作流程,并确保了智能合约部署的透明性和可靠性。

import { ethers, run } from "hardhat";

async function main() {
  const blastAddress: string = "0x4300000000000000000000000000000000000002";

  const vault = await ethers.deployContract("Vault", [
    blastAddress,
  ]);

  await vault.waitForDeployment();

  console.log(`Vault contract deployed to ${vault.target}`);

  await run("verify:verify", {
    address: vault.target,
    constructorArguments: [blastAddress],
  });

  const blast = await ethers.getContractAt("IBlast", blastAddress);

  const configuration = await blast.readYieldConfiguration(
    vault.target
  );

  console.log(`Yield Configuration for Vault (${vault.target})`);
  console.log(configuration);
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});

通过运行以下命令部署合约:

npx hardhat run --network blast_sepolia scripts/deploy.ts

请注意,我们使用 blast_sepolia,因为我们在 hardhat.config.tsnetworks 设置中将 Blast Sepolia 测试网定义为 blast_sepolia

成功部署后,你将在输出中看到你的合约地址。

Vault contract deployed to 0xB2b68B2ad7cc81841D92f721104E6FdB5dbB78F3
Successfully submitted source code for contract
contracts/Vault.sol:Vault at 0xB2b68B2ad7cc81841D92f721104E6FdB5dbB78F3
for verification on the block explorer. Waiting for verification result...

Successfully verified contract Vault on the block explorer.
https://testnet.blastscan.io/address/0xB2b68B2ad7cc81841D92f721104E6FdB5dbB78F3#code

Yield Configuration for Vault (0xB2b68B2ad7cc81841D92f721104E6FdB5dbB78F3)
0n

Vault 合约的收益配置值为 0 表示 "AUTOMATIC" 模式,因为 YieldMode 在合约中定义如下,表示自动原生收益生成,无需手动干预。

YieldMode 枚举

enum YieldMode {
    AUTOMATIC, // 0
    VOID, // 1
    CLAIMABLE // 2
}

导航到 Blast Sepolia 测试网的 区块浏览器,通过输入从上面的部署脚本返回的地址来验证智能合约是否已部署。

请注意,由于部署脚本中的验证步骤,智能合约已在区块浏览器上验证。

已验证合约在浏览器上

与 Blast 上的智能合约交互

要与合约交互,请在你的 scripts 目录中创建一个名为 depositEth.ts 的附加脚本:

echo > scripts/depositEth.ts

然后,打开该文件并输入以下代码。

记住用你的 Vault 合约地址更新 YOUR_VAULT_CONTRACT_ADDRESS 占位符。

此外,此脚本文件用于将 0.001 ETH 存入 Vault 合约。如果要更改要存入的 ETH 金额,请更改高亮显示行中的金额。

要阅读代码的解释 (强烈推荐),请点击 here

此 TypeScript 脚本的开发目的是将 ETH 存入 Blast 区块链上的 Vault 智能合约,并利用 Hardhat 框架。

  1. 设置合约交互: 该脚本首先指定已部署的 Vault 合约的地址。用户需要将 ' YOUR_VAULT_CONTRACT_ADDRESS' 替换为实际合约地址。

  2. 定义存款金额: ethAmountToDeposit 变量使用 ethers.parseEther('0.001') 设置为特定的 ETH 金额。这会将 ETH 金额的字符串表示形式转换为 Ethereum 区块链可以理解的格式,在本例中为 0.001 ETH。

  3. 合约交互进行存款: 该脚本使用 getContractAt 和指定的合约地址获取 Vault 合约实例。然后,它调用 Vault 合约的 deposit 函数,并传递要存入的 ETH 金额。此交易触发智能合约中的存款操作。

  4. 交易确认和日志记录: 发送交易后,脚本会等待使用 tx.wait() 挖掘交易。挖掘完成后,它会记录一条带有交易哈希的消息,并提供一个链接,以在 Blast 区块链浏览器上查看交易状态。

  5. 错误处理: 使用标准错误处理模式来捕获脚本执行期间的任何异常,记录错误,并设置退出代码以指示失败。

该脚本是用户或开发者与 Vault 合约交互的实用工具,使他们能够轻松存入 ETH 并参与 Blast 区块链的收益生成机制。

import { ethers } from 'hardhat'

async function main() {
    const vaultAddress: string = 'YOUR_VAULT_CONTRACT_ADDRESS' // 👈 UPDATE HERE

    const ethAmountToDeposit: bigint = ethers.parseEther('0.001')

    const vault = await ethers.getContractAt(
    "Vault",
    vaultAddress
  );

  const tx = await vault.deposit({ value: ethAmountToDeposit });

  tx.wait();

  console.log(
    `Transaction to deposit ETH is sent to the blockchain. Check your transaction status: https://testnet.blastscan.io/tx/${tx.hash}`
  );
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});

要运行该脚本,请使用以下 hardhat 命令:

npx hardhat run scripts/depositEth.ts --network blast_sepolia

控制台输出应如下所示。

Transaction to deposit ETH is sent to the blockchain. Check your transaction status: https://testnet.blastscan.io/tx/0x34edf8b98a57bf2d127d7b5c96737e9edec1256088310775524b462acfe2f88f

你可以通过单击该链接来检查交易详细信息。

在浏览器上的交易结果

通过浏览器与智能合约交互

作为一种替代方法,由于我们的合约已获得批准,因此可以通过浏览器与其进行交互。

  • 转到 Blast Sepolia 浏览器
  • 搜索你的 Vault 合约的地址并转到其页面。
  • 单击 Contract 选项卡,然后选择 Read ContractWrite Contract 选项卡。
  • 连接你的钱包后,你将能够调用这些函数。

就这样!你刚刚使用 Hardhat 和 QuickNode 在 Blast Sepolia 测试网上创建了一个保管库智能合约。此外,你设置了收益赚取模式并运行了一个脚本来存入一些 ETH。

检查自动收益机制

要验证自动收益机制,我们可以随着时间的推移监控合约的 ETH 余额。在没有额外存款的情况下,余额的增加表明成功的自主原生收益生成。此验证确保了自动收益机制的功能。

最简单的方法是从 Blast Sepolia 浏览器 上的合约页面检查余额。如你所见,虽然总存款金额为 0.001 ETH,但 Vault 合约的 ETH 余额略高于该值。

在浏览器上检查自动收益

由于收益,余额多久更新一次?

在主网上,ETH 余额将大约每天更新一次。在测试网上,ETH 余额将每小时更新一次,速率约为每天 0.01%。

来源:Blast 文档

更多资源

如果你想继续了解 Blast 和智能合约,请查看以下资源:

结论

🎉 恭喜!在此过程中,你已经了解了 Blast,部署了一个智能合约,并创建了与智能合约交互的脚本。

如果你有任何问题或需要更多帮助,请随时加入我们的 Discord 服务器或使用下面的表格提供反馈。请在 Twitter (@QuickNode) 和 Telegram 公告频道 上关注我们,以了解最新信息。

我们 ❤️ 反馈!

如果你有任何反馈或对新主题的要求,请 告诉我们。我们很乐意收到你的来信。

  • 原文链接: quicknode.com/guides/bla...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
QuickNode
QuickNode
江湖只有他的大名,没有他的介绍。