解决问题
编写 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 ETHuint256 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 ETHrequire(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!");_;}// 回退函数:允许合约直接接收 ETHreceive() external payable {fund();}// 回退函数:允许合约直接接收 ETHfallback() external payable {fund();}
}
代码说明
-
priceFeed
:Chainlink 价格喂价合约地址,用于将 ETH 转换为 USD。 -
fund
函数:-
接收用户转账的 ETH。
-
使用
require
检查转账金额是否大于等于 1 ETH。 -
记录转账金额和参与者地址。
-
-
withdraw
函数:-
仅管理员可调用。
-
使用
for
循环重置所有参与者的转账金额。 -
清空参与者列表。
-
使用
call
发送合约中的所有 ETH 给管理员。
-
-
onlyOwner
修改器:限制只有管理员可以调用withdraw
函数。 -
回退函数:
receive
和fallback
函数允许合约直接接收 ETH,并自动调用fund
函数。