本文继续用Remix工具部署学习智能合约,通过具体案例来深入学习solidity语法
1. 编写PriceConverter.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
library PriceConverter {
// We could make this public, but then we'd have to deploy it
function getPrice() internal view returns (uint256) {
// Goerli ETH / USD Address
// https://docs.chain.link/docs/ethereum-addresses/
AggregatorV3Interface priceFeed = AggregatorV3Interface(
0xD4a33860578De61DBAbDc8BFdb98FD742fA7028e
);
(, int256 answer, , , ) = priceFeed.latestRoundData();
// ETH/USD rate in 18 digit
return uint256(answer * 10000000000);
}
// 1000000000
function getConversionRate(uint256 ethAmount)
internal
view
returns (uint256)
{
uint256 ethPrice = getPrice();
uint256 ethAmountInUsd = (ethPrice * ethAmount) / 1000000000000000000;
// the actual ETH/USD conversion rate, after adjusting the extra 0s.
return ethAmountInUsd;
}
}
2. 编写FundMe.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
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;
address public immutable i_owner;
uint256 public constant MINIMUM_USD = 50;
constructor() {
i_owner = msg.sender;
}
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);
}
function getVersion() public view returns (uint256){
// ETH/USD price feed address of Goerli Network.
AggregatorV3Interface priceFeed = AggregatorV3Interface(0xD4a33860578De61DBAbDc8BFdb98FD742fA7028e);
return priceFeed.version();
}
// 类似AOP,前置执行,校验通过则继续执行后续逻辑,因为_;在校验后面
modifier onlyOwner {
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);
// 将合同余额置为0
(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();
}
}
我们部署后,设置value为20000000000000000 Wei,当我们调用Fund函数成功后,可以看到余额为0.002ETH
当我们调用withdraw后,余额重置为0