持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第10天,点击查看活动详情
前言
当我们学习一定的智能合约的相关基础语法后,我们已经可以实现一些简单的合约了,这一篇主要通过实现一个收集捐款的合约来实战。当我们实现一个合约的时候,得清楚这个合约要实现什么功能,目的明确才好开发,因为合约一旦部署便不能更改。
功能点
因为我们是一个收集捐款的合约,所以一个很确定的功能当然是收钱的功能。有了收钱功能,当然还有提现功能,这是一起的,因此可以总结为:
- 捐赠函数(发送金额到合约)
- 提现函数 (可以把捐款提出来做消费)
- 其他自定义函数
大概就需要这2个函数,接着就可以开发了。
合约实现步骤
确认全局变量
首先我们要实现一个捐赠函数,这个合约应该要记录捐款人、捐赠金额。捐款人可能有多个,因此需要一个数组来存储,我们还需要查询对应捐款人对应捐的款数,因此需要一个mapping映射, 我们还需要记录一下总金额,应该有一个totalMoney变量,
同时需要注意的是还应该存放一个部署人地址,确保只有当前部署者能调用某些方法。
方法实现
- 捐赠函数(fundme)
这个函数应该接收一个金额的参数,注意金额建议用分表示,因为不能出现小数点,这是solidity本身规则,它是没法保存小数点。 拿到金额以后把对应的捐赠人和金额存储到对应的数组和映射。
- 提现函数(withdraw)
这个函数应该接收一个参数,表示提现的金额,每次调用,只需要把总金额减掉对应的数值就可以。
合约实现
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
error NotOwner();
contract Donate {
mapping(address => int256) public addressToAmountFunded; //捐款人对应的金额映射
address[] public funders; //所有的捐款人
address public i_owner;
int256 public totalMoney; //存储的总金额
constructor(){
i_owner = msg.sender;
}
modifier onlyOwner {
// require(msg.sender == owner);
if (msg.sender != i_owner) revert NotOwner();
_;
}
function fundme(int256 money) public {
addressToAmountFunded[msg.sender] += money;
funders.push(msg.sender);
totalMoney += money;
}
function withdraw(int256 money) onlyOwner public{
require(money < totalMoney,"not such money");
totalMoney -= money;
}
//获取捐款人金额
function getDonateList(address funder) public view returns(int256) {
return addressToAmountFunded[funder];
}
}
部署上述合约,在下图上可以测试。
这里我们捐款1000分当前部署者是我自己,相当于我这个部署者调用捐款,即我自己捐了1000分,即10元,这里的数值都是按分表示。 调用fundme函数后,可以查询totalMoney,为1000,说明捐赠成功了。同时可以查询映射里面,我这个地址捐赠的值,也可以看到是1000,说明逻辑处理都ok。
接下来是做提现的测试,调用withdraw函数,输入金额500,调用成功后,查看totalMoney可以看到声誉500了,说明正确。 如果我们输入大于totalMoney的值,那么就会报错,这里用到了require函数,判断条件,不符合则报错。
同时还用到了modifier关键字,这是一个修复符,表示要满足modifier修饰的函数里面的条件,才可以继续往下执行,这里定义了一个名称 的modifier 条件,在我们需要的函数后面 加上就能生效了。
总结
当然这是一个很基础的合约,实际要是真有这样的捐赠合约实现,应该会更严格,这是一个基础版,可以扩展。并且实际跟业务结合的话,更多的要让其更加透明化,自动化、也要更安全。