使用 BuildBear 创建质押智能合约

  • BuildBear
  • 发布于 2022-09-22 19:52
  • 阅读 47

本文介绍了如何构建一个以太坊智能合约,用于质押以太币以赚取利息。文章详细讲解了合约的设计、编码、部署及测试,包括创建项目、编写合约的关键功能、在私有测试网进行部署和审核交易。最后,用户还可以邀请朋友共同参与测试,协助提升智能合约的功能和性能。

Staking 加密货币是将加密货币资产锁定或存入 DeFi 协议或智能合约以赚取利息的过程。

今天我们将构建一个智能合约,我们可以在其中质押以太币并赚取利息。如果用户尝试在解锁日期之前提取资金,将会受到惩罚。如果用户这样做,他必须放弃已获得的利息。

在本文结束时,你将学到以下内容:

  1. 学习如何编写一个质押智能合约
  2. 部署到一个私有测试网
  3. 使用水龙头获取原生代币
  4. 从区块浏览器测试我们的质押智能合约,进行一些交易
  5. 邀请你的朋友加入你的私有测试网,并与你一起通过水龙头测试合约
  6. 使用 Postman 调用在我们的私有测试网上提高时间
  7. 测试提取已质押代币

让我们开始构建吧!🧑‍💻

1. 创建项目并安装依赖

1.1: 在你的命令行中使用以下命令来初始化项目。

mkdir staking-with-buildbear && cd staking-with-buildbear

1.2: 在命令行中运行命令 npx hardhat,选择 Create a Javascript Object;所有选项选择 yes

成功执行上述步骤后,如果在 VS Code 中打开此仓库,你应有一个类似于下面的目录结构:

2. 编写质押智能合约

2.1: 在 contracts 文件夹中创建一个名为 Staking.sol 的文件。

2.2: 我们将开始定义 Solidity 版本(这将决定我们在 hardhat.config.js 文件中使用的 Solidity 编译器)。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;contract Staking {

2.3: 定义我们将在合约中使用的变量:

address public owner; // 地址质押的以太币数量
struct Position {
    uint positionId;
    address walletAddress;
    uint createdDate;
    uint unlockDate;
    uint percentInterest;
    uint weiStaked;
    uint weiInterest;
    bool open;
} Position position;
uint public currentPositionId;
mapping (uint => Position) public positions;
mapping (address => uint[]) public positionIdsByAddress;
mapping (uint => uint) public tiers;
uint[] public lockPeriods; // 30天 / 90天 / 180天

2.3.1: 关键变量

  • 结构 Position 存储特定地址在一段时间内质押的以太币数量,附带其他细节。尽管这些细节是自解释的,如果你需要任何信息,可以随时联系我们。
  • 整数到位置的映射,其中每个位置可以通过其 ID 进行查询
  • lockPeriods 将存储不同的质押锁定期限。

2.4: 智能合约的 constructor

使用以下代码作为构造函数:

constructor () payable {
        owner = msg.sender;
        currentPositionId = 0;
        tiers[30] = 700; // 30天 -> 7%
        tiers[90] = 1000; // 90天 -> 10%
        tiers[180] = 1200; // 180天 -> 12%        
        lockPeriods.push(30);
        lockPeriods.push(90);
        lockPeriods.push(180);
    }

我们已经将构造函数标记为可支付,这将允许合约的部署者在部署时向其发送一些以太币。

在构造函数中,我们将 msg.sender 设置为所有者

  • currentPositionId 将初始化为 0
  • 然后我们定义了 tiers
  • 30 天期限的年收益率为 7%
  • 90 天期限的年收益率为 10%
  • 180 天期限的年收益率为 12%
  • 最后,我们将有 lockPeriod,也就是 30、90 和 180 天

2.5: 合约的逻辑函数:

// 质押的天数
function stakeEther(uint numDays) external payable {
    require(tiers[numDays] > 0, "Mapping not found");
    positions[currentPositionId] = Position(
        currentPositionId,
        msg.sender,
        block.timestamp,
        block.timestamp + (numDays * 15180),
        tiers[numDays],
        msg.value,
        calculateInterest(tiers[numDays], numDays, msg.value),
        true
    );    
    positionIdsByAddress[msg.sender].push(currentPositionId);
    currentPositionId += 1;
}

function calculateInterest(uint basisPoints, uint numDays, uint weiAmount) private pure returns (uint) {
    return basisPoints * weiAmount / 10000;
}

function modifyLockPeriods(uint numDays, uint basisPoints) external {
    require(owner == msg.sender, "Only owner may modify staking periods");
    tiers[numDays] = basisPoints;
    lockPeriods.push(numDays);
}

function getLockPeriods() external view returns(uint[] memory) {
    return lockPeriods;
}

function getInterestRate(uint numDays) external view returns (uint) {
    return tiers[numDays];
}

function getPositionById(uint positionId) external view returns (Position memory) {
    return positions[positionId];
}

function getPositionIdsForAddress(address walletAddress) external view returns (uint[] memory) {
    return positionIdsByAddress[walletAddress];
}

function closePosition(uint positionId) external {
    require(positions[positionId].walletAddress == msg.sender, "Only position creator can modify the position");
    require(positions[positionId].open == true, "Position is closed");
    positions[positionId].open = false;    
    if(block.timestamp > positions[positionId].unlockDate) {
        uint amount = positions[positionId].weiStaked + positions[positionId].weiInterest;
        payable(msg.sender).call{value: amount}("");
    } else {
        payable(msg.sender).call{value: positions[positionId].weiStaked}("");
    }
}

让我们讨论一些关键函数:

  • stakeEther 接收一个整数,表示质押以太币的天数(在调用该函数时发送到智能合约中)。
  • calculateInterest 函数将接收一个基点的整数,并根据用户质押天数和层级提供的利息。你会注意到,这是一个 private 函数。一个私有函数只能在定义了该函数的合约内部访问,而且不允许任何外部源访问。
  • modifyLockPeriods 将允许部署者(仅部署者)更改合约的锁定期限。如果其他地址调用此功能,则会失败,因为这是一个保护函数,仅可由所有者调用。
  • getPositionByIdgetPositionByAddresses 用于获取位置和质押用户
  • closePosition 将用于更改质押位置的解锁时间。

你的智能合约应该看起来类似于此:

3. 部署到区块链,调用智能合约功能并邀请你的朋友/受众一起参与测试

3.1: 在 BuildBear 上创建一个私有测试网 🐻‍❄️ *(你可能会问为什么使用 BuildBear?请看这里: [Where Localhost Fails](https://medium.com/p/492f1038883d) 和 Win Web3 Hackathons, using BuildBear Testnet’s analytics )

3.1.1: 访问 BuildBear 应用。一旦你使用 GitHub 账号登录,你将看到类似以下图像的页面:

在这里,我们需要为我们的质押应用创建一个简单的节点,因此我们将点击 create an endpoint,并将被重定向到节点配置页面。对于本文,我们将使用默认配置创建节点。

所以我们将简单地单击下面所示的 create 按钮。

恭喜!你已创建了自己的私有测试网络节点!

你的页面应更新为类似下面的内容:

单击 RPC URL(复制或单击查看)以获取指向你的私有测试网的 RPC。

3.2: 为了执行交易,我们需要来自水龙头的资金。别担心!我们不需要寻找随机水龙头来获取测试以太币。

单击 Open Faucet 选项并选择你的账户。

之后,单击水龙头页面右上角的 Add to Metamask 选项。

你的 MetaMask 将立即获得 1,000 BB ETH。

3.3: 将 hardhat.config.js 更新为以下内容:

在网络中,我们创建了一个名为 buildbear 的网络,并在那里添加了我们的 RPC URL,然后添加了 MetaMask 账户的私钥(请不要将私人密钥暴露给任何人)。

现在我们的配置已经准备好了!让我们开始编写我们的智能合约。

4. 使用 BuildBear 部署我们的质押合约

4.1: 使用以下脚本部署你的质押合约:

const { ethers } = require("hardhat");
const hre = require("hardhat");

async function main() {
  const Staking = await hre.ethers.getContractFactory("Staking");
  const staking = await Staking.deploy({value: ethers.utils.parseEther('10')});  
  await staking.deployed();  
  console.log(
    "Staking contract deployed to:", staking.address
  );
}

main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});

打开你的命令行,运行以下命令:

npx hardhat run scripts/deploy.js --network buildbear

现在如果你返回 BuildBear Explorer(链接可从BuildBear 应用获取,当你创建私有测试网后)。你将看到已执行的交易。

打开交易哈希,你将获得与交易相关的所有细节。

如果你点击 advance 按钮,你将看到显示 unknownContract 创建的追踪。

这代表我们的质押合约已被部署。

但是 unknownContract 听起来有点令人困惑! 😥. 所以让我们来解决这个问题。

4.2: 返回你的 Dashboard, 并单击 advanced 按钮。

在这里提交你的 artifacts 文件夹。

现在,再次打开你的交易并检查 advanced 选项。

你将看到这次不是得到 unknownContract,而是收到了质押合约。

这不是很棒吗? 😎

5. 在我们的合约上执行交易

我们将使用 BuildBear Explorer 测试我们的合约。

5.1: 为了执行交易,请访问你在浏览器上的合约地址。将合约地址放入搜索选项中。

你的合约的样子如下:

单击与 Transactions 相邻的 Contract 选项。

在这里我们有 3 个选项:

  • 代码以提交你的合约的 ABI
  • 读取合约
  • 写入合约

由于我们已经使用仪表板提交了 ABI,因此我们将被重定向到读取合约选项。

你的 Read Contract 选项将具有你在合约中编写的所有函数。

5.2: 让我们在 write contract 上质押我们的以太币。

确保你连接到你的 Web3 账户。

write contract 选项下,你将看到 stakeEthers 函数。

我们需要传入 numDaysamount 的值。因此,我们将在这里将 30 作为 numDays 的值,2 以太币作为金额。

然后单击 write button 调用 stakeEthers 函数。这将触发 MetaMask,以 2 BB ETH 为值并调用智能合约的函数。

完成后,你将在查询按钮下收到一个 交易哈希,告诉你交易是否成功。

点击交易哈希,你将收到与其相关的所有信息。

我们与合约 0x73eccD6288e117cAcA738BDAD4FEC51312166C1A 进行互动,并在合约中添加了 2 ETH。

交易的追踪将展示你的活动。

在读取合约中, currentPositionId 的值等于 1,因为我们刚才质押了以太币。

通过这种方式,我们可以运行合约的所有函数并对合约进行测试。

5.3: 提取你的利息

质押的利息只有在达到 lockPeriod 时才会获得。

我们可以通过 Postman 请求进行测试。

我们将做的是,获取节点的 RPC URL 并在 Postman 上发送一个 post 请求。

将正文传递如下 JSON 主体

{
    "jsonrpc": "2.0",
     "id": 1,
    "method": "evm_increaseTime",
    "params": ["0x28DE80"]
}

这将在节点上将区块时间戳增加 31 天。因此,我们将能够关闭我们的质押并赚取利息。

因此,现在如果你运行 POST 请求,你将获得类似于此的结果。

这意味着节点的时间戳已成功增加 31 天。

现在要测试我们的质押收集,我们将返回浏览器,打开我们的合约并检查 closePosition

现在在参数中输入 positionId 并单击 write button

你可以看到我们的交易已成功执行。

为了了解我们刚才所做的,让我们打开在 write 按钮下方收到的交易哈希,然后打开 advanced 标签。

你将收到类似于以下内容的追踪。

让我们了解一下刚刚发生了什么:

  • 当我们调用 stakeEther 时,我们规定质押的以太币应在 30 天后解锁
  • 但这并不是解锁以太币的最可行方式,因此我们在这里使用了 Postman
  • 我们使用 RPC URL 进行了 POST 请求,并执行了 evm_increaseTime 方法,并在参数中提供了 31 天的十六进制值,以便我们不必等待那么久
  • 一旦我们完成了 POST 请求,我们节点的区块时间戳将增加 31 天。因此现在可以解锁我们的质押。
  • 如果我们查看上面显示的追踪,
  • 当我们调用 closePosition 函数时,它与我们的合约进行了互动
  • 然后合约将资金发送到用户账户(在上面的示例中,地址 0xd51.. 是我收到资金的波动地址。 UnknownContractAndFunction 显示了发送资金的方式。

现在我们刚刚学会了如何进行加密质押! 😎

这就是 BuildBear 让你部署合约并与之交互的方式。

  1. 奖金

为了更进一步,你可以邀请你的朋友在你的质押合约上质押他们的以太币并执行多个功能。我创建了私有测试网,并且质押合约在 这里 可用。

你可以从 这里 获取该测试网的水龙头。

专业提示:在创建私有测试网时,我已禁用提高时间的选项,因此你将无法提前我私有测试网的区块时间。太棒了!!!

要了解有关 BuildBear 的更多信息,请阅读这里 docs

这里 获取上面的 GitHub 代码。

如果你喜欢我们所做的,请在 Twitter 上关注我们,并且如果你还没有加入,Telegram 群组,请加入。

如果你喜欢我们的工作,请给我们一个掌声 👏。

作者:

Pari Tomar ( Twitter || LinkedIn),始终乐于接受反馈及学习。

顺便说一下,如果你知道任何想要与 BuildBear 一起工作的人,请查看 这里!!!

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

0 条评论

请先 登录 后评论
BuildBear
BuildBear
https://medium.com/buildbear