实践:实现FundMe合约
下面我们将实现一个用于募捐的FundMe合约,合约中有以下两个方法:
- fund方法,允许用户向合约发送代币,将设置最低转账金额。
- withdraw方法,使合约的拥有者能够提取出合约中的代币。
定义fund方法
fund方法允许任何人调用,因此使用public关键字。
在调用fund函数时需要付款,因此使用payable关键字,带payable的方法可以在调用时附带进行以太坊转账。
// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;
// Get fund from users
// Withdraw funds
// Set a minimum funding value in USD
contract FundMe {
function fund() public payable {
}
// function withdraw() {
// }
}
使用require
为了设置fund的最小额度,我们将使用require来检查调用fund方法时附带的以太坊是否达到最低金额,代码如下。
// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;
contract FundMe {
function fund() public payable {
require(msg.value > 1e18, "Didn't send enough");
}
// function withdraw() {
// }
}
部署合约后点击fund按钮调用fund方法。
报错如下图。
出现这个报错是因为调用fund方法时没有附上足够的以太坊,没有满足fund方法中require的条件,正因为如此才能看到报错信息中有require中指明的错误信息。
为了成功调用fund方法,我们需要设置执行该方法时附带的以太坊,为此我们需要修改侧边栏中的value和对应单位,如下图。
设置好后再次调用fund方法,可以看到成功调用的提示。
没有通过require检查的方法会被撤回(revert),revert会将操作回滚,并且退回剩余的gas。
使用预言机获取代币价格
下面我们将实现使用USD作为fund的最小额度的单位,为此我们将使用Chainlink预言机来在合约中获取代币的USD价格。
尝试在Goerli测试链上部署下列PriceConsumerV3合约。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
contract PriceConsumerV3 {
AggregatorV3Interface internal priceFeed;
/**
* Network: Sepolia
* Aggregator: ETH/USD
* Address: 0xD4a33860578De61DBAbDc8BFdb98FD742fA7028e
*/
constructor() {
priceFeed = AggregatorV3Interface(
0xD4a33860578De61DBAbDc8BFdb98FD742fA7028e
);
}
/**
* Returns the latest price.
*/
function getLatestPrice() public view returns (int) {
// prettier-ignore
(
/* uint80 roundID */,
int price,
/*uint startedAt*/,
/*uint timeStamp*/,
/*uint80 answeredInRound*/
) = priceFeed.latestRoundData();
return price;
}
}
部署成功后调用合约的getLatestPrice方法,可以获取到以太坊当前的USD价格,如下图。