一个简易募集合约
初始化:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
interface IERC20 {
function transfer(address, uint256) external returns (bool);
function transferFrom(address, address, uint256) external returns (bool);
}
MockToken资金管理合约:
contract MockToken is IERC20 {
string public constant name = "MockToken";
string public constant symbol = "MCK";
uint8 public constant decimals = 18;
mapping(address => uint256) balances;
mapping(address => mapping(address => uint256)) allowed;
uint256 totalSupply_ = 1000000 ether;
constructor() {
balances[msg.sender] = totalSupply_;
}
function totalSupply() public view returns (uint256) {
return totalSupply_;
}
function balanceOf(address tokenOwner) public view returns (uint256) {
return balances[tokenOwner];
}
function transfer(address receiver, uint256 numTokens) public override returns (bool) {
require(numTokens <= balances[msg.sender], "Insufficient balance");
balances[msg.sender] -= numTokens;
balances[receiver] += numTokens;
return true;
}
function approve(address delegate, uint256 numTokens) public returns (bool) {
allowed[msg.sender][delegate] = numTokens;
return true;
}
function allowance(address owner, address delegate) public view returns (uint256) {
return allowed[owner][delegate];
}
function transferFrom(address owner, address buyer, uint256 numTokens) public override returns (bool) {
require(numTokens <= balances[owner], "Insufficient balance");
require(numTokens <= allowed[owner][msg.sender], "Insufficient allowance");
balances[owner] -= numTokens;
allowed[owner][msg.sender] -= numTokens;
balances[buyer] += numTokens;
return true;
}
}
CrowdFund募集合约:
contract CrowdFund {
event Launch(
uint256 id,
address indexed creator,
uint256 goal,
uint32 startAt,
uint32 endAt
);
event Cancel(uint256 id);
event Pledge(uint256 indexed id, address indexed caller, uint256 amount);
event UnPledge(uint256 indexed id, address indexed caller, uint256 amount);
event Claim(uint256 id);
event Refund(uint256 id, address indexed caller, uint256 amount);
struct Campaign {
address creator;
uint256 goal;
uint256 pledged;
uint32 startAt;
uint32 endAt;
bool claimed;
}
IERC20 public immutable token;
uint256 public count;
mapping(uint256 => Campaign) public campaigns;
mapping(uint256 => mapping(address => uint256)) public pledgedAmount;
constructor(address _token) {
token = IERC20(_token);
}
function launch(uint256 _goal,uint32 _startAt,uint32 _endAt) external {
//require(_startAt >= block.timestamp, "start at < now");
require(_endAt >= _startAt, "end at < start at");
require(_endAt <= block.timestamp + 90 days, "end at > max duration");
count += 1;
campaigns[count] = Campaign({
creator: msg.sender,
goal: _goal,
pledged: 0,
startAt: _startAt,
endAt: _endAt,
claimed: false
});
emit Launch(count, msg.sender, _goal, _startAt, _endAt);
}
function cancel(uint256 _id) external {
Campaign memory campaign = campaigns[_id];
require(campaign.creator == msg.sender, "not creator");
require(block.timestamp < campaign.startAt, "started");
delete campaigns[_id];
emit Cancel(_id);
}
function pledge(uint256 _id, uint256 _amount) external {
Campaign storage campaign = campaigns[_id];
require(block.timestamp >= campaign.startAt, "not started");
require(block.timestamp <= campaign.endAt, "ended");
campaign.pledged += _amount;
pledgedAmount[_id][msg.sender] += _amount;
token.transferFrom(msg.sender, address(this), _amount);
emit Pledge(_id, msg.sender, _amount);
}
function unpledge(uint256 _id, uint256 _amount) external {
Campaign storage campaign = campaigns[_id];
require(block.timestamp <= campaign.endAt, "ended");
campaign.pledged -= _amount;
pledgedAmount[_id][msg.sender] -= _amount;
token.transfer(msg.sender, _amount);
emit UnPledge(_id, msg.sender, _amount);
}
function claim(uint256 _id) external {
Campaign storage campaign = campaigns[_id];
require(campaign.creator == msg.sender, "not creator");
//require(block.timestamp > campaign.endAt, "not ended");
require(campaign.pledged >= campaign.goal, "pledged < goal");
require(!campaign.claimed, "claimed");
campaign.claimed = true;
token.transfer(campaign.creator, campaign.pledged);
emit Claim(_id);
}
function refund(uint256 _id) external {
Campaign memory campaign = campaigns[_id];
require(block.timestamp > campaign.endAt, "not ended");
require(campaign.pledged < campaign.goal, "pledged >= goal");
uint256 bal = pledgedAmount[_id][msg.sender];
pledgedAmount[_id][msg.sender] = 0;
token.transfer(msg.sender, bal);
emit Refund(_id, msg.sender, bal);
}
}