pragma solidity ^0.4.20;
/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
*/
library SafeMath {
function mul(uint256 a, uint256 b) internal constant returns (uint256) {
uint256 c = a * b;
assert(a == 0 || c / a == b);
return c;
}
function div(uint256 a, uint256 b) internal constant 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 constant returns (uint256) {
assert(b <= a);
return a - b;
}
function add(uint256 a, uint256 b) internal constant returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
}
/**
* @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() {
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;
}
}
/**
* @title ERC20Basic
* @dev Simpler version of ERC20 interface
* @dev see https://github.com/ethereum/EIPs/issues/179
*/
contract ERC20Basic {
uint256 public totalSupply;
function balanceOf(address who) constant returns (uint256);
function transfer(address to, uint256 value) 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) constant returns (uint256);
function transferFrom(address from, address to, uint256 value) returns (bool);
function approve(address spender, uint256 value) returns (bool);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
/**
* @title Basic token
* @dev Basic version of StandardToken, with no allowances.
*/
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) returns (bool) {
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) constant returns (uint256 balance) {
return balances[_owner];
}
}
/**
* @title Standard ERC20 token
*
* @dev Implementation of the basic standard token.
* @dev https://github.com/ethereum/EIPs/issues/20
* @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
*/
contract StandardToken is ERC20, BasicToken {
mapping (address => mapping (address => uint256)) internal allowed;
/**
* @dev Transfer tokens from one address to another
* @param _from address The address which you want to send tokens from
* @param _to address The address which you want to transfer to
* @param _value uint256 the amount of tokens to be transferred
*/
function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
require(_to != address(0));
require(_value <= balances[_from]);
require(_value <= allowed[_from][msg.sender]);
balances[_from] = balances[_from].sub(_value);
balances[_to] = balances[_to].add(_value);
allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
Transfer(_from, _to, _value);
return true;
}
/**
* @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
*
* Beware that changing an allowance with this method brings the risk that someone may use both the old
* and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
* race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
* @param _spender The address which will spend the funds.
* @param _value The amount of tokens to be spent.
*/
function approve(address _spender, uint256 _value) public returns (bool) {
allowed[msg.sender][_spender] = _value;
Approval(msg.sender, _spender, _value);
return true;
}
/**
* @dev Function to check the amount of tokens that an owner allowed to a spender.
* @param _owner address The address which owns the funds.
* @param _spender address The address which will spend the funds.
* @return A uint256 specifying the amount of tokens still available for the spender.
*/
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, uint _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, uint _subtractedValue) public returns (bool success) {
uint 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;
}
}
/**
* @title Pausable
* @dev Base contract which allows children to implement an emergency stop mechanism.
*/
contract Pausable is Ownable {
event Pause();
event Unpause();
bool public paused = false;
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*/
modifier whenNotPaused() {
require(!paused);
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*/
modifier whenPaused() {
require(paused);
_;
}
/**
* @dev called by the owner to pause, triggers stopped state
*/
function pause() onlyOwner whenNotPaused public {
paused = true;
Pause();
}
/**
* @dev called by the owner to unpause, returns to normal state
*/
function unpause() onlyOwner whenPaused public {
paused = false;
Unpause();
}
}
/**
* @title Pausable token
*
* @dev StandardToken modified with pausable transfers.
**/
contract PausableToken is StandardToken, Pausable {
function transfer(address _to, uint256 _value) public whenNotPaused returns (bool) {
return super.transfer(_to, _value);
}
function transferFrom(address _from, address _to, uint256 _value) public whenNotPaused returns (bool) {
return super.transferFrom(_from, _to, _value);
}
function approve(address _spender, uint256 _value) public whenNotPaused returns (bool) {
return super.approve(_spender, _value);
}
function increaseApproval(address _spender, uint _addedValue) public whenNotPaused returns (bool success) {
return super.increaseApproval(_spender, _addedValue);
}
function decreaseApproval(address _spender, uint _subtractedValue) public whenNotPaused returns (bool success) {
return super.decreaseApproval(_spender, _subtractedValue);
}
}
/**
* @title Mintable token
* @dev Simple ERC20 Token example, with mintable token creation
* @dev Issue: * https://github.com/OpenZeppelin/zeppelin-solidity/issues/120
* Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol
*/
contract MintableToken is StandardToken, Ownable {
event Mint(address indexed to, uint256 amount);
event MintFinished();
bool public mintingFinished = false;
modifier canMint() {
require(!mintingFinished);
_;
}
/**
* @dev Function to mint tokens
* @param _to The address that will receive the minted tokens.
* @param _amount The amount of tokens to mint.
* @return A boolean that indicates if the operation was successful.
*/
function mint(address _to, uint256 _amount) onlyOwner canMint public returns (bool) {
totalSupply = totalSupply.add(_amount);
balances[_to] = balances[_to].add(_amount);
Mint(_to, _amount);
Transfer(0x0, _to, _amount);
return true;
}
/**
* @dev Function to stop minting new tokens.
* @return True if the operation was successful.
*/
function finishMinting() onlyOwner public returns (bool) {
mintingFinished = true;
MintFinished();
return true;
}
}
/*
* Company reserve pool where the tokens will be locked for two years
* @title Company token reserve
*/
contract AdviserTimeLock is Ownable{
SignalsToken token;
uint256 withdrawn;
uint start;
event TokensWithdrawn(address owner, uint amount);
/*
* Constructor changing owner to owner multisig & setting time lock
* @param address of the Signals Token contract
* @param address of the owner multisig
*/
function AdviserTimeLock(address _token, address _owner) public{
token = SignalsToken(_token);
owner = _owner;
start = now;
}
/*
* Only function for periodical tokens withdrawal (with monthly allowance)
* @dev Will withdraw the whole allowance;
*/
function withdraw() onlyOwner public {
require(now - start >= 25920000);
uint toWithdraw = canWithdraw();
token.transfer(owner, toWithdraw);
withdrawn += toWithdraw;
TokensWithdrawn(owner, toWithdraw);
}
/*
* Only function for the tokens withdrawal (with two years time lock)
* @dev Based on division down rounding
*/
function canWithdraw() public view returns (uint256) {
uint256 sinceStart = now - start;
uint256 allowed = (sinceStart/2592000)*504546000000000;
uint256 toWithdraw;
if (allowed > token.balanceOf(address(this))) {
toWithdraw = token.balanceOf(address(this));
} else {
toWithdraw = allowed - withdrawn;
}
return toWithdraw;
}
/*
* Function to clean up the state and moved not allocated tokens to custody
*/
function cleanUp() onlyOwner public {
require(token.balanceOf(address(this)) == 0);
selfdestruct(owner);
}
}
/*
* Pre-allocation pool for company advisers
* @title Advisory pool
*/
contract AdvisoryPool is Ownable{
SignalsToken token;
/*
* @dev constant addresses of all advisers
*/
address constant ADVISER1 = 0x7915D5A865FE68C63112be5aD3DCA5187EB08f24;
address constant ADVISER2 = 0x31cFF39AA68B91fa7C957272A6aA8fB8F7b69Cb0;
address constant ADVISER3 = 0x358b3aeec9fae5ab15fe28d2fe6c7c9fda596857;
address constant ADVISER4 = 0x1011FC646261eb5d4aB875886f1470d4919d83c8;
address constant ADVISER5 = 0xcc04Cd98da89A9172372aEf4B62BEDecd01A7F5a;
address constant ADVISER6 = 0xECD791f8E548D46A9711D853Ead7edC685Ca4ee8;
address constant ADVISER7 = 0x38B58e5783fd4D077e422B3362E9d6B265484e3f;
address constant ADVISER8 = 0x2934205135A129F995AC891C143cCae83ce175c7;
address constant ADVISER9 = 0x9F5D00F4A383bAd14DEfA9aee53C5AF2ad9ad32F;
address constant ADVISER10 = 0xBE993c982Fc5a0C0360CEbcEf9e4d2727339d96B;
address constant ADVISER11 = 0xdf1E2126eB638335eFAb91a834db4c57Cbe18735;
address constant ADVISER12 = 0x8A404969Ad1BCD3F566A7796722f535eD9cA22b2;
address constant ADVISER13 = 0x066a8aD6fA94AC83e1AFB5Aa7Dc62eD1D2654bB2;
address constant ADVISER14 = 0xA1425Fa987d1b724306d93084b93D62F37482c4b;
address constant ADVISER15 = 0x4633515904eE5Bc18bEB70277455525e84a51e90;
address constant ADVISER16 = 0x230783Afd438313033b07D39E3B9bBDBC7817759;
address constant ADVISER17 = 0xe8b9b07c1cca9aE9739Cec3D53004523Ab206CAc;
address constant ADVISER18 = 0x0E73f16CfE7F545C0e4bB63A9Eef18De8d7B422d;
address constant ADVISER19 = 0x6B4c6B603ca72FE7dde971CF833a58415737826D;
address constant ADVISER20 = 0x823D3123254a3F9f9d3759FE3Fd7d15e21a3C5d8;
address constant ADVISER21 = 0x0E48bbc496Ae61bb790Fc400D1F1a57520f772Df;
address constant ADVISER22 = 0x06Ee8eCc0145CcaCEc829490e3c557f577BE0e85;
address constant ADVISER23 = 0xbE56bFF75A1cB085674Cc37a5C8746fF6C43C442;
address constant ADVISER24 = 0xb442b5297E4aEf19E489530E69dFef7fae27F4A5;
address constant ADVISER25 = 0x50EF1d6a7435C7FB3dB7c204b74EB719b1EE3dab;
address constant ADVISER26 = 0x3e9fed606822D5071f8a28d2c8B51E6964160CB2;
AdviserTimeLock public tokenLocker23;
/*
* Constructor changing owner to owner multisig & calling the allocation
* @param address of the Signals Token contract
* @param address of the owner multisig
*/
function AdvisoryPool(address _token, address _owner) public {
owner = _owner;
token = SignalsToken(_token);
}
/*
* Allocation function, tokens get allocated from this contract as current token owner
* @dev only accessible from the constructor
*/
function initiate() public onlyOwner {
require(token.balanceOf(address(this)) == 18500000000000000);
tokenLocker23 = new AdviserTimeLock(address(token), ADVISER23);
token.transfer(ADVISER1, 380952380000000);
token.transfer(ADVISER2, 380952380000000);
token.transfer(ADVISER3, 659200000000000);
token.transfer(ADVISER4, 95238100000000);
token.transfer(ADVISER5, 1850000000000000);
token.transfer(ADVISER6, 15384620000000);
token.transfer(ADVISER7, 62366450000000);
token.transfer(ADVISER8, 116805560000000);
token.transfer(ADVISER9, 153846150000000);
token.transfer(ADVISER10, 10683760000000);
token.transfer(ADVISER11, 114285710000000);
token.transfer(ADVISER12, 576923080000000);
token.transfer(ADVISER13, 76190480000000);
token.transfer(ADVISER14, 133547010000000);
token.transfer(ADVISER15, 96153850000000);
token.transfer(ADVISER16, 462500000000000);
token.transfer(ADVISER17, 462500000000000);
token.transfer(ADVISER18, 399865380000000);
token.transfer(ADVISER19, 20032050000000);
token.transfer(ADVISER20, 35559130000000);
token.transfer(ADVISER21, 113134000000000);
token.transfer(ADVISER22, 113134000000000);
token.transfer(address(tokenLocker23), 5550000000000000);
token.transfer(ADVISER23, 1850000000000000);
token.transfer(ADVISER24, 100000000000000);
token.transfer(ADVISER25, 100000000000000);
token.transfer(ADVISER26, 2747253000000000);
}
/*
* Clean up function for token loss prevention and cleaning up Ethereum blockchain
* @dev call to clean up the contract
*/
function cleanUp() onlyOwner public {
uint256 notAllocated = token.balanceOf(address(this));
token.transfer(owner, notAllocated);
selfdestruct(owner);
}
}
/*
* Pre-allocation pool for the community, will be govern by a company multisig
* @title Community pool
*/
contract CommunityPool is Ownable{
SignalsToken token;
event CommunityTokensAllocated(address indexed member, uint amount);
/*
* Constructor changing owner to owner multisig
* @param address of the Signals Token contract
* @param address of the owner multisig
*/
function CommunityPool(address _token, address _owner) public{
token = SignalsToken(_token);
owner = _owner;
}
/*
* Function to alloc tokens to a community member
* @param address of community member
* @param uint amount units of tokens to be given away
*/
function allocToMember(address member, uint amount) public onlyOwner {
require(amount > 0);
token.transfer(member, amount);
CommunityTokensAllocated(member, amount);
}
/*
* Clean up function
* @dev call to clean up the contract after all tokens were assigned
*/
function clean() public onlyOwner {
require(token.balanceOf(address(this)) == 0);
selfdestruct(owner);
}
}
/*
* Company reserve pool where the tokens will be locked for two years
* @title Company token reserve
*/
contract CompanyReserve is Ownable{
SignalsToken token;
uint256 withdrawn;
uint start;
/*
* Constructor changing owner to owner multisig & setting time lock
* @param address of the Signals Token contract
* @param address of the owner multisig
*/
function CompanyReserve(address _token, address _owner) public {
token = SignalsToken(_token);
owner = _owner;
start = now;
}
event TokensWithdrawn(address owner, uint amount);
/*
* Only function for the tokens withdrawal (3% anytime, 5% after one year, 10% after two year)
* @dev Will withdraw the whole allowance;
*/
function withdraw() onlyOwner public {
require(now - start >= 25920000);
uint256 toWithdraw = canWithdraw();
withdrawn += toWithdraw;
token.transfer(owner, toWithdraw);
TokensWithdrawn(owner, toWithdraw);
}
/*
* Checker function to find out how many tokens can be withdrawn.
* note: percentage of the token.totalSupply
* @dev Based on division down rounding
*/
function canWithdraw() public view returns (uint256) {
uint256 sinceStart = now - start;
uint256 allowed;
if (sinceStart >= 0) {
allowed = 555000000000000;
} else if (sinceStart >= 31536000) { // one year difference
allowed = 1480000000000000;
} else if (sinceStart >= 63072000) { // two years difference
allowed = 3330000000000000;
} else {
return 0;
}
return allowed - withdrawn;
}
/*
* Function to clean up the state and moved not allocated tokens to custody
*/
function cleanUp() onlyOwner public {
require(token.balanceOf(address(this)) == 0);
selfdestruct(owner);
}
}
/**
* @title Signals token
* @dev Mintable token created for Signals.Network
*/
contract PresaleToken is PausableToken, MintableToken {
// Standard token variables
string constant public name = "SGNPresaleToken";
string constant public symbol = "SGN";
uint8 constant public decimals = 9;
event TokensBurned(address initiatior, address indexed _partner, uint256 _tokens);
/*
* Constructor which pauses the token at the time of creation
*/
function PresaleToken() public {
pause();
}
/*
* @dev Token burn function to be called at the time of token swap
* @param _partner address to use for token balance buring
* @param _tokens uint256 amount of tokens to burn
*/
function burnTokens(address _partner, uint256 _tokens) public onlyOwner {
require(balances[_partner] >= _tokens);
balances[_partner] -= _tokens;
totalSupply -= _tokens;
TokensBurned(msg.sender, _partner, _tokens);
}
}
/**
* @title Signals token
* @dev Mintable token created for Signals.Network
*/
contract SignalsToken is PausableToken, MintableToken {
// Standard token variables
string constant public name = "Signals Network Token";
string constant public symbol = "SGN";
uint8 constant public decimals = 9;
}
contract PrivateRegister is Ownable {
struct contribution {
bool approved;
uint8 extra;
}
mapping (address => contribution) verified;
event ApprovedInvestor(address indexed investor);
event BonusesRegistered(address indexed investor, uint8 extra);
/*
* Approve function to adjust allowance to investment of each individual investor
* @param _investor address sets the beneficiary for later use
* @param _referral address to pay a commission in token to
* @param _commission uint8 expressed as a number between 0 and 5
*/
function approve(address _investor, uint8 _extra) onlyOwner public{
require(!isContract(_investor));
verified[_investor].approved = true;
if (_extra <= 100) {
verified[_investor].extra = _extra;
BonusesRegistered(_investor, _extra);
}
ApprovedInvestor(_investor);
}
/*
* Constant call to find out if an investor is registered
* @param _investor address to be checked
* @return bool is true is _investor was approved
*/
function approved(address _investor) view public returns (bool) {
return verified[_investor].approved;
}
/*
* Constant call to find out the referral and commission to bound to an investor
* @param _investor address to be checked
* @return address of the referral, returns 0x0 if there is none
* @return uint8 commission to be paid out on any investment
*/
function getBonuses(address _investor) view public returns (uint8 extra) {
return verified[_investor].extra;
}
/*
* Check if address is a contract to prevent contracts from participating the direct sale.
* @param addr address to be checked
* @return boolean of it is or isn't an contract address
* @credits Manuel Aráoz
*/
function isContract(address addr) public view returns (bool) {
uint size;
assembly { size := extcodesize(addr) }
return size > 0;
}
}
contract CrowdsaleRegister is Ownable {
struct contribution {
bool approved;
uint8 commission;
uint8 extra;
}
mapping (address => contribution) verified;
event ApprovedInvestor(address indexed investor);
event BonusesRegistered(address indexed investor, uint8 commission, uint8 extra);
/*
* Approve function to adjust allowance to investment of each individual investor
* @param _investor address sets the beneficiary for later use
* @param _referral address to pay a commission in token to
* @param _commission uint8 expressed as a number between 0 and 5
*/
function approve(address _investor, uint8 _commission, uint8 _extra) onlyOwner public{
require(!isContract(_investor));
verified[_investor].approved = true;
if (_commission <= 15 && _extra <= 5) {
verified[_investor].commission = _commission;
verified[_investor].extra = _extra;
BonusesRegistered(_investor, _commission, _extra);
}
ApprovedInvestor(_investor);
}
/*
* Constant call to find out if an investor is registered
* @param _investor address to be checked
* @return bool is true is _investor was approved
*/
function approved(address _investor) view public returns (bool) {
return verified[_investor].approved;
}
/*
* Constant call to find out the referral and commission to bound to an investor
* @param _investor address to be checked
* @return address of the referral, returns 0x0 if there is none
* @return uint8 commission to be paid out on any investment
*/
function getBonuses(address _investor) view public returns (uint8 commission, uint8 extra) {
return (verified[_investor].commission, verified[_investor].extra);
}
/*
* Check if address is a contract to prevent contracts from participating the direct sale.
* @param addr address to be checked
* @return boolean of it is or isn't an contract address
* @credits Manuel Aráoz
*/
function isContract(address addr) public view returns (bool) {
uint size;
assembly { size := extcodesize(addr) }
return size > 0;
}
}
/*
* Token pool for the presale tokens swap
* @title PresalePool
* @dev Requires to transfer ownership of both PresaleToken contracts to this contract
*/
contract PresalePool is Ownable {
PresaleToken public PublicPresale;
PresaleToken public PartnerPresale;
SignalsToken token;
CrowdsaleRegister registry;
/*
* Compensation coefficient based on the difference between the max ETHUSD price during the presale
* and price fix for mainsale
*/
uint256 compensation1;
uint256 compensation2;
// Date after which all tokens left will be transfered to the company reserve
uint256 deadLine;
event SupporterResolved(address indexed supporter, uint256 burned, uint256 created);
event PartnerResolved(address indexed partner, uint256 burned, uint256 created);
/*
* Constructor changing owner to owner multisig, setting all the contract addresses & compensation rates
* @param address of the Signals Token contract
* @param address of the KYC registry
* @param address of the owner multisig
* @param uint rate of the compensation for early investors
* @param uint rate of the compensation for partners
*/
function PresalePool(address _token, address _registry, address _owner, uint comp1, uint comp2) public {
owner = _owner;
PublicPresale = PresaleToken(0x15fEcCA27add3D28C55ff5b01644ae46edF15821);
PartnerPresale = PresaleToken(0xa70435D1a3AD4149B0C13371E537a22002Ae530d);
token = SignalsToken(_token);
registry = CrowdsaleRegister(_registry);
compensation1 = comp1;
compensation2 = comp2;
deadLine = now + 30 days;
}
/*
* Fallback function for simple contract usage, only calls the swap()
* @dev left for simpler interaction
*/
function() public {
swap();
}
/*
* Function swapping the presale tokens for the Signal tokens regardless on the presale pool
* @dev requires having ownership of the two presale contracts
* @dev requires the calling party to finish the KYC process fully
*/
function swap() public {
require(registry.approved(msg.sender));
uint256 oldBalance;
uint256 newBalance;
if (PublicPresale.balanceOf(msg.sender) > 0) {
oldBalance = PublicPresale.balanceOf(msg.sender);
newBalance = oldBalance * compensation1 / 100;
PublicPresale.burnTokens(msg.sender, oldBalance);
token.transfer(msg.sender, newBalance);
SupporterResolved(msg.sender, oldBalance, newBalance);
}
if (PartnerPresale.balanceOf(msg.sender) > 0) {
oldBalance = PartnerPresale.balanceOf(msg.sender);
newBalance = oldBalance * compensation2 / 100;
PartnerPresale.burnTokens(msg.sender, oldBalance);
token.transfer(msg.sender, newBalance);
PartnerResolved(msg.sender, oldBalance, newBalance);
}
}
/*
* Function swapping the presale tokens for the Signal tokens regardless on the presale pool
* @dev initiated from Signals (passing the ownership to a oracle to handle a script is recommended)
* @dev requires having ownership of the two presale contracts
* @dev requires the calling party to finish the KYC process fully
*/
function swapFor(address whom) onlyOwner public returns(bool) {
require(registry.approved(whom));
uint256 oldBalance;
uint256 newBalance;
if (PublicPresale.balanceOf(whom) > 0) {
oldBalance = PublicPresale.balanceOf(whom);
newBalance = oldBalance * compensation1 / 100;
PublicPresale.burnTokens(whom, oldBalance);
token.transfer(whom, newBalance);
SupporterResolved(whom, oldBalance, newBalance);
}
if (PartnerPresale.balanceOf(whom) > 0) {
oldBalance = PartnerPresale.balanceOf(whom);
newBalance = oldBalance * compensation2 / 100;
PartnerPresale.burnTokens(whom, oldBalance);
token.transfer(whom, newBalance);
SupporterResolved(whom, oldBalance, newBalance);
}
return true;
}
/*
* Function to clean up the state and moved not allocated tokens to custody
*/
function clean() onlyOwner public {
require(now >= deadLine);
uint256 notAllocated = token.balanceOf(address(this));
token.transfer(owner, notAllocated);
selfdestruct(owner);
}
}
/**
* @title Crowdsale
* @dev Crowdsale is a base contract for managing a token crowdsale.
* Crowdsales have a start and end timestamps, 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
SignalsToken public token;
// address where funds are collected
address public wallet;
// amount of raised money in wei
uint256 public weiRaised;
// start/end related
uint256 public startTime;
bool public hasEnded;
/**
* 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(address _token, address _wallet) public {
require(_wallet != 0x0);
token = SignalsToken(_token);
wallet = _wallet;
}
// fallback function can be used to buy tokens
function () public payable {
buyTokens(msg.sender);
}
// low level token purchase function
function buyTokens(address beneficiary) private {}
// 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 validPurchase() internal constant returns (bool) {}
}
/**
* @title FinalizableCrowdsale
* @dev Extension of Crowdsale where an owner can do extra work
* after finishing.
*/
contract FinalizableCrowdsale is Crowdsale, Ownable {
using SafeMath for uint256;
bool public isFinalized = false;
event Finalized();
/**
* @dev Must be called after crowdsale ends, to do some extra finalization
* work. Calls the contract's finalization function.
*/
function finalize() onlyOwner public {
require(!isFinalized);
require(hasEnded);
finalization();
Finalized();
isFinalized = true;
}
/**
* @dev Can be overridden to add finalization logic. The overriding function
* should call super.finalization() to ensure the chain of finalization is
* executed entirely.
*/
function finalization() internal {
}
}
contract SignalsCrowdsale is FinalizableCrowdsale {
// Cap & price related values
uint256 public constant HARD_CAP = 18000*(10**18);
uint256 public toBeRaised = 18000*(10**18);
uint256 public constant PRICE = 360000;
uint256 public tokensSold;
uint256 public constant maxTokens = 185000000*(10**9);
// Allocation constants
uint constant ADVISORY_SHARE = 18500000*(10**9); //FIXED
uint constant BOUNTY_SHARE = 3700000*(10**9); // FIXED
uint constant COMMUNITY_SHARE = 37000000*(10**9); //FIXED
uint constant COMPANY_SHARE = 33300000*(10**9); //FIXED
uint constant PRESALE_SHARE = 7856217611546440; // FIXED;
// Address pointers
address constant ADVISORS = 0x98280b2FD517a57a0B8B01b674457Eb7C6efa842; // TODO: change
address constant BOUNTY = 0x8726D7ac344A0BaBFd16394504e1cb978c70479A; // TODO: change
address constant COMMUNITY = 0x90CDbC88aB47c432Bd47185b9B0FDA1600c22102; // TODO: change
address constant COMPANY = 0xC010b2f2364372205055a299B28ef934f090FE92; // TODO: change
address constant PRESALE = 0x7F3a38fa282B16973feDD1E227210Ec020F2481e; // TODO: change
CrowdsaleRegister register;
PrivateRegister register2;
// Start & End related vars
bool public ready;
// Events
event SaleWillStart(uint256 time);
event SaleReady();
event SaleEnds(uint256 tokensLeft);
function SignalsCrowdsale(address _token, address _wallet, address _register, address _register2) public
FinalizableCrowdsale()
Crowdsale(_token, _wallet)
{
register = CrowdsaleRegister(_register);
register2 = PrivateRegister(_register2);
}
// @return true if the transaction can buy tokens
function validPurchase() internal constant returns (bool) {
bool started = (startTime <= now);
bool nonZeroPurchase = msg.value != 0;
bool capNotReached = (weiRaised < HARD_CAP);
bool approved = register.approved(msg.sender);
bool approved2 = register2.approved(msg.sender);
return ready && started && !hasEnded && nonZeroPurchase && capNotReached && (approved || approved2);
}
/*
* Buy in function to be called from the fallback function
* @param beneficiary address
*/
function buyTokens(address beneficiary) private {
require(beneficiary != 0x0);
require(validPurchase());
uint256 weiAmount = msg.value;
// base discount
uint256 discount = ((toBeRaised*10000)/HARD_CAP)*15;
// calculate token amount to be created
uint256 tokens;
// update state
weiRaised = weiRaised.add(weiAmount);
toBeRaised = toBeRaised.sub(weiAmount);
uint commission;
uint extra;
uint premium;
if (register.approved(beneficiary)) {
(commission, extra) = register.getBonuses(beneficiary);
// If extra access granted then give additional %
if (extra > 0) {
discount += extra*10000;
}
tokens = howMany(msg.value, discount);
// If referral was involved, give some percent to the source
if (commission > 0) {
premium = tokens.mul(commission).div(100);
token.mint(BOUNTY, premium);
}
} else {
extra = register2.getBonuses(beneficiary);
if (extra > 0) {
discount = extra*10000;
tokens = howMany(msg.value, discount);
}
}
token.mint(beneficiary, tokens);
TokenPurchase(msg.sender, beneficiary, weiAmount, tokens);
tokensSold += tokens + premium;
forwardFunds();
assert(token.totalSupply() <= maxTokens);
}
/*
* Helper token emission functions
* @param value uint256 of the wei amount that gets invested
* @return uint256 of how many tokens can one get
*/
function howMany(uint256 value, uint256 discount) public view returns (uint256){
uint256 actualPrice = PRICE * (1000000 - discount) / 1000000;
return value / actualPrice;
}
/*
* Function to do preallocations - MANDATORY to continue
* @dev It's separated so it doesn't have to run in constructor
*/
function initialize() public onlyOwner {
require(!ready);
// Pre-allocation to pools
token.mint(ADVISORS,ADVISORY_SHARE);
token.mint(BOUNTY,BOUNTY_SHARE);
token.mint(COMMUNITY,COMMUNITY_SHARE);
token.mint(COMPANY,COMPANY_SHARE);
token.mint(PRESALE,PRESALE_SHARE);
tokensSold = PRESALE_SHARE;
ready = true;
SaleReady();
}
/*
* Function to do set or adjust the startTime - NOT MANDATORY but good for future start
*/
function changeStart(uint256 _time) public onlyOwner {
startTime = _time;
SaleWillStart(_time);
}
/*
* Function end or pause the sale
* @dev It's MANDATORY to finalize()
*/
function endSale(bool end) public onlyOwner {
require(startTime <= now);
uint256 tokensLeft = maxTokens - token.totalSupply();
if (tokensLeft > 0) {
token.mint(wallet, tokensLeft);
}
hasEnded = end;
SaleEnds(tokensLeft);
}
/*
* Adjust finalization to transfer token ownership to the fund holding address for further use
*/
function finalization() internal {
token.finishMinting();
token.transferOwnership(wallet);
}
/*
* Clean up function to get the contract selfdestructed - OPTIONAL
*/
function cleanUp() public onlyOwner {
require(isFinalized);
selfdestruct(owner);
}
}
{
"compilationTarget": {
"SignalsCrowdsale.sol": "SignalsCrowdsale"
},
"libraries": {},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"constant":true,"inputs":[],"name":"toBeRaised","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"HARD_CAP","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":false,"inputs":[],"name":"finalize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"tokensSold","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":"ready","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"value","type":"uint256"},{"name":"discount","type":"uint256"}],"name":"howMany","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"startTime","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"isFinalized","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"PRICE","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_time","type":"uint256"}],"name":"changeStart","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"end","type":"bool"}],"name":"endSale","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"maxTokens","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"hasEnded","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"cleanUp","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"token","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_token","type":"address"},{"name":"_wallet","type":"address"},{"name":"_register","type":"address"},{"name":"_register2","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":false,"name":"time","type":"uint256"}],"name":"SaleWillStart","type":"event"},{"anonymous":false,"inputs":[],"name":"SaleReady","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"tokensLeft","type":"uint256"}],"name":"SaleEnds","type":"event"},{"anonymous":false,"inputs":[],"name":"Finalized","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"}]