pragma solidity ^0.4.19;
contract Ownable {
/**
* @dev set `owner` of the contract to the sender
*/
address 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));
owner = newOwner;
}
}
library SafeMath {
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a);
return a - b;
}
}
/**
* @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) 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 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) public returns (bool) {
require(_to != address(0));
require(_value <= balances[msg.sender]);
// SafeMath.sub will throw if there is not enough balance.
balances[msg.sender] = balances[msg.sender].sub(_value);
balances[_to] += _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 view 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] += _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 view returns (uint256) {
return allowed[_owner][_spender];
}
}
/**
* @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 Burn(address indexed burner, uint value);
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 += _amount;
balances[_to] += _amount;
Mint(_to, _amount);
Transfer(address(0), _to, _amount);
return true;
}
/**
* @dev Function to burn tokens
* @param _addr The address that will have _amount of tokens burned.
* @param _amount The amount of tokens to burn.
*/
function burn(address _addr, uint _amount) onlyOwner public {
require(_amount > 0 && balances[_addr] >= _amount && totalSupply >= _amount);
balances[_addr] -= _amount;
totalSupply -= _amount;
Burn(_addr, _amount);
Transfer(_addr, address(0), _amount);
}
/**
* @dev Function to stop minting new tokens.
* @return True if the operation was successful.
*/
function finishMinting() onlyOwner canMint public returns (bool) {
mintingFinished = true;
MintFinished();
return true;
}
}
contract WealthBuilderToken is MintableToken {
string public name = "Wealth Builder Token";
string public symbol = "WBT";
uint32 public decimals = 18;
/**
* how many {tokens*10^(-18)} get per 1wei
*/
uint public rate = 10**7;
/**
* multiplicator for rate
*/
uint public mrate = 10**7;
function setRate(uint _rate) onlyOwner public {
rate = _rate;
}
}
contract Declaration {
// threshold in USD => status
mapping (uint => uint8) statusThreshold;
// status => (depositsNumber => percentage)
mapping (uint8 => mapping (uint8 => uint)) feeDistribution;
// status thresholds in USD
uint[8] thresholds = [
0, 5000, 35000, 150000, 500000, 2500000, 5000000, 10000000
];
uint[5] referralFees = [50, 30, 20, 10, 5];
uint[5] serviceFees = [25, 20, 15, 10, 5];
/**
* @dev The Declaration constructor to define some constants
*/
function Declaration() public {
setFeeDistributionsAndStatusThresholds();
}
/**
* @dev Set up fee distribution & status thresholds
*/
function setFeeDistributionsAndStatusThresholds() private {
// Agent - 0
setFeeDistributionAndStatusThreshold(0, [12, 8, 5, 2, 1], thresholds[0]);
// SilverAgent - 1
setFeeDistributionAndStatusThreshold(1, [16, 10, 6, 3, 2], thresholds[1]);
// Manager - 2
setFeeDistributionAndStatusThreshold(2, [20, 12, 8, 4, 2], thresholds[2]);
// ManagerOfGroup - 3
setFeeDistributionAndStatusThreshold(3, [25, 15, 10, 5, 3], thresholds[3]);
// ManagerOfRegion - 4
setFeeDistributionAndStatusThreshold(4, [30, 18, 12, 6, 3], thresholds[4]);
// Director - 5
setFeeDistributionAndStatusThreshold(5, [35, 21, 14, 7, 4], thresholds[5]);
// DirectorOfGroup - 6
setFeeDistributionAndStatusThreshold(6, [40, 24, 16, 8, 4], thresholds[6]);
// DirectorOfRegion - 7
setFeeDistributionAndStatusThreshold(7, [50, 30, 20, 10, 5], thresholds[7]);
}
/**
* @dev Set up specific fee and status threshold
* @param _st The status to set up for
* @param _percentages Array of pecentages, which should go to member
* @param _threshold The minimum amount of sum of children deposits to get
* the status _st
*/
function setFeeDistributionAndStatusThreshold(
uint8 _st,
uint8[5] _percentages,
uint _threshold
)
private
{
statusThreshold[_threshold] = _st;
for (uint8 i = 0; i < _percentages.length; i++) {
feeDistribution[_st][i] = _percentages[i];
}
}
}
contract Data is Ownable {
// node => its parent
mapping (address => address) private parent;
// node => its status
mapping (address => uint8) public statuses;
// node => sum of all his child deposits in USD cents
mapping (address => uint) public referralDeposits;
// client => balance in wei*10^(-6) available for withdrawal
mapping(address => uint256) private balances;
// investor => balance in wei*10^(-6) available for withdrawal
mapping(address => uint256) private investorBalances;
function parentOf(address _addr) public constant returns (address) {
return parent[_addr];
}
function balanceOf(address _addr) public constant returns (uint256) {
return balances[_addr] / 1000000;
}
function investorBalanceOf(address _addr) public constant returns (uint256) {
return investorBalances[_addr] / 1000000;
}
/**
* @dev The Data constructor to set up the first depositer
*/
function Data() public {
// DirectorOfRegion - 7
statuses[msg.sender] = 7;
}
function addBalance(address _addr, uint256 amount) onlyOwner public {
balances[_addr] += amount;
}
function subtrBalance(address _addr, uint256 amount) onlyOwner public {
require(balances[_addr] >= amount);
balances[_addr] -= amount;
}
function addInvestorBalance(address _addr, uint256 amount) onlyOwner public {
investorBalances[_addr] += amount;
}
function subtrInvestorBalance(address _addr, uint256 amount) onlyOwner public {
require(investorBalances[_addr] >= amount);
investorBalances[_addr] -= amount;
}
function addReferralDeposit(address _addr, uint256 amount) onlyOwner public {
referralDeposits[_addr] += amount;
}
function setStatus(address _addr, uint8 _status) onlyOwner public {
statuses[_addr] = _status;
}
function setParent(address _addr, address _parent) onlyOwner public {
parent[_addr] = _parent;
}
}
contract Investors is Ownable {
// investors
/*
"0x418155b19d7350f5a843b826474aa2f7623e99a6","0xbeb7a29a008d69069fd10154966870ff1dda44a0","0xa9cb1b8ba1c8facb92172e459389f80d304595a3","0xf3f2bf9be0ccc8f27a15ccf18d820c0722e8996a","0xa0f36ac9f68c1a4594ef5cec29dc9b1cc67f822c","0xc319278cca404e3a479b088922e4117feb4cec9d","0xe633c933529d6fd7c6147d2b0dc51bfbe3304e56","0x5bd2c1f2f06b16e427a4ec3a6beef6263fd506da","0x52c4f101d0367c3f9933d0c14ea389e74ad00352","0xf7a0d2149f324a0b607ebf23df671acc4e9da6d2", "0x0418df662bb2994262bb720d477e558a59e19490","0xf0de6520e0726ba3d84611f84867aa9987391402","0x1e895274a9570f150f11ae0ed86dd42a53208b81","0x95a247bef71f6b234e9805d1493366a302a498e4","0x9daaeaf355f69f7176a0145df6d1769d7f14553b","0x029136181d87c6f0979431255424b5fad78e8491","0x7e1f5669d9e1c593a495c5cec384ca32ad4a09fc","0x46c7e04fdaaa1a9298e63ca2fd47b0004cb236bf","0x5933fa485863da06584057494f0f6660d3c1477c","0x4290231804dd59947aff9fcef925287e44906e7b", "0x2feaf2101b3f9943a81567badb56e3780946ce3f","0x5b602c34ba643913908f69a4cd5846a07ed3915b","0x146308896955030ce3bcc6030bab142afddaa1e6","0x9fc61b75451fabf5b5b78e03bacaf8bb592541fc","0x87f7636f7856466b6c6bce999574a784387e2b78","0x024db1f560327ab5174f1a737caf446b5644c709","0x715c248e621cbdb6f091bf653bb4bc331d2f9b1e","0xfe92a23b497140ba055a91ade89d91f95f8e5153","0xc3426e0e0634725a628a7a21bfd49274e1f24733","0xb12a79b9dba8bbb9ed5e329466a9c2703da38dbd","0x44d8336749ebf584a4bcd636cefe83e6e0b33e7d","0x89c91460c3bdc164250e5a27351c743c070c226a","0xe0798a1b847f450b5d4819043d27a380a4715af8","0xeac5e75252d902cb7f8473e45fff9ceb391c536b","0xea53e88876a6da2579d837a559b31b08d6750681","0x5df22fac00c45ef7b5c285c54a006798f42bbc6e","0x09899f20064b5e67d02f6a97ef412564977ee193","0xc572f18d0a4a65f6e612e6de484dbc15b8839df3","0x397b9719e720c0d33fe7dcc004958e56636cbf82","0x577de83b60299df60cc7fce7ac78d3a5d880aa95", "0x9a716298949b16c4610b40ba1d19e96d3286c35c","0x60ef523f3845e38a20b63344a4e9ec689773ead6","0xe34252e3efe0514c5fb76c9fb39ff31f554d6659","0xbabfbdf4f422d36c00e448cc562ce0f5dbe47d64","0x2608cca4aff4cc3008ac6bd22e0664348ecee088","0x0dd1d3102f89d4ee7c260048cbe01933f17debde","0xdbb28fafc4ecd7736247aca7dc8e20782ca86a7a","0x6201fc413bb9292527956a70e7575436d5135ce1","0xa836f4cfb8fd3e5bccc9c7a6a678f2a5928b7c79","0x85dce799fd059d86c420eb4e3c1bd89e323b7b12","0xdef2086c6bbdc8b0f6e130907f05345b44af8cc3","0xc1004695ce07ef5efb1d218672e5cfcb659c5900","0x227a5b4bb4cffc2b907d9f586dd100989efeee56","0xd372b3d43ba8ea406f64dbc68f70ec812e54fbc8","0xdf6c417cdb27bc0c877a0e121a2c58ad884e85c6","0x090f4d53b5d7ebcb8e348709cdb708d80cd199f0","0x2499b302b6f5e57f54c1c7a326813e3dffddcd1a","0x3114024a034443e972707522d911fc709f62dd3e","0x30b864f49cef510b1173a5bfc31e77b0b59daf9e","0x9a9680f5ddee6cef96ef36ab506f4b6d3198c35e","0x08018337b9b138b631cd325168c3d5014df6e18b","0x2ac345a4ec1615c3a236099ebbed4911673bbfa5","0x2b9fd54828cd443b7c411419b058b44bd02fdc49","0x208713a63460d44e5a83ae8e8f7333496a05065e","0xe4052eb7ba8891ee7ccd7551faaa5f4c421904e7","0x74bc9db1ac813db06f771bcff359e9237b01c906","0x033dd047a042ea873ca27af36b64ca566a006e97","0xb4721808a3f2830a1708967302443b53f5943429","0xc91fbb815c2f4944d8c6846be6ac0e30f5a037df","0x19ef947c276436ac11a8be15567909a37d824e73","0x079eefd69c5a4c5e4c9ee3fa08c2a2964da3e11a","0x11fb64be296590f948d56daab6c2d102c9842b08","0x06ec97feaeb0f4b9a75f9671d6b62bfadaf18ddd","0xaeda3cff45032695fb2cf4f584cda822bd5d8b7e","0x9f377085d3da85107cd68bd08bdd9a1b862d44e0","0xb46b8d1c313c52fd422fe189dde1b4d0800a5e0f","0x99039fa34510c7321f4d19ea337c80cc14cc885d","0x378aba0f47c7790ed0e5ca61749b0025d1208a5d","0x4395e1db93d4e2f4583a4f87494eb0aea057b8fd","0xa4035578750564e48abfb5ba1d6eec1da1bf366f","0xb611b39eb6c16dae3754e514ddd5f02fcadd765f","0x67d41491ddc004e899a3faf109f526cd717fe6d8","0x58e2c10865f9a1668e800c91b6a3d7b3416fb26c","0x04e34355ced9d532c9bc01d5e569f31b6d46cd50","0xf80358cabdc9b9b79570b6f073a861cf5567bb57","0xbdacb079fc17a00d945f01f4f9bd5d03cfcd5b6c","0x387a723060bc42a7796c76197d2d3b41b4c43d19","0xa04cc8fc56c34ab8104f63c11bf211de4bb7b0aa","0x3bf8b5ede7501519d41792715215735d8f40af10","0x6c3a13bac5cf61b1927562a927e89ca6b5d034d6","0x9899aecef15de43eec04859be649ac4c50330886","0xa4d25bac971ca08b47a908a070b6362102206c12",
"0xf88d963dc3f58fe6e71879543e57734e8152f70d","0x7b30a000f7ae56ee6206cbd9fb20c934b4bbb5d1","0xb2f0e5330e90559a738eda0df156635e18a145fd","0x5b2c07b6cce506f2293f1b32dc33d9928b8c9ada","0x5a967c0e38cb3bfad90df288ce238699cc47b5e3","0x0e686d6f3c897cae3984b80b5f6a7c785c708718","0xa8ea0b6bc70502644c0644fb4c0810540a1fa261","0xc70e278819ef5aec6b3ededc21e2981557e14443","0x477b5ae32ffcd34eb25f0c52866d4f602982dc6f","0x3e72a45fbc6a0858b506a0c7bedff79af75ae37c","0x1430e272a50703ef46d8ed5aa01e1ced71245341","0xc87d0bb90a6105a66fd5105c6746218d381b8207","0x0ed7f98b6177d0c15e27704f2bae4d068b8594d5","0x09a627b57879eb625cd8b7c59ffa363222553c23","0x0fdbc41046590ef7ee2a73b9808fd5bd7e189ac4","0x6a4b68af67a3b4a98fe1a59210dd3d775e567729","0x442a3daf774329fee3e904e86ddec1191f4be3ce","0x9efa8fe7fa51c8b36ab902046f879b035520f556","0x510e8e58b8ce4acaa6866e59dfc0fa339ea358e5","0x374831251283aa63aee6506ac6580479aaf3c22b","0xf758c498d020c0b92f2116d09d7ef6509c2c71bd","0xd83e8281ffcfb0ff96236e99ba66aabb8dcc7920","0x3670c3a5e65b757db8c82b12dd92057ac19d41fa","0xfd28eb7e3e5e3406ce6b82045d487c2be294cd38","0x2d23cd492096b903e4595ccdac74e49692a6ea8e","0x94d3a0a19ed5448052c549fd1f69f54c5f1fd8c5","0x8e5354ac59cee09d252e379a3534053306022ebe","0xa66f3700dda0147c56c2970202768c956c644ffd","0xf11d32baef6221f36916c58844cd8e9813c0af47","0x384a9bc1de23b36c2a23b963e57c8cd85b0d592c","0xbd00dfbaaa1abaa7948c7b2a6bed6e644293cc1c","0xa99a28afcbd4ab09a2ef2c0932becd0368225ee6","0xe554084d77bc6e510eed7276cb6033865375b669","0xe7582fa53531915a2fef5a81b98969d0091d8d44","0x5f15db1d209fa6fd3c667fb086d3d89e3793511f","0x7e9ff5348d57d3427e24b7e104ad5acf039edaf2","0xb4fb1a01483454d75a0cdfa983b99236c4c91111","0x4a7cc5eebfe019efab06c1fa9ae8453dc63ba84e","0xb6fc08d5043b51ac05cdbd88afaab0e4422762d0","0xb18365f4f1e95287a5f85c8a67cebee9e6164c31","0xaf575cfb94d65eaeaace749868282d0e26e4608a","0x3d07e5ff3a2d29ee17584dff60cc99bb4cd79c3d","0x08f0afc93fbc8188150f4bcab004e259cd4785aa","0x65ac3ed81f101e5651c72c4cc2d74650378b5b0c","0x58aef4fc6b54cb53683a6481655021109b8d4dce","0x6aa43e24604577574a0632524a1f4c21d70a61e2","0xbee55aa5ad9953294ecac83a6b62f10c8155444b","0x99dc885ac6ec9873e2409d5a31e7f525c1897e09","0x53a0622034680d64bd0f139df5e989d70b194a4d","0xa6ba4966f1fdd0e8560516e53490b25cf0c4fbd1","0xbd1b95ee4621ecda41961da61277e17e52f37dbf","0xf6481b881eea526ae36cbe11d58d641f96f04a77","0xd158d53d75eac0dda9d2dedf3418d071a2fd44ee","0xb22697e3f33544da7782c8197d07704e1906a3bf","0xa3237e67df409dca45930c1f5f671251adc202be","0x72b26f2dded753a01f391322b00f9a85a77c7fda","0x203fbf3a77bdf35f7aca220b363272896db91d57","0xb1be2f4d72eb87dfcf7ed93c8ec16e4040e52560","0xc60d8a0313ede22194ebe6285471f72f9bcdcda0","0x9888e7423ea48413a4c90a10c76ca5f90d065e1f","0x0be856768ad0ec5b45464ce5202e2c337224cebf","0x3b54ea00a74b116510c4f73a3fc19a62991aaf64","0xe72aa06ffe7058f73622f219af164369c03e3a41","0x7e71fada017d9af455f38db4957d527f51fe1bc5","0x78430e58934220f37ca6b9dbe622f076ad0eb3f5","0x46b55dd1c8187f17b659948a991adac7b426b71e","0x0c765e201bb43d49ab5b44d40d3cf1d219424821","0x4739d251b40028761bbd8034a21919d926f23b45","0x00a7c7bc71022032f6ef3f699b212c9450875740","0x0d4f50b0d43d34a163b8dd7c33fbcc92a19cfa59","0x9284fbc0cc35d9b835de2b00b6b7093075527f6b","0x3564e101b32fe5f3c99e8da823ac003373c26d33","0xf5a358f228dc964fa7c703cb6ad9f6002ce77b17","0x8297a09b5dac9e60896c787f0995ac06441ab14f","0xed8c9b4fd60a6e4ae66c38f5819cffb360af5dd5","0x23009de4ec4a666ba719656d844e42e264e14c6b","0x63227f4492c6bbd9e1015f2c864a31eef1465cd3","0xf3e0ec409386ea202b15d97bb8dd2d131917e3b1","0x981154fafb3a5aeee43d984ee255e5121ce79790","0x49a4598cdf112b5848c11c465d39989fcb5cb6c1","0x575ca03f00f9e5566d85dc095165998953ab0753","0x09d87f2979c4ac6c9d4077d1f5d94cb9aadf43ca","0x0b4575867757b3982379f4d05c92fd2d019247a0","0x8c666d40e2ac961885d675e58e3115b859dac6c1","0x34a3401ebe8431d44efee9948c4b641142407aa8","0x1683512dbcce189ea6042862a2ba4abd4886623b","0x72d45f733336f6f03ef20c1ad4f51ff6b7f90186","0x569fe010fe2d40037c029537eef78aa9b0e018f9","0x061def9fab3aee4161711d4c040d138a273893b5","0xe77e2ae67e1152425c75ff56291d03d92f5d3cad","0x93ebdeb0b0c967f5cc1a10f481569e1871b7d7cd","0x6d7910f900fc3e3f2e2b6d5d8aad43bc6a232685",
"0xb16e28be300f579a81f2b80fdd5a95cf168bf3a4", "0xd69835daeee01601ea991efe9fd0309c64c07d42", "0x30b45ed69250a160ee91dadab2986d21626d7f4b", "0xd28075489da5f9ef51bcc61668c114296a8e8603"
*/
address[] public investors;
// investor address => percentage * 10^(-2)
/*
3313,1500,510,462,453,302,250,250,226,220,150,129,100,100,60,55,50,50,50,50,50,50,50,50,50,40,40,30,27,26,25,25,25,25,25,25,25,25,23,20,15,15,15,15,15,15,14,14,13,13,13,13,12,12,11,11,11,11,11,11,10,10,10,10,10,10,10,10,10,9,9,8,8,8,8,7,6,6,6,6,6,6,6,6,6,6,6,6,6,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,4,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,1,
6,6,125,50
*/
mapping (address => uint) public investorPercentages;
/**
* @dev Add investors
*/
function addInvestors(address[] _investors, uint[] _investorPercentages) onlyOwner public {
for (uint i = 0; i < _investors.length; i++) {
investors.push(_investors[i]);
investorPercentages[_investors[i]] = _investorPercentages[i];
}
}
/**
* @dev Get investors count
* @return uint count
*/
function getInvestorsCount() public constant returns (uint) {
return investors.length;
}
/**
* @dev Get investors' fee depending on the current year
* @return uint8 The fee percentage, which investors get
*/
function getInvestorsFee() public constant returns (uint8) {
//01/01/2020
if (now >= 1577836800) {
return 1;
}
//01/01/2019
if (now >= 1546300800) {
return 5;
}
return 10;
}
}
contract Referral is Declaration, Ownable {
using SafeMath for uint;
// reference to token contract
WealthBuilderToken private token;
// reference to data contract
Data private data;
// reference to investors contract
Investors private investors;
// investors balance to be distributed in wei*10^(2)
uint public investorsBalance;
/**
* how many USD cents get per ETH
*/
uint public ethUsdRate;
/**
* @dev The Referral constructor to set up the first depositer,
* reference to system token, data & investors and set ethUsdRate
*/
function Referral(uint _ethUsdRate, address _token, address _data, address _investors) public {
ethUsdRate = _ethUsdRate;
// instantiate token & data contracts
token = WealthBuilderToken(_token);
data = Data(_data);
investors = Investors(_investors);
investorsBalance = 0;
}
/**
* @dev Callback function
*/
function() payable public {
}
function invest(address client, uint8 depositsCount) payable public {
uint amount = msg.value;
// if less then 5 deposits
if (depositsCount < 5) {
uint serviceFee;
uint investorsFee = 0;
if (depositsCount == 0) {
uint8 investorsFeePercentage = investors.getInvestorsFee();
serviceFee = amount * (serviceFees[depositsCount].sub(investorsFeePercentage));
investorsFee = amount * investorsFeePercentage;
investorsBalance += investorsFee;
} else {
serviceFee = amount * serviceFees[depositsCount];
}
uint referralFee = amount * referralFees[depositsCount];
// distribute deposit fee among users above on the branch & update users' statuses
distribute(data.parentOf(client), 0, depositsCount, amount);
// update balance & number of deposits of user
uint active = (amount * 100)
.sub(referralFee)
.sub(serviceFee)
.sub(investorsFee);
token.mint(client, active / 100 * token.rate() / token.mrate());
// update owner`s balance
data.addBalance(owner, serviceFee * 10000);
} else {
token.mint(client, amount * token.rate() / token.mrate());
}
}
/**
* @dev Recursively distribute deposit fee between parents
* @param _node Parent address
* @param _prevPercentage The percentage for previous parent
* @param _depositsCount Count of depositer deposits
* @param _amount The amount of deposit
*/
function distribute(
address _node,
uint _prevPercentage,
uint8 _depositsCount,
uint _amount
)
private
{
address node = _node;
uint prevPercentage = _prevPercentage;
// distribute deposit fee among users above on the branch & update users' statuses
while(node != address(0)) {
uint8 status = data.statuses(node);
// count fee percentage of current node
uint nodePercentage = feeDistribution[status][_depositsCount];
uint percentage = nodePercentage.sub(prevPercentage);
data.addBalance(node, _amount * percentage * 10000);
//update refferals sum amount
data.addReferralDeposit(node, _amount * ethUsdRate / 10**18);
//update status
updateStatus(node, status);
node = data.parentOf(node);
prevPercentage = nodePercentage;
}
}
/**
* @dev Update node status if children sum amount is enough
* @param _node Node address
* @param _status Node current status
*/
function updateStatus(address _node, uint8 _status) private {
uint refDep = data.referralDeposits(_node);
for (uint i = thresholds.length - 1; i > _status; i--) {
uint threshold = thresholds[i] * 100;
if (refDep >= threshold) {
data.setStatus(_node, statusThreshold[threshold]);
break;
}
}
}
/**
* @dev Distribute fee between investors
*/
function distributeInvestorsFee(uint start, uint end) onlyOwner public {
for (uint i = start; i < end; i++) {
address investor = investors.investors(i);
uint investorPercentage = investors.investorPercentages(investor);
data.addInvestorBalance(investor, investorsBalance * investorPercentage);
}
if (end == investors.getInvestorsCount()) {
investorsBalance = 0;
}
}
/**
* @dev Set token exchange rate
* @param _rate wbt/eth rate
*/
function setRate(uint _rate) onlyOwner public {
token.setRate(_rate);
}
/**
* @dev Set ETH exchange rate
* @param _ethUsdRate eth/usd rate
*/
function setEthUsdRate(uint _ethUsdRate) onlyOwner public {
ethUsdRate = _ethUsdRate;
}
/**
* @dev Add new child
* @param _inviter parent
* @param _invitee child
*/
function invite(
address _inviter,
address _invitee
)
public onlyOwner
{
data.setParent(_invitee, _inviter);
// Agent - 0
data.setStatus(_invitee, 0);
}
/**
* @dev Set _status for _addr
* @param _addr address
* @param _status ref. status
*/
function setStatus(address _addr, uint8 _status) public onlyOwner {
data.setStatus(_addr, _status);
}
/**
* @dev Set investors contract address
* @param _addr address
*/
function setInvestors(address _addr) public onlyOwner {
investors = Investors(_addr);
}
/**
* @dev Withdraw _amount for _addr
* @param _addr withdrawal address
* @param _amount withdrawal amount
*/
function withdraw(address _addr, uint256 _amount, bool investor) public onlyOwner {
uint amount = investor ? data.investorBalanceOf(_addr)
: data.balanceOf(_addr);
require(amount >= _amount && this.balance >= _amount);
if (investor) {
data.subtrInvestorBalance(_addr, _amount * 1000000);
} else {
data.subtrBalance(_addr, _amount * 1000000);
}
_addr.transfer(_amount);
}
/**
* @dev Withdraw contract balance to _addr
* @param _addr withdrawal address
*/
function withdrawOwner(address _addr, uint256 _amount) public onlyOwner {
require(this.balance >= _amount);
_addr.transfer(_amount);
}
/**
* @dev Withdraw corresponding amount of ETH to _addr and burn _value tokens
* @param _addr withdrawal address
* @param _amount amount of tokens to sell
*/
function withdrawToken(address _addr, uint256 _amount) onlyOwner public {
token.burn(_addr, _amount);
uint256 etherValue = _amount * token.mrate() / token.rate();
_addr.transfer(etherValue);
}
/**
* @dev Transfer ownership of token contract to _addr
* @param _addr address
*/
function transferTokenOwnership(address _addr) onlyOwner public {
token.transferOwnership(_addr);
}
/**
* @dev Transfer ownership of data contract to _addr
* @param _addr address
*/
function transferDataOwnership(address _addr) onlyOwner public {
data.transferOwnership(_addr);
}
}
{
"compilationTarget": {
"Referral.sol": "Referral"
},
"libraries": {},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"constant":false,"inputs":[{"name":"_addr","type":"address"}],"name":"setInvestors","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_addr","type":"address"}],"name":"transferTokenOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_addr","type":"address"},{"name":"_status","type":"uint8"}],"name":"setStatus","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_rate","type":"uint256"}],"name":"setRate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"start","type":"uint256"},{"name":"end","type":"uint256"}],"name":"distributeInvestorsFee","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"ethUsdRate","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"investorsBalance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"client","type":"address"},{"name":"depositsCount","type":"uint8"}],"name":"invest","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"_inviter","type":"address"},{"name":"_invitee","type":"address"}],"name":"invite","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":"_addr","type":"address"},{"name":"_amount","type":"uint256"}],"name":"withdrawToken","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_addr","type":"address"},{"name":"_amount","type":"uint256"}],"name":"withdrawOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_addr","type":"address"}],"name":"transferDataOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_addr","type":"address"},{"name":"_amount","type":"uint256"},{"name":"investor","type":"bool"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_ethUsdRate","type":"uint256"}],"name":"setEthUsdRate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_ethUsdRate","type":"uint256"},{"name":"_token","type":"address"},{"name":"_data","type":"address"},{"name":"_investors","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"}]