学习测试ICO合约 / 学习智能合约#10
有了前面ERC20代币和智能合约的基础,再来试试ICO合约就会比较轻松地搞定。ICO合约主要是增加了一些复合性和操作的逻辑性,难度上并没有多少增加。
ICO合约的本质就是你给它发以太币,它给你发代币! ERC20代币在前面试过,实现一些标准的函数即可。ICO合约就是在一定的逻辑基础上将这些ERC20代币换成以太币。大家各取所需,皆大欢喜。
ICO合约最主要的是一个互换的函数(卖币),这里需要使用前一篇讲到的接口来调用ERC20代币合约,也就这点稍显复杂。
具体代码如下所示:
pragma solidity >=0.4.22 <0.7.0;
interface token {
function transfer(address receiver, uint amount) external ;
//代币合约的接口
}
contract Ico {
address payable public beneficiary;
uint public fundingGoal;
uint public amountRaised;
uint public deadline;
uint public price;
token public tokenReward;
mapping(address => uint256) public balanceOf;
bool crowdsaleClosed = false;
event GoalReached(address recipient, uint totalAmountRaised);
event FundTransfer(address backer, uint amount, bool isContribution);
constructor (
uint fundingGoalInEthers,
uint durationInMinutes,
uint etherCostOfEachToken,
address addressOfTokenUsedAsReward
) public {
beneficiary = msg.sender;
fundingGoal = fundingGoalInEthers * 1 ether;
deadline = now + durationInMinutes * 1 minutes;
price = etherCostOfEachToken * 1 ether;
tokenReward = token(addressOfTokenUsedAsReward); //代币合约地址,以接口形式实现
}
receive() external payable {
//给合约转以太币以换取代币
require(!crowdsaleClosed);
uint amount = msg.value;
balanceOf[msg.sender] += amount;
amountRaised += amount;
tokenReward.transfer(msg.sender, amount / price);
emit FundTransfer(msg.sender, amount, true);
}
fallback () external payable { }
modifier afterDeadline() {
if (now >= deadline) {
_;
}
}
function checkGoalReached() public afterDeadline {
if (amountRaised >= fundingGoal) {
emit GoalReached(beneficiary, amountRaised);
}
crowdsaleClosed = true;
}
function safeWithdrawal() public afterDeadline {
if (amountRaised < fundingGoal) {
uint amount = balanceOf[msg.sender];
balanceOf[msg.sender] = 0;
if (amount > 0) {
msg.sender.transfer(amount);
emit FundTransfer(msg.sender, amount, false);
}
}
if (fundingGoal <= amountRaised && beneficiary == msg.sender) {
beneficiary.transfer(amountRaised);
emit FundTransfer(beneficiary, amountRaised, false);
}
}
function getEthBalance(address addr) public view returns (uint) {
return addr.balance;
}
}
新版的Solidity更新了不少的代码规范,我参考网上的文章做了不少改进,有兴趣的朋友不妨也来测试下。