当前位置: 首页> 文旅> 旅游 > 免费制作简历模板网站_北京注册公司地址有什么要求_网站推广的具体方案_百度推广开户价格

免费制作简历模板网站_北京注册公司地址有什么要求_网站推广的具体方案_百度推广开户价格

时间:2025/8/8 1:00:55来源:https://blog.csdn.net/qq_51118755/article/details/147055570 浏览次数:0次
免费制作简历模板网站_北京注册公司地址有什么要求_网站推广的具体方案_百度推广开户价格

项目介绍

在这个项目中,我们建立一个小型智能合约应用,他允许用户向合约地址捐赠,允许合约所有者从合约中提取余额;并且还设定了捐赠的金额门槛;针对直接对地址进行的捐赠行为,我们也予以记录

源代码

https://github.com/PatrickAlphaC/fund-me-fcc


代码分析

PriceConverter.sol
✅ 函数 1:getPrice()
我们先创建一个价格转化器,这里我们先引入clainlink的包。然后,创建一个 getPrice()函数,他可以通过chainlink获取到真实世界的eth的价格,调用 Chainlink 的 latestRoundData() 方法,从中提取价格 answer(ETH/USD,单位通常是8位小数),代码如下:

(, int256 answer, , , ) = priceFeed.latestRoundData();

为了与以太坊中的 18 位小数精度统一,这里乘以 1e10(即 10^10),因为原始数据是 8 位精度(即 1 ETH = 1234.56789000 USD),我们希望它变成 18 位精度(1234.567890000000000000 USD),代码如下:

return uint256(answer * 10000000000);

✅ 函数 2:getConversionRate(uint256 ethAmount)
根据传入的 ETH 数量(单位为 Wei),返回对应的 USD 金额(同样以 18 位精度表示)。
调用上面那个函数,得到当前 ETH 的价格(单位为 USD,18 位小数)。

uint256 ethPrice = getPrice();

下面一步是核心:

  • ethPrice 是每 1 ETH 的价格(18 位精度)
  • ethAmount 是传入的 ETH 数量(单位是 Wei,18 位精度)
  • 乘积是 36 位小数
  • 除以 1e18,得到结果回到 18 位精度的美元数值
uint256 ethAmountInUsd = (ethPrice * ethAmount) / 1e18;

完整代码如下:

pragma solidity ^0.8.8;import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";library PriceConverter {// We could make this public, but then we'd have to deploy it// We can get eht price with this functionfunction getPrice() internal view returns (uint256) {// Sepolia ETH / USD Address// https://docs.chain.link/data-feeds/price-feeds/addresses#Sepolia%20TestnetAggregatorV3Interface priceFeed = AggregatorV3Interface(0x694AA1769357215DE4FAC081bf1f309aDC325306);(, int256 answer, , , ) = priceFeed.latestRoundData();// ETH/USD rate in 18 digitreturn uint256(answer * 10000000000);// or (Both will do the same thing)// return uint256(answer * 1e10); // 1* 10 ** 10 == 10000000000}// 1000000000function getConversionRate(uint256 ethAmount)internalviewreturns (uint256){uint256 ethPrice = getPrice();uint256 ethAmountInUsd = (ethPrice * ethAmount) / 1000000000000000000;// or (Both will do the same thing)// uint256 ethAmountInUsd = (ethPrice * ethAmount) / 1e18; // 1 * 10 ** 18 == 1000000000000000000// the actual ETH/USD conversion rate, after adjusting the extra 0s.return ethAmountInUsd;}
}

FundMe.sol
🧱 状态变量

mapping(address => uint256) public addressToAmountFunded;
address[] public funders;
address public /* immutable */ i_owner;
uint256 public constant MINIMUM_USD = 50 * 10 ** 18;

addressToAmountFunded:记录每个地址捐了多少 ETH。

  • funders:所有捐赠者的地址列表。

  • i_owner:部署合约的地址,是这个合约的管理员。 建议加上 immutable 关键字提高效率(只能在构造函数中赋值)。

  • MINIMUM_USD:捐款的最小限制,50 美元(以 18 位精度计算,单位 Wei)。

🚀 构造函数

constructor() {i_owner = msg.sender;
}

部署合约的人自动成为合约的拥有者。

💸 捐款函数 fund()

function fund() public payable {require(msg.value.getConversionRate() >= MINIMUM_USD, "You need to spend more ETH!");addressToAmountFunded[msg.sender] += msg.value;funders.push(msg.sender);
}
  • msg.value 是用户发送的 ETH 数量(单位为 Wei)
  • getConversionRate() 是库函数,转化为对应美元价值
  • 如果小于 MINIMUM_USD(即 50 美元),就 require 失败
  • 记录捐款金额,添加到地址映射中,追加到 funders 数组

🛡️ 只有管理员可调用的 modifier

modifier onlyOwner {if (msg.sender != i_owner) revert NotOwner();_;
}
  • 限制某些函数(比如 withdraw)只能由 i_owner 调用。
  • 使用 revert NotOwner() 自定义错误节省 gas。
  • _ 的含义是这个类修饰的函数接下来的代码逻辑

🏧 取款函数 withdraw()

    function withdraw() public onlyOwner {for (uint256 funderIndex=0; funderIndex < funders.length; funderIndex++){address funder = funders[funderIndex];addressToAmountFunded[funder] = 0;}funders = new address[](0);// // transfer// payable(msg.sender).transfer(address(this).balance);// // send// bool sendSuccess = payable(msg.sender).send(address(this).balance);// require(sendSuccess, "Send failed");// call(bool callSuccess, ) = payable(msg.sender).call{value: address(this).balance}("");require(callSuccess, "Call failed");}
  • 清空每个捐赠者在 mapping 里的记录
  • 重置 funders 数组
  • 将所有合约余额通过 .call{value:…}() 的方式发送给合约拥有者
  • 使用 call 而不是 transfer 或 send 是最佳实践(更灵活,处理 gas 限制更好)。

📥 fallback / receive 函数

fallback() external payable { fund(); }
receive() external payable { fund(); }
  • receive():处理空 msg.data 的 ETH 转账
  • fallback():处理非空 msg.data 的 ETH 转账
  • 它们都调用 fund(),意味着无论是直接转账还是调用错误函数名,都能正常执行捐赠逻辑

完整代码:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
import "./PriceConverter.sol";error NotOwner();contract FundMe {using PriceConverter for uint256;mapping(address => uint256) public addressToAmountFunded;address[] public funders;// Could we make this constant?  /* hint: no! We should make it immutable! */address public /* immutable */ i_owner;uint256 public constant MINIMUM_USD = 50 * 10 ** 18;constructor() {i_owner = msg.sender;}function fund() public payable {require(msg.value.getConversionRate() >= MINIMUM_USD, "You need to spend more ETH!");// require(PriceConverter.getConversionRate(msg.value) >= MINIMUM_USD, "You need to spend more ETH!");addressToAmountFunded[msg.sender] += msg.value;funders.push(msg.sender);}function getVersion() public view returns (uint256){// ETH/USD price feed address of Sepolia Network.AggregatorV3Interface priceFeed = AggregatorV3Interface(0x694AA1769357215DE4FAC081bf1f309aDC325306);return priceFeed.version();}modifier onlyOwner {// require(msg.sender == owner);if (msg.sender != i_owner) revert NotOwner();_;}function withdraw() public onlyOwner {for (uint256 funderIndex=0; funderIndex < funders.length; funderIndex++){address funder = funders[funderIndex];addressToAmountFunded[funder] = 0;}funders = new address[](0);// // transfer// payable(msg.sender).transfer(address(this).balance);// // send// bool sendSuccess = payable(msg.sender).send(address(this).balance);// require(sendSuccess, "Send failed");// call(bool callSuccess, ) = payable(msg.sender).call{value: address(this).balance}("");require(callSuccess, "Call failed");}// Explainer from: https://solidity-by-example.org/fallback/// Ether is sent to contract//      is msg.data empty?//          /   \ //         yes  no//         /     \//    receive()?  fallback() //     /   \ //   yes   no//  /        \//receive()  fallback()fallback() external payable {fund();}receive() external payable {fund();}}

大家可以在 remix官网 上运行部署这两个合约,进行实战测试

关键字:免费制作简历模板网站_北京注册公司地址有什么要求_网站推广的具体方案_百度推广开户价格

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: