Solidity合约编写(五)

news/2025/1/10 2:09:29 标签: 区块链

解决问题

编写 FundMe.sol 一个众筹合约,允许用户向合约转账 ETH,并记录每个地址的转账金额。同时,合约还要求每次转账至少为 1 ETH,否则交易失败。最后,合约管理员可以提取资金,并使用 call 函数发送 ETH。

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

// 导入 PriceConverter 库
import "./PriceConverter.sol";

contract FundMe {
    using PriceConverter for uint256;

    // 最小转账金额:1 ETH
    uint256 public constant MINIMUM_USD = 1 * 1e18; // 1 ETH in wei

    // 记录每个地址的转账金额
    mapping(address => uint256) public addressToAmountFunded;

    // 记录所有参与者的地址
    address[] public funders;

    // 合约管理员地址
    address public immutable owner;

    // Chainlink 价格喂价合约地址
    AggregatorV3Interface public priceFeed;

    // 构造函数:设置管理员和价格喂价合约地址
    constructor(address _priceFeedAddress) {
        owner = msg.sender;
        priceFeed = AggregatorV3Interface(_priceFeedAddress);
    }

    // 接收 ETH 的函数
    function fund() public payable {
        // 检查转账金额是否大于等于 1 ETH
        require(
            msg.value.getConversionRate(priceFeed) >= MINIMUM_USD,
            "You need to spend at least 1 ETH!"
        );

        // 记录转账金额
        addressToAmountFunded[msg.sender] += msg.value;

        // 记录参与者地址
        funders.push(msg.sender);
    }

    // 提取合约中的所有资金(仅管理员可调用)
    function withdraw() public onlyOwner {
        // 重置所有参与者的转账金额
        for (uint256 i = 0; i < funders.length; i++) {
            address funder = funders[i];
            addressToAmountFunded[funder] = 0;
        }

        // 清空参与者列表
        funders = new address[](0);

        // 使用 call 发送合约中的所有 ETH 给管理员
        (bool success, ) = payable(owner).call{value: address(this).balance}("");
        require(success, "Transfer failed.");
    }

    // 修改器:仅允许管理员调用
    modifier onlyOwner() {
        require(msg.sender == owner, "Only the owner can call this function!");
        _;
    }

    // 回退函数:允许合约直接接收 ETH
    receive() external payable {
        fund();
    }

    // 回退函数:允许合约直接接收 ETH
    fallback() external payable {
        fund();
    }
}

代码说明

  1. priceFeed:Chainlink 价格喂价合约地址,用于将 ETH 转换为 USD。

  2. fund 函数

    • 接收用户转账的 ETH。

    • 使用 require 检查转账金额是否大于等于 1 ETH。

    • 记录转账金额和参与者地址。

  3. withdraw 函数

    • 仅管理员可调用。

    • 使用 for 循环重置所有参与者的转账金额。

    • 清空参与者列表。

    • 使用 call 发送合约中的所有 ETH 给管理员。

  4. onlyOwner 修改器:限制只有管理员可以调用 withdraw 函数。

  5. 回退函数receive 和 fallback 函数允许合约直接接收 ETH,并自动调用 fund 函数。


http://www.niftyadmin.cn/n/5818136.html

相关文章

golang中的字符串,字符串驻留 Intern,unique包

Go1.23 Go字符串 Go语言中的字符串是一个不可变的字节序列&#xff0c;这意味着一旦字符串被创建&#xff0c;其内容就不能被修改&#xff08;尽管可以通过切片、拼接等方式生成新的字符串&#xff09;。这一设计选择不仅简化了字符串的处理逻辑&#xff0c;还提高了程序的并…

Netty中用了哪些设计模式?

大家好&#xff0c;我是锋哥。今天分享关于【Netty中用了哪些设计模式&#xff1f;】面试题。希望对大家有帮助&#xff1b; Netty中用了哪些设计模式&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Netty 是一个高性能的网络通信框架&#xff0c;广泛…

【25考研】川大计算机复试情况,重点是啥?怎么准备?

24年进入复试的同学中&#xff0c;有10位同学的复试成绩为0分。具体是个人原因还是校方原因&#xff0c;还尚不明确。但是C哥提醒&#xff0c;一定要认真复习&#xff01;复试完后不要跟任何人讨论有关复试的题目及细节&#xff01; 一、复试内容 四川大学复试内容较多&#xf…

【C++习题】20. 两个数组的交集

题目&#xff1a;349. 两个数组的交集 - 力扣&#xff08;LeetCode&#xff09; 链接&#x1f517;&#xff1a;349. 两个数组的交集 - 力扣&#xff08;LeetCode&#xff09; 题目&#xff1a; 代码&#xff1a; class Solution { public:// 函数功能&#xff1a;求两个数组…

Android 修改DialogFragment的大小

如题 在开发中自定义dialog 为了正确使用dialog 有效的生命周期观察 可以使用dialogFragment 如果在布局中设置的大小无效 可以在dialog开始之前 使用系统布局对属性进行修改 Overridepublic void onStart() {super.onStart();if (getDialog() ! null && getDialog().…

【centos8 ES】Elasticsearch linux 龙晰8操作系统安装

在龙晰8操作系统上安装 Elasticsearch 的步骤如下&#xff1a; 1. 安装 Java Elasticsearch 需要 Java 环境&#xff0c;建议安装 OpenJDK 11 或更高版本。你可以使用以下命令来安装 OpenJDK&#xff1a; sudo yum install java-11-openjdk-devel2. 下载 Elasticsearch 你可…

【前端,TypeScript】TypeScript速成(八):Promise

Promise 前端编程是一个单线程的模型&#xff0c;但是其中包含许多异步的动作&#xff0c;异步的动作应该通过以下四步来完成&#xff1a; 发起请求&#xff1b;事件处理函数结束&#xff1b;请求结束&#xff1b;进入回调函数&#xff1b; 上述的基于回调函数解决方案不够好…

JVM 优化指南

JVM 优化指南 1. JVM 参数配置 1.1 基础参数配置 设置堆内存大小 -Xms2048m -Xmx2048m 设置新生代大小 -Xmn1024m 设置元空间大小 -XX:MetaspaceSize256m -XX:MaxMetaspaceSize256m 设置线程栈大小 -Xss512k1.2 垃圾回收器配置 使用 G1 垃圾回收器 -XX:UseG1GC 设置期望停顿…