Add Crowdsale contracts
This commit is contained in:
35
contracts/crowdsale/CappedCrowdsale.sol
Normal file
35
contracts/crowdsale/CappedCrowdsale.sol
Normal file
@ -0,0 +1,35 @@
|
||||
pragma solidity ^0.4.11;
|
||||
|
||||
import '../SafeMath.sol';
|
||||
import './Crowdsale.sol';
|
||||
|
||||
/**
|
||||
* @title CappedCrowdsale
|
||||
* @dev Extension of Crowsdale with a max amount of funds raised
|
||||
*/
|
||||
contract CappedCrowdsale is Crowdsale {
|
||||
using SafeMath for uint256;
|
||||
|
||||
uint256 public cap;
|
||||
|
||||
function CappedCrowdsale(
|
||||
uint256 _cap
|
||||
) {
|
||||
cap = _cap;
|
||||
}
|
||||
|
||||
// overriding Crowdsale#canBuy to add extra cap logic
|
||||
// @return true if investors can buy at the moment
|
||||
function canBuy() internal constant returns (bool) {
|
||||
bool withinCap = weiRaised.add(msg.value) <= cap;
|
||||
return super.canBuy() && withinCap;
|
||||
}
|
||||
|
||||
// overriding Crowdsale#hasEnded to add cap logic
|
||||
// @return true if crowdsale event has ended
|
||||
function hasEnded() public constant returns (bool) {
|
||||
bool capReached = weiRaised >= cap;
|
||||
return super.hasEnded() || capReached;
|
||||
}
|
||||
|
||||
}
|
||||
107
contracts/crowdsale/Crowdsale.sol
Normal file
107
contracts/crowdsale/Crowdsale.sol
Normal file
@ -0,0 +1,107 @@
|
||||
pragma solidity ^0.4.11;
|
||||
|
||||
import '../token/MintableToken.sol';
|
||||
import '../SafeMath.sol';
|
||||
|
||||
/**
|
||||
* @title Crowdsale
|
||||
* @dev Crowdsale is a base contract for managing a token crowdsale.
|
||||
* Crowdsales have a start and end block, where investors can make
|
||||
* token purchases and the crowdsale will assign them tokens based
|
||||
* on a token per ETH rate. Funds collected are forwarded to a wallet
|
||||
* as they arrive.
|
||||
*/
|
||||
contract Crowdsale {
|
||||
using SafeMath for uint256;
|
||||
|
||||
// The token being sold
|
||||
MintableToken public token;
|
||||
|
||||
// start and end block where investments are allowed (both inclusive)
|
||||
uint256 public startBlock;
|
||||
uint256 public endBlock;
|
||||
|
||||
// address where funds are collected
|
||||
address public wallet;
|
||||
|
||||
// token to ETH conversion rate
|
||||
uint256 public rate;
|
||||
|
||||
// amount of raised money in wei
|
||||
uint256 public weiRaised;
|
||||
|
||||
/**
|
||||
* event for token purchase logging
|
||||
* @param purchaser who paid for the tokens
|
||||
* @param beneficiary who got the tokens
|
||||
* @param value weis paid for purchase
|
||||
* @param amount amount of tokens purchased
|
||||
*/
|
||||
event TokenPurchase(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 amount);
|
||||
|
||||
|
||||
function Crowdsale(uint256 _startBlock, uint256 _endBlock, uint256 _rate, address _wallet) {
|
||||
require(_startBlock >= block.number);
|
||||
require(_endBlock >= _startBlock);
|
||||
require(_rate > 0);
|
||||
require(_wallet != 0x0);
|
||||
|
||||
token = createTokenContract();
|
||||
startBlock = _startBlock;
|
||||
endBlock = _endBlock;
|
||||
rate = _rate;
|
||||
wallet = _wallet;
|
||||
}
|
||||
|
||||
// creates the token to be sold.
|
||||
// override this method to have crowdsale of a specific mintable token.
|
||||
function createTokenContract() internal returns (MintableToken) {
|
||||
return new MintableToken();
|
||||
}
|
||||
|
||||
|
||||
// fallback function can be used to buy tokens
|
||||
function () payable {
|
||||
buyTokens(msg.sender);
|
||||
}
|
||||
|
||||
// low level token purchase function
|
||||
function buyTokens(address beneficiary) payable {
|
||||
require(canBuy());
|
||||
|
||||
uint256 weiAmount = msg.value;
|
||||
uint256 updatedWeiRaised = weiRaised.add(weiAmount);
|
||||
|
||||
// calculate token amount to be created
|
||||
uint256 tokens = weiAmount.mul(rate);
|
||||
|
||||
// update state
|
||||
weiRaised = updatedWeiRaised;
|
||||
|
||||
token.mint(beneficiary, tokens);
|
||||
TokenPurchase(msg.sender, beneficiary, weiAmount, tokens);
|
||||
|
||||
forwardFunds();
|
||||
}
|
||||
|
||||
// send ether to the fund collection wallet
|
||||
// override to create custom fund forwarding mechanisms
|
||||
function forwardFunds() internal {
|
||||
wallet.transfer(msg.value);
|
||||
}
|
||||
|
||||
// @return true if the transaction can buy tokens
|
||||
function canBuy() internal constant returns (bool) {
|
||||
uint256 current = block.number;
|
||||
bool withinPeriod = current >= startBlock && current <= endBlock;
|
||||
bool nonZeroPurchase = msg.value != 0;
|
||||
return withinPeriod && nonZeroPurchase;
|
||||
}
|
||||
|
||||
// @return true if crowdsale event has ended
|
||||
function hasEnded() public constant returns (bool) {
|
||||
return block.number > endBlock;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
39
contracts/crowdsale/FinalizableCrowdsale.sol
Normal file
39
contracts/crowdsale/FinalizableCrowdsale.sol
Normal file
@ -0,0 +1,39 @@
|
||||
pragma solidity ^0.4.11;
|
||||
|
||||
import '../SafeMath.sol';
|
||||
import '../ownership/Ownable.sol';
|
||||
import './Crowdsale.sol';
|
||||
|
||||
/**
|
||||
* @title FinalizableCrowdsale
|
||||
* @dev Extension of Crowsdale where an owner can do extra work
|
||||
* after finishing. By default, it will end token minting.
|
||||
*/
|
||||
contract FinalizableCrowdsale is Crowdsale, Ownable {
|
||||
using SafeMath for uint256;
|
||||
|
||||
bool public isFinalized = false;
|
||||
|
||||
event Finalized();
|
||||
|
||||
// should be called after crowdsale ends, to do
|
||||
// some extra finalization work
|
||||
function finalize() onlyOwner {
|
||||
require(!isFinalized);
|
||||
require(hasEnded());
|
||||
|
||||
finalization();
|
||||
Finalized();
|
||||
|
||||
isFinalized = true;
|
||||
}
|
||||
|
||||
// end token minting on finalization
|
||||
// override this with custom logic if needed
|
||||
function finalization() internal {
|
||||
token.finishMinting();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
56
contracts/crowdsale/RefundVault.sol
Normal file
56
contracts/crowdsale/RefundVault.sol
Normal file
@ -0,0 +1,56 @@
|
||||
pragma solidity ^0.4.11;
|
||||
|
||||
import '../SafeMath.sol';
|
||||
import '../ownership/Ownable.sol';
|
||||
|
||||
/**
|
||||
* @title RefundVault
|
||||
* @dev This contract is used for storing funds while a crowdsale
|
||||
* is in progress. Supports refunding the money if crowdsale fails,
|
||||
* and forwarding it if crowdsale is successful.
|
||||
*/
|
||||
contract RefundVault is Ownable {
|
||||
using SafeMath for uint256;
|
||||
|
||||
enum State { Active, Refunding, Closed }
|
||||
|
||||
mapping (address => uint256) public deposited;
|
||||
address public wallet;
|
||||
State public state;
|
||||
|
||||
event Closed();
|
||||
event RefundsEnabled();
|
||||
event Refunded(address indexed beneficiary, uint256 weiAmount);
|
||||
|
||||
function RefundVault(address _wallet) {
|
||||
require(_wallet != 0x0);
|
||||
wallet = _wallet;
|
||||
state = State.Active;
|
||||
}
|
||||
|
||||
function deposit(address investor) onlyOwner payable {
|
||||
require(state == State.Active);
|
||||
deposited[investor] = deposited[investor].add(msg.value);
|
||||
}
|
||||
|
||||
function close() onlyOwner {
|
||||
require(state == State.Active);
|
||||
state = State.Closed;
|
||||
Closed();
|
||||
wallet.transfer(this.balance);
|
||||
}
|
||||
|
||||
function enableRefunds() onlyOwner {
|
||||
require(state == State.Active);
|
||||
state = State.Refunding;
|
||||
RefundsEnabled();
|
||||
}
|
||||
|
||||
function refund(address investor) {
|
||||
require(state == State.Refunding);
|
||||
uint256 depositedValue = deposited[investor];
|
||||
deposited[investor] = 0;
|
||||
investor.transfer(depositedValue);
|
||||
Refunded(investor, depositedValue);
|
||||
}
|
||||
}
|
||||
61
contracts/crowdsale/RefundableCrowdsale.sol
Normal file
61
contracts/crowdsale/RefundableCrowdsale.sol
Normal file
@ -0,0 +1,61 @@
|
||||
pragma solidity ^0.4.11;
|
||||
|
||||
|
||||
import '../SafeMath.sol';
|
||||
import './FinalizableCrowdsale.sol';
|
||||
import './RefundVault.sol';
|
||||
|
||||
|
||||
/**
|
||||
* @title RefundableCrowdsale
|
||||
* @dev Extension of Crowdsale contract that adds a funding goal, and
|
||||
* the possibility of users getting a refund if goal is not met.
|
||||
* Uses a RefundVault as the crowdsale's vault.
|
||||
*/
|
||||
contract RefundableCrowdsale is FinalizableCrowdsale {
|
||||
using SafeMath for uint256;
|
||||
|
||||
// minimum amount of funds to be raised in weis
|
||||
uint256 public goal;
|
||||
|
||||
// refund vault used to hold funds while crowdsale is running
|
||||
RefundVault public vault;
|
||||
|
||||
function RefundableCrowdsale(
|
||||
uint256 _goal
|
||||
) {
|
||||
vault = new RefundVault(wallet);
|
||||
goal = _goal;
|
||||
}
|
||||
|
||||
// We're overriding the fund forwarding from Crowdsale.
|
||||
// In addition to sending the funds, we want to call
|
||||
// the RefundVault deposit function
|
||||
function forwardFunds() internal {
|
||||
vault.deposit.value(msg.value)(msg.sender);
|
||||
}
|
||||
|
||||
// if crowdsale is unsuccessful, investors can claim refunds here
|
||||
function claimRefund() {
|
||||
require(hasEnded());
|
||||
require(!goalReached());
|
||||
|
||||
vault.refund(msg.sender);
|
||||
}
|
||||
|
||||
// vault finalization task, called when owner calls finalize()
|
||||
function finalization() internal {
|
||||
if (goalReached()) {
|
||||
vault.close();
|
||||
} else {
|
||||
vault.enableRefunds();
|
||||
}
|
||||
|
||||
super.finalization();
|
||||
}
|
||||
|
||||
function goalReached() public constant returns (bool) {
|
||||
return weiRaised >= goal;
|
||||
}
|
||||
|
||||
}
|
||||
@ -7,19 +7,15 @@ import '../lifecycle/Pausable.sol';
|
||||
* Pausable token
|
||||
*
|
||||
* Simple ERC20 Token example, with pausable token creation
|
||||
* Issue:
|
||||
* https://github.com/OpenZeppelin/zeppelin-solidity/issues/194
|
||||
* Based on code by BCAPtoken:
|
||||
* https://github.com/BCAPtoken/BCAPToken/blob/5cb5e76338cc47343ba9268663a915337c8b268e/sol/BCAPToken.sol#L27
|
||||
**/
|
||||
|
||||
contract PausableToken is Pausable, StandardToken {
|
||||
contract PausableToken is StandardToken, Pausable {
|
||||
|
||||
function transfer(address _to, uint256 _value) whenNotPaused {
|
||||
function transfer(address _to, uint _value) whenNotPaused {
|
||||
super.transfer(_to, _value);
|
||||
}
|
||||
|
||||
function transferFrom(address _from, address _to, uint256 _value) whenNotPaused {
|
||||
function transferFrom(address _from, address _to, uint _value) whenNotPaused {
|
||||
super.transferFrom(_from, _to, _value);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user