Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- pragma solidity 0.4.19;
- library SafeMath {
- function mul(uint256 a, uint256 b) internal pure returns (uint256) {
- uint256 c = a * b;
- assert(a == 0 || c / a == b);
- return c;
- }
- 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 c;
- }
- function sub(uint256 a, uint256 b) internal pure returns (uint256) {
- assert(b <= a);
- return a - b;
- }
- function add(uint256 a, uint256 b) internal pure returns (uint256) {
- uint256 c = a + b;
- assert(c >= a);
- return c;
- }
- }
- 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) onlyOwner public {
- require(newOwner != address(0));
- OwnershipTransferred(owner, newOwner);
- owner = newOwner;
- }
- }
- contract Haltable is Ownable {
- // public variables
- bool public halted;
- modifier stopInEmergency() {
- require(!halted);
- _;
- }
- modifier stopInEmergencyNonOwners() {
- if(halted && msg.sender != owner)
- revert();
- _;
- }
- function halt() external onlyOwner {
- halted = true;
- }
- function unhalt() external onlyOwner {
- halted = false;
- }
- }
- contract ERC20Basic {
- uint256 public totalSupply;
- function balanceOf(address who) public constant returns (uint256);
- function transfer(address to, uint256 value) public returns (bool);
- event Transfer(address indexed from, address indexed to, uint256 value);
- }
- contract BasicToken is ERC20Basic {
- using SafeMath for uint256;
- mapping(address => uint256) balances;
- /**
- * @dev transfer token for a specified address
- * @param _to The address to transfer to.
- * @param _value The amount to be transferred.
- */
- function transfer(address _to, uint256 _value) public returns (bool) {
- require(_to != address(0));
- // SafeMath.sub will throw if there is not enough balance.
- balances[msg.sender] = balances[msg.sender].sub(_value);
- balances[_to] = balances[_to].add(_value);
- Transfer(msg.sender, _to, _value);
- return true;
- }
- /**
- * @dev Gets the balance of the specified address.
- * @param _owner The address to query the the balance of.
- * @return An uint256 representing the amount owned by the passed address.
- */
- function balanceOf(address _owner) public constant returns (uint256 balance) {
- return balances[_owner];
- }
- }
- contract FriendzToken is BasicToken, Ownable {
- // public variables
- mapping(address => uint256) public release_dates;
- mapping(address => uint256) public purchase_dates;
- mapping(address => uint256) public blocked_amounts;
- mapping (address => mapping (address => uint256)) public allowed;
- bool public free_transfer = false;
- // private variables
- address private co_owner;
- // ERC20 variables
- string public name;
- string public symbol;
- uint256 public decimals;
- event Approval(address indexed owner, address indexed spender, uint256 value);
- function FriendzToken(string _name, string _symbol, uint256 _decimals, uint256 _supply) public {
- // safety checks
- require(_decimals > 0);
- require(_supply > 0);
- // set owner
- owner = msg.sender;
- // assign variables
- name = _name;
- symbol = _symbol;
- decimals = _decimals;
- totalSupply = _supply * 10 ** decimals;
- // assign the total supply to the owner
- balances[owner] = totalSupply;
- }
- // modifiers
- // checks if the address can transfer tokens
- modifier canTransfer(address _sender, uint256 _value) {
- uint256 after_math = balances[_sender].sub(_value);
- require(
- (free_transfer) ||
- (
- _sender != address(0) &&
- after_math >= getMinimumAmount(_sender)
- )
- );
- _;
- }
- // check if we're in a free-transfter state
- modifier isFreeTransfer() {
- require(free_transfer);
- _;
- }
- // check if we're in non free-transfter state
- modifier isBlockingTransfer() {
- require(!free_transfer);
- _;
- }
- // functions
- // set co-owner
- function setCoOwner(address _addr) onlyOwner public {
- co_owner = _addr;
- }
- // set token informations
- function setInformations(string _name, string _symbol) onlyOwner public {
- require(bytes(_name).length != 0);
- require(bytes(_symbol).length != 0);
- name = _name;
- symbol = _symbol;
- }
- // calculate the amount of tokens an address can use
- function getMinimumAmount(address _addr) constant public returns (uint256) {
- // if the address ha no limitations just return 0
- if(blocked_amounts[_addr] == 0x0)
- return 0x0;
- uint256 alpha = uint256(now).sub(purchase_dates[_addr]); // absolute purchase date
- uint256 beta = release_dates[_addr].sub(purchase_dates[_addr]); // absolute token release date
- uint256 tokens = blocked_amounts[_addr].sub(alpha.mul(blocked_amounts[_addr]).div(beta)); // T - (α * T) / β
- return tokens;
- }
- // set blocking state to an address
- function setBlockingState(address _addr, uint256 _end, uint256 _value) isBlockingTransfer public {
- // only the onwer and the co-owner can call this function
- require(
- msg.sender == owner ||
- msg.sender == co_owner
- );
- require(_addr != address(0));
- if(release_dates[_addr] != 0x0){
- // if it's not the first time this function is beign called for this address
- // update its information instead of setting them (add value to previous value)
- release_dates[_addr] = _end;
- purchase_dates[_addr] = now;
- blocked_amounts[_addr] = blocked_amounts[_addr].add(_value);
- }else{
- release_dates[_addr] = _end;
- purchase_dates[_addr] = now;
- blocked_amounts[_addr] = _value;
- }
- }
- // all addresses can transfer tokens now
- function freeToken() public onlyOwner {
- free_transfer = true;
- }
- // override function using canTransfer on the sender address
- function transfer(address _to, uint _value) canTransfer(msg.sender, _value) public returns (bool success) {
- return super.transfer(_to, _value);
- }
- // transfer tokens from one address to another
- function transferFrom(address _from, address _to, uint _value) canTransfer(_from, _value) public returns (bool success) {
- require(_from != address(0));
- require(_to != address(0));
- // SafeMath.sub will throw if there is not enough balance.
- balances[_from] = balances[_from].sub(_value);
- balances[_to] = balances[_to].add(_value);
- allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value); // this will throw if we don't have enough allowance
- // this event comes from BasicToken.sol
- Transfer(_from, _to, _value);
- return true;
- }
- // erc20 functions
- function approve(address _spender, uint256 _value) public returns (bool) {
- require(_value == 0 || allowed[msg.sender][_spender] == 0);
- allowed[msg.sender][_spender] = _value;
- Approval(msg.sender, _spender, _value);
- return true;
- }
- function allowance(address _owner, address _spender) public constant returns (uint256 remaining) {
- return allowed[_owner][_spender];
- }
- /**
- * approve should be called when allowed[_spender] == 0. To increment
- * allowed value is better to use this function to avoid 2 calls (and wait until
- * the first transaction is mined)
- * From MonolithDAO Token.sol
- */
- function increaseApproval (address _spender, uint256 _addedValue) public returns (bool success) {
- allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_addedValue);
- Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
- return true;
- }
- function decreaseApproval (address _spender, uint256 _subtractedValue) public returns (bool success) {
- uint256 oldValue = allowed[msg.sender][_spender];
- if (_subtractedValue > oldValue) {
- allowed[msg.sender][_spender] = 0;
- } else {
- allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue);
- }
- Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
- return true;
- }
- }
- contract Sale is Haltable {
- // usings
- using SafeMath for uint256;
- // public variables
- FriendzToken public token;
- address public wallet;
- uint256 public rate;
- string public name;
- mapping (address => uint256) invested_amount_wei;
- mapping (address => uint256) invested_amount_tokens;
- uint256 public raised_wei = 0;
- uint256 public raised_tokens = 0;
- uint256 public investor_count = 0;
- // events
- event Invested(address indexed investor, uint256 wei_amount, uint256 token_amout);
- function Sale(string _name, address _token, address _wallet, uint256 _rate) public {
- // safety checks
- require(_token != address(0));
- require(_wallet != address(0));
- require(_rate > 0);
- // set owner
- owner = msg.sender;
- // assign variables
- token = FriendzToken(_token);
- wallet = _wallet;
- rate = _rate;
- name = _name;
- }
- // assign tokens to the investor, abstract
- function assignTokens(address _to, uint256 _amount) internal;
- }
- contract PreSale is Sale {
- // public variables
- address public holder;
- uint256 public start_date;
- uint256 public end_date;
- uint256 public discount;
- uint256 public available_tokens;
- // constants
- uint256 constant MINIMUM_INVESTMENT = 10 * 1 ether;
- // events
- event Invested(address indexed investor, uint256 wei_amount, uint256 token_amout);
- function PreSale(address _holder, string _name, address _token, address _wallet, uint256 _rate, uint256 _discount, uint256 _available_tokens, uint256 _start_date, uint256 _end_date)
- Sale(_name, _token, _wallet, _rate) public // extends 'Sale' contract
- {
- // safety checks
- require(_holder != address(0));
- require(_available_tokens > 0);
- require(_start_date > 0);
- require(_end_date > 0);
- require(_start_date < _end_date);
- // assign variables
- holder = _holder;
- discount = _discount;
- available_tokens = _available_tokens;
- start_date = _start_date;
- end_date = _end_date;
- }
- // checks if the presale is finished or not
- modifier canInvest() {
- require(now >= start_date);
- require(now < end_date);
- _;
- }
- // chcks if the presale is finished
- modifier isFinished() {
- require(now >= end_date);
- _;
- }
- // fallback function, the only one that can receive payments
- function () payable external {
- investInternal(msg.sender);
- }
- // internal function for handling payments
- function investInternal(address _to) canInvest stopInEmergency internal returns(uint256 tokens) {
- // safety checks
- require(_to != address(0));
- require(msg.value >= MINIMUM_INVESTMENT);
- uint256 value_wei = msg.value;
- uint256 new_rate = rate.mul(discount.add(100)).div(100);
- uint256 value_tokens = value_wei.mul(new_rate);
- require(value_tokens > 0);
- // increase investor count only if it's their the first time
- if(invested_amount_wei[_to] == 0){
- investor_count = investor_count.add(1);
- }
- // update investor
- invested_amount_wei[_to] = invested_amount_wei[_to].add(value_wei);
- invested_amount_tokens[_to] = invested_amount_tokens[_to].add(value_tokens);
- // update amounts
- raised_wei = raised_wei.add(value_wei);
- raised_tokens = raised_tokens.add(value_tokens);
- // this will throw an error and revert in case 'value_tokens' is greater than 'available_tokens'
- available_tokens = available_tokens.sub(value_tokens);
- // send ether to the wallet
- wallet.transfer(value_wei);
- // assign tokens to investor
- assignTokens(_to, value_tokens);
- Invested(_to, value_wei, value_tokens);
- return value_tokens;
- }
- // internal function for assigning tokens to an address
- function assignTokens(address _to, uint256 _value) internal {
- if(!token.transferFrom(holder, _to, _value))
- revert();
- }
- // once the presale is finished we kill the contract and remove it from the blockchain.
- // all remaining ethers in the contract (shouldn't be any) will be send to '_address'
- function kill(address _address) onlyOwner isFinished public {
- selfdestruct(_address);
- }
- }
- contract Reservation is Haltable {
- // usings
- using SafeMath for uint256;
- // public variables
- uint256 public maximum;
- uint256 public rate;
- uint256 public start;
- uint256 public end;
- address[] public investors;
- mapping (address => uint256) public balances;
- mapping (address => bool) public invested;
- mapping (address => bool) public whitelist;
- // private variables
- Crowdsale private ico; // we don't want to show the final ico address
- // constants
- uint256 constant MINIMUM_INVESTMENT = 0.5 * 1 ether;
- uint256 constant KYC_REQUIRED = 20 * 1 ether;
- // events
- event Invested(address indexed sender, uint256 amount, uint256 token_amount);
- event Whitelisted(address indexed investor);
- function Reservation(uint256 _maximum, uint256 _rate, uint256 _start, uint256 _end) public {
- // safety checks
- require(_maximum > 0);
- require(_rate > 0);
- require(_start > 0);
- require(_end > 0);
- require(_start < _end);
- // set owner
- owner = msg.sender;
- // set variables
- maximum = _maximum;
- rate = _rate;
- start = _start;
- end = _end;
- }
- // checks if the reservation is finished
- modifier isFinished() {
- require(now >= end);
- _;
- }
- // invest etheres
- function () payable external {
- require(this.balance < maximum);
- require(now >= start);
- require(now < end);
- // to invest more than 20 ethers you need to be whitelisted
- require(
- msg.value >= MINIMUM_INVESTMENT &&
- (
- msg.value < KYC_REQUIRED ||
- whitelist[msg.sender] == true
- )
- );
- uint256 tokens = uint256(msg.value).mul(rate).mul(uint256(7).div(5));
- ico.reserve(tokens); // this reverts the transaction if we can't reserva our tokens
- if(!invested[msg.sender]){
- investors.push(msg.sender);
- invested[msg.sender] = true;
- }
- balances[msg.sender] = balances[msg.sender].add(tokens);
- Invested(msg.sender, msg.value, tokens);
- }
- // send the tokens using the ico contract
- function sendTokens() onlyOwner isFinished public {
- require(address(ico) != address(0));
- for(uint i = 0; i < investors.length; i++){
- if(balances[investors[i]] > 0){
- uint256 amount = balances[investors[i]];
- delete balances[investors[i]];
- ico.invest.value(amount)(investors[i]);
- }
- }
- }
- // withdraw ethers
- function withdraw() public {
- uint256 amount = balances[msg.sender];
- require(amount > 0);
- balances[msg.sender] = 0;
- msg.sender.transfer(amount);
- }
- // whitelist an address
- function whitelistAddress(address _address) onlyOwner public {
- require(_address != address(0));
- whitelist[_address] = true;
- Whitelisted(_address);
- }
- function setIco(address _ico) onlyOwner public {
- ico = Crowdsale(_ico);
- }
- // once the reservation sale is finished we kill the contract and remove it from the blockchain.
- // all remaining ethers in the contract (shouldn't be any) will be send to '_address'
- function kill(address _address) onlyOwner isFinished public {
- selfdestruct(_address);
- }
- }
- contract TimeManager is Ownable {
- // usings
- using SafeMath for uint256;
- // defines
- struct TimeSlice {
- uint256 start; // start time
- uint256 end; // end time
- uint256 discount; // discount percentage
- bool active; // is active
- bool blocking; // in this period of time all tokens emitted are blocked
- }
- // public variables
- uint256 public constant MAX_SLICES = 10;
- TimeSlice[10] public time_slices; // max 10 slices
- // private variables
- uint256 private slice_count;
- bool private finished = false;
- function TimeManager(uint256[] _slices) public {
- require(
- _slices.length % 4 == 0 && // gotta have 4 values per slice
- _slices.length < MAX_SLICES.sub(1).mul(4) // check we don't exceed max_slices
- );
- slice_count = _slices.length.div(4);
- require(slice_count > 1); // we need more than one slice...
- for(uint i = 0; i < slice_count; i++){
- time_slices[i].start = _slices[i * 4 + 0];
- time_slices[i].end = _slices[i * 4 + 1];
- time_slices[i].discount = _slices[i * 4 + 2];
- time_slices[i].blocking = _slices[i * 4 + 3] == 1;
- time_slices[i].active = true;
- }
- // create the last slice
- time_slices[slice_count].start = time_slices[slice_count - 1].end;
- time_slices[slice_count].end = 1609372800; // 2020-12-31 00:00:00
- time_slices[slice_count].active = false; // we can't buy tokens here
- // our first slice must be a dummy one
- require(
- time_slices[0].start == 0 &&
- time_slices[0].end == 0
- );
- // we set the end of our dummy slice to the start of our first 'real' slice
- time_slices[0].end = time_slices[1].start;
- time_slices[0].active = false; // we can't buy tokens here
- }
- function getCurrentSlice() private constant returns(TimeSlice) {
- for(uint i = 0; i < time_slices.length; i++){
- if(time_slices[i].start <= now && time_slices[i].end > now){
- return time_slices[i];
- }
- }
- }
- function setSlice(uint256 _index, uint256 _start, uint256 _end, uint256 _discount, bool _active, bool _blocked) onlyOwner public {
- require(_index < slice_count);
- require(_start > 0);
- require(_end > 0);
- require(_start < _end);
- time_slices[_index].start = _start;
- time_slices[_index].end = _end;
- time_slices[_index].discount = _discount;
- time_slices[_index].active = _active;
- time_slices[_index].blocking = _blocked;
- }
- function calculateDiscount(uint256 _wei, uint256 _rate) public constant returns(uint256) {
- TimeSlice memory slice = getCurrentSlice();
- if(slice.active == false)
- return 0; // return 0 so that in Crowdsale.sol we'll fire an exception because we don't support 0-valued transactions
- return _wei.mul(_rate.mul(slice.discount.add(100)).div(100));
- }
- function isBlocked() public constant returns(bool) {
- TimeSlice memory slice = getCurrentSlice();
- return slice.blocking;
- }
- // this contract can't be payed
- function () payable public {
- revert();
- }
- // kill this contract once we've finished with him
- function kill() onlyOwner public {
- selfdestruct(this);
- }
- }
- contract Crowdsale is Sale {
- // uninitialized public variables
- TimeManager public time_manager;
- address public holder;
- bool public finished = false;
- uint256 public available;
- uint256 public reserve_available;
- uint256 public minimum;
- // constants
- uint256 constant MINIMUM_INVESTMENT = 0.5 * 1 ether;
- uint256 constant BLOCKING_PERIOD = 1 years;
- function Crowdsale(address _holder, string _name, address _token, address _time_manager, address _wallet, uint256 _rate, uint256 _available, uint256 _minimum)
- Sale(_name, _token, _wallet, _rate) public
- {
- // safety checks
- require(_time_manager != address(0));
- require(_holder != address(0));
- require(_available > 0);
- require(_minimum > 0);
- time_manager = TimeManager(_time_manager);
- holder = _holder;
- available = _available;
- reserve_available = _available;
- minimum = _minimum;
- }
- // checks if we have closed the crowdsale
- modifier notFinished() {
- require(!finished);
- _;
- }
- modifier isFinished() {
- require(finished);
- _;
- }
- // fallback function
- function () payable public {
- invest(msg.sender);
- }
- // end crawdsale
- function finish() onlyOwner public {
- finished = true;
- }
- // internal function for accepting payments and transfering tokens
- function invest(address _to) notFinished stopInEmergency payable public returns(uint256 tokens) {
- // minimum value
- require(msg.value >= MINIMUM_INVESTMENT);
- uint256 value_wei = msg.value;
- uint256 value_tokens = time_manager.calculateDiscount(value_wei, rate);
- // 'calculateDiscount' will return 0 if we can't buy tokens
- require(value_tokens > 0);
- // increase investor count only if it's their the first time
- if(invested_amount_wei[_to] == 0) {
- investor_count = investor_count.add(1);
- }
- // update investor
- invested_amount_wei[_to] = invested_amount_wei[_to].add(value_wei);
- invested_amount_tokens[_to] = invested_amount_tokens[_to].add(value_tokens);
- // update amounts
- raised_wei = raised_wei.add(value_wei);
- raised_tokens = raised_tokens.add(value_tokens);
- // it will throw if 'available' is less than 'value_tokens', this is our HARD CAP
- available = available.sub(value_tokens);
- // send ether to the wallet
- wallet.transfer(value_wei);
- // assign tokens to investor
- assignTokens(_to, value_tokens);
- Invested(_to, value_wei, value_tokens);
- return value_tokens;
- }
- // internal function for assigning tokens to an address
- function assignTokens(address _to, uint256 _value) internal {
- if(!token.transferFrom(holder, _to, _value))
- revert();
- if(time_manager.isBlocked()){
- uint256 end = now + BLOCKING_PERIOD;
- token.setBlockingState(_to, end, _value);
- }
- }
- // a reservation contract calls this function to try to reserve some tokens
- function reserve(uint256 _value) public {
- // this is going to throw if we try to go under 0
- reserve_available = reserve_available.sub(_value);
- }
- // once the crowdsale is finished we kill the contract and remove it from the blockchain.
- // all remaining ethers in the contract (shouldn't be any) will be send to '_address'
- function kill(address _address) onlyOwner isFinished public {
- selfdestruct(_address);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement