pragma solidity ^0.4.23;
/**
* @title ERC20Basic
* @dev Simpler version of ERC20 interface
* @dev see https://github.com/ethereum/EIPs/issues/179
*/
contract ERC20Basic {
function totalSupply() public view returns (uint256);
function balanceOf(address who) public view returns (uint256);
function transfer(address to, uint256 value) public returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
}
/**
* @title ERC20 interface
* @dev see https://github.com/ethereum/EIPs/issues/20
*/
contract ERC20 is ERC20Basic {
function allowance(address owner, address spender) public view returns (uint256);
function transferFrom(address from, address to, uint256 value) public returns (bool);
function approve(address spender, uint256 value) public returns (bool);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
*/
library SafeMath {
/**
* @dev Multiplies two numbers, throws on overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {
if (a == 0) {
return 0;
}
c = a * b;
assert(c / a == b);
return c;
}
/**
* @dev Integer division of two numbers, truncating the quotient.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// assert(b > 0); // Solidity automatically throws when dividing by 0
// uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return a / b;
}
/**
* @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
/**
* @dev Adds two numbers, throws on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256 c) {
c = a + b;
assert(c >= a);
return c;
}
}
/**
* @title Crowdsale
* @dev Crowdsale is a base contract for managing a token crowdsale,
* allowing investors to purchase tokens with ether. This contract implements
* such functionality in its most fundamental form and can be extended to provide additional
* functionality and/or custom behavior.
* The external interface represents the basic interface for purchasing tokens, and conform
* the base architecture for crowdsales. They are *not* intended to be modified / overriden.
* The internal interface conforms the extensible and modifiable surface of crowdsales. Override
* the methods to add functionality. Consider using 'super' where appropiate to concatenate
* behavior.
*/
contract Crowdsale {
using SafeMath for uint256;
// The token being sold
ERC20 public token;
// Address where funds are collected
address public wallet;
// How many token units a buyer gets per wei
uint256 public rate;
// Amount of wei raised
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);
/**
* @param _rate Number of token units a buyer gets per wei
* @param _wallet Address where collected funds will be forwarded to
* @param _token Address of the token being sold
*/
function Crowdsale(uint256 _rate, address _wallet, ERC20 _token) public {
require(_rate > 0);
require(_wallet != address(0));
require(_token != address(0));
rate = _rate;
wallet = _wallet;
token = _token;
}
// -----------------------------------------
// Crowdsale external interface
// -----------------------------------------
/**
* @dev fallback function ***DO NOT OVERRIDE***
*/
function () external payable {
buyTokens(msg.sender);
}
/**
* @dev low level token purchase ***DO NOT OVERRIDE***
* @param _beneficiary Address performing the token purchase
*/
function buyTokens(address _beneficiary) public payable {
uint256 weiAmount = msg.value;
_preValidatePurchase(_beneficiary, weiAmount);
// calculate token amount to be created
uint256 tokens = _getTokenAmount(weiAmount);
// update state
weiRaised = weiRaised.add(weiAmount);
_processPurchase(_beneficiary, tokens);
emit TokenPurchase(
msg.sender,
_beneficiary,
weiAmount,
tokens
);
_updatePurchasingState(_beneficiary, weiAmount);
_forwardFunds();
_postValidatePurchase(_beneficiary, weiAmount);
}
// -----------------------------------------
// Internal interface (extensible)
// -----------------------------------------
/**
* @dev Validation of an incoming purchase. Use require statements to revert state when conditions are not met. Use super to concatenate validations.
* @param _beneficiary Address performing the token purchase
* @param _weiAmount Value in wei involved in the purchase
*/
function _preValidatePurchase(address _beneficiary, uint256 _weiAmount) internal {
require(_beneficiary != address(0));
require(_weiAmount != 0);
}
/**
* @dev Validation of an executed purchase. Observe state and use revert statements to undo rollback when valid conditions are not met.
* @param _beneficiary Address performing the token purchase
* @param _weiAmount Value in wei involved in the purchase
*/
function _postValidatePurchase(address _beneficiary, uint256 _weiAmount) internal {
// optional override
}
/**
* @dev Source of tokens. Override this method to modify the way in which the crowdsale ultimately gets and sends its tokens.
* @param _beneficiary Address performing the token purchase
* @param _tokenAmount Number of tokens to be emitted
*/
function _deliverTokens(address _beneficiary, uint256 _tokenAmount) internal {
token.transfer(_beneficiary, _tokenAmount);
}
/**
* @dev Executed when a purchase has been validated and is ready to be executed. Not necessarily emits/sends tokens.
* @param _beneficiary Address receiving the tokens
* @param _tokenAmount Number of tokens to be purchased
*/
function _processPurchase(address _beneficiary, uint256 _tokenAmount) internal {
_deliverTokens(_beneficiary, _tokenAmount);
}
/**
* @dev Override for extensions that require an internal state to check for validity (current user contributions, etc.)
* @param _beneficiary Address receiving the tokens
* @param _weiAmount Value in wei involved in the purchase
*/
function _updatePurchasingState(address _beneficiary, uint256 _weiAmount) internal {
// optional override
}
/**
* @dev Override to extend the way in which ether is converted to tokens.
* @param _weiAmount Value in wei to be converted into tokens
* @return Number of tokens that can be purchased with the specified _weiAmount
*/
function _getTokenAmount(uint256 _weiAmount) internal view returns (uint256) {
return _weiAmount.mul(rate);
}
/**
* @dev Determines how ETH is stored/forwarded on purchases.
*/
function _forwardFunds() internal {
wallet.transfer(msg.value);
}
}
/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
contract Ownable {
address public owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
function Ownable() public {
owner = msg.sender;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) public onlyOwner {
require(newOwner != address(0));
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
}
/**
* @title UbexCrowdsale
* @dev Crowdsale that locks tokens from withdrawal until it ends.
*/
contract UbexCrowdsale is Crowdsale, Ownable {
using SafeMath for uint256;
// Map of all purchaiser's balances (doesn't include bounty amounts)
mapping(address => uint256) public balances;
// Amount of issued tokens
uint256 public tokensIssued;
// Bonus tokens rate multiplier x1000 (i.e. 1200 is 1.2 x 1000 = 120% x1000 = +20% bonus)
uint256 public bonusMultiplier;
// Is a crowdsale closed?
bool public closed;
/**
* Event for token withdrawal logging
* @param receiver who receive the tokens
* @param amount amount of tokens sent
*/
event TokenDelivered(address indexed receiver, uint256 amount);
/**
* Event for token adding by referral program
* @param beneficiary who got the tokens
* @param amount amount of tokens added
*/
event TokenAdded(address indexed beneficiary, uint256 amount);
/**
* Init crowdsale by setting its params
*
* @param _rate Number of token units a buyer gets per wei
* @param _wallet Address where collected funds will be forwarded to
* @param _token Address of the token being sold
* @param _bonusMultiplier bonus tokens rate multiplier x1000
*/
function UbexCrowdsale(
uint256 _rate,
address _wallet,
ERC20 _token,
uint256 _bonusMultiplier
) Crowdsale(
_rate,
_wallet,
_token
) {
bonusMultiplier = _bonusMultiplier;
}
/**
* @dev Withdraw tokens only after crowdsale ends.
*/
function withdrawTokens() public {
_withdrawTokensFor(msg.sender);
}
/**
* @dev Overrides parent by storing balances instead of issuing tokens right away.
* @param _beneficiary Token purchaser
* @param _tokenAmount Amount of tokens purchased
*/
function _processPurchase(address _beneficiary, uint256 _tokenAmount) internal {
require(!hasClosed());
balances[_beneficiary] = balances[_beneficiary].add(_tokenAmount);
tokensIssued = tokensIssued.add(_tokenAmount);
}
/**
* @dev Overrides the way in which ether is converted to tokens.
* @param _weiAmount Value in wei to be converted into tokens
* @return Number of tokens that can be purchased with the specified _weiAmount
*/
function _getTokenAmount(uint256 _weiAmount) internal view returns (uint256) {
return _weiAmount.mul(rate).mul(bonusMultiplier).div(1000);
}
/**
* @dev Deliver tokens to receiver_ after crowdsale ends.
*/
function withdrawTokensFor(address receiver_) public onlyOwner {
_withdrawTokensFor(receiver_);
}
/**
* @dev Checks whether the period in which the crowdsale is open has already elapsed.
* @return Whether crowdsale period has elapsed
*/
function hasClosed() public view returns (bool) {
return closed;
}
/**
* @dev Closes the period in which the crowdsale is open.
*/
function closeCrowdsale(bool closed_) public onlyOwner {
closed = closed_;
}
/**
* @dev set the bonus multiplier.
*/
function setBonusMultiplier(uint256 bonusMultiplier_) public onlyOwner {
bonusMultiplier = bonusMultiplier_;
}
/**
* @dev Withdraw tokens excess on the contract after crowdsale.
*/
function postCrowdsaleWithdraw(uint256 _tokenAmount) public onlyOwner {
token.transfer(wallet, _tokenAmount);
}
/**
* @dev Add tokens for specified beneficiary (referral system tokens, for example).
* @param _beneficiary Token purchaser
* @param _tokenAmount Amount of tokens added
*/
function addTokens(address _beneficiary, uint256 _tokenAmount) public onlyOwner {
balances[_beneficiary] = balances[_beneficiary].add(_tokenAmount);
tokensIssued = tokensIssued.add(_tokenAmount);
emit TokenAdded(_beneficiary, _tokenAmount);
}
/**
* @dev Withdraw tokens for receiver_ after crowdsale ends.
*/
function _withdrawTokensFor(address receiver_) internal {
require(hasClosed());
uint256 amount = balances[receiver_];
require(amount > 0);
balances[receiver_] = 0;
emit TokenDelivered(receiver_, amount);
_deliverTokens(receiver_, amount);
}
}
{
"compilationTarget": {
"UbexCrowdsale.sol": "UbexCrowdsale"
},
"evmVersion": "byzantium",
"libraries": {},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"constant":true,"inputs":[],"name":"hasClosed","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balances","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"rate","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"weiRaised","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"wallet","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"closed","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_beneficiary","type":"address"},{"name":"_tokenAmount","type":"uint256"}],"name":"addTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"tokensIssued","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"withdrawTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"receiver_","type":"address"}],"name":"withdrawTokensFor","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"bonusMultiplier","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_beneficiary","type":"address"}],"name":"buyTokens","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"closed_","type":"bool"}],"name":"closeCrowdsale","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"token","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_tokenAmount","type":"uint256"}],"name":"postCrowdsaleWithdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"bonusMultiplier_","type":"uint256"}],"name":"setBonusMultiplier","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_rate","type":"uint256"},{"name":"_wallet","type":"address"},{"name":"_token","type":"address"},{"name":"_bonusMultiplier","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"receiver","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"TokenDelivered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"beneficiary","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"TokenAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"purchaser","type":"address"},{"indexed":true,"name":"beneficiary","type":"address"},{"indexed":false,"name":"value","type":"uint256"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"TokenPurchase","type":"event"}]