Created
September 5, 2017 00:07
-
-
Save vamshi4001/9876665133983449ef7bafae327a1171 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.4.8; | |
/** | |
* Math operations with safety checks | |
*/ | |
library SafeMath { | |
function mul(uint a, uint b) internal returns (uint) { | |
uint c = a * b; | |
assert(a == 0 || c / a == b); | |
return c; | |
} | |
function div(uint a, uint b) internal returns (uint) { | |
assert(b > 0); | |
uint c = a / b; | |
assert(a == b * c + a % b); | |
return c; | |
} | |
function sub(uint a, uint b) internal returns (uint) { | |
assert(b <= a); | |
return a - b; | |
} | |
function add(uint a, uint b) internal returns (uint) { | |
uint c = a + b; | |
assert(c >= a); | |
return c; | |
} | |
function max64(uint64 a, uint64 b) internal constant returns (uint64) { | |
return a >= b ? a : b; | |
} | |
function min64(uint64 a, uint64 b) internal constant returns (uint64) { | |
return a < b ? a : b; | |
} | |
function max256(uint256 a, uint256 b) internal constant returns (uint256) { | |
return a >= b ? a : b; | |
} | |
function min256(uint256 a, uint256 b) internal constant returns (uint256) { | |
return a < b ? a : b; | |
} | |
function assert(bool assertion) internal { | |
if (!assertion) { | |
throw; | |
} | |
} | |
} | |
/* | |
* ERC20Basic | |
* Simpler version of ERC20 interface | |
* see https://github.com/ethereum/EIPs/issues/20 | |
*/ | |
contract ERC20Basic { | |
uint public totalSupply; | |
function balanceOf(address who) constant returns (uint); | |
function transfer(address to, uint value); | |
event Transfer(address indexed from, address indexed to, uint value); | |
} | |
/* | |
* ERC20 interface | |
* see https://github.com/ethereum/EIPs/issues/20 | |
*/ | |
contract ERC20 is ERC20Basic { | |
function allowance(address owner, address spender) constant returns (uint); | |
function transferFrom(address from, address to, uint value); | |
function approve(address spender, uint value); | |
event Approval(address indexed owner, address indexed spender, uint value); | |
} | |
/* | |
* Basic token | |
* Basic version of StandardToken, with no allowances | |
*/ | |
contract BasicToken is ERC20Basic { | |
using SafeMath for uint; | |
mapping(address => uint) balances; | |
/* | |
* Fix for the ERC20 short address attack | |
*/ | |
modifier onlyPayloadSize(uint size) { | |
if(msg.data.length < size + 4) { | |
throw; | |
} | |
_; | |
} | |
function transfer(address _to, uint _value) onlyPayloadSize(2 * 32) { | |
balances[msg.sender] = balances[msg.sender].sub(_value); | |
balances[_to] = balances[_to].add(_value); | |
Transfer(msg.sender, _to, _value); | |
} | |
function balanceOf(address _owner) constant returns (uint balance) { | |
return balances[_owner]; | |
} | |
} | |
/** | |
* Standard ERC20 token | |
* | |
* https://github.com/ethereum/EIPs/issues/20 | |
* Based on code by FirstBlood: | |
* https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol | |
*/ | |
contract StandardToken is BasicToken, ERC20 { | |
mapping (address => mapping (address => uint)) allowed; | |
function transferFrom(address _from, address _to, uint _value) { | |
var _allowance = allowed[_from][msg.sender]; | |
// Check is not needed because sub(_allowance, _value) will already throw if this condition is not met | |
// if (_value > _allowance) throw; | |
balances[_to] = balances[_to].add(_value); | |
balances[_from] = balances[_from].sub(_value); | |
allowed[_from][msg.sender] = _allowance.sub(_value); | |
Transfer(_from, _to, _value); | |
} | |
function approve(address _spender, uint _value) { | |
allowed[msg.sender][_spender] = _value; | |
Approval(msg.sender, _spender, _value); | |
} | |
function allowance(address _owner, address _spender) constant returns (uint remaining) { | |
return allowed[_owner][_spender]; | |
} | |
} | |
/* | |
* Ownable | |
* | |
* Base contract with an owner. | |
* Provides onlyOwner modifier, which prevents function from running if it is called by anyone other than the owner. | |
*/ | |
contract Ownable { | |
address public owner; | |
function Ownable() { | |
owner = msg.sender; | |
} | |
modifier onlyOwner() { | |
if (msg.sender != owner) { | |
throw; | |
} | |
_; | |
} | |
function transferOwnership(address newOwner) onlyOwner { | |
if (newOwner != address(0)) { | |
owner = newOwner; | |
} | |
} | |
} | |
contract RKCToken is StandardToken, Ownable { | |
using SafeMath for uint; | |
//-------------- Info for ERC20 explorers -----------------// | |
string public name = "Vamshi Kingdom Coin"; | |
string public symbol = "VKC"; | |
uint public decimals = 18; | |
//--------------------- Constants ------------------------// | |
bool public constant TEST_MODE = false; | |
uint public constant atto = 1000000000000000000; | |
uint public constant INITIAL_SUPPLY = 15000000 * atto; // 15 mln RKC. Impossible to mint more than this | |
address public teamWallet = 0xEA018EFd6108d782add96B02f23f682a8019f448; | |
// Made up ICO address (designating the token pool reserved for ICO, no one has access to it) | |
address public ico_address = 0x1c01C01C01C01c01C01c01c01c01C01c01c01c01; | |
uint public constant ICO_START_TIME = 1499810400; | |
//---------------------- Variables -------------------------// | |
uint public current_supply = 0; // Holding the number of all the coins in existence | |
uint public ico_starting_supply = 0; // How many atto tokens *were* available for sale at the beginning of the ICO | |
uint public current_price_atto_tokens_per_wei = 0; // Holding current price (determined by the algorithm in buy()) | |
//------------- Flags describing ICO stages --------------// | |
bool public preSoldSharesDistributed = false; // Prevents accidental re-distribution of shares | |
bool public isICOOpened = true; | |
bool public isICOClosed = false; | |
// 3 stages: | |
// Contract has just been deployed and initialized. isICOOpened == false, isICOClosed == false | |
// ICO has started, now anybody can buy(). isICOOpened == true, isICOClosed == false | |
// ICO has finished, now the team can receive the ether. isICOOpened == false, isICOClosed == true | |
//--------------------- Premiums -------------------------// | |
uint[] public premiumPacks; | |
mapping(address => uint) premiumPacksPaid; | |
//---------------------- Events ---------------------------// | |
event ICOOpened(); | |
event ICOClosed(); | |
event PriceChanged(uint old_price, uint new_price); | |
event SupplyChanged(uint supply, uint old_supply); | |
event RKCAcquired(address account, uint amount_in_wei, uint amount_in_rkc); | |
// *************************************************************************** | |
// Constructor | |
function RKCToken() { | |
// Some percentage of the tokens is already reserved by early employees and investors | |
// Here we're initializing their balances | |
distributePreSoldShares(); | |
// Starting price | |
current_price_atto_tokens_per_wei = calculateCurrentPrice(1); | |
// Some other initializations | |
premiumPacks.length = 0; | |
} | |
// Sending ether directly to the contract invokes buy() and assigns tokens to the sender | |
function () payable { | |
buy(); | |
} | |
// *************************************************************************** | |
// Buy token by sending ether here | |
// | |
// Price is being determined by the algorithm in recalculatePrice() | |
// You can also send the ether directly to the contract address | |
function buy() payable { | |
if (msg.value == 0) throw; // no tokens for you | |
// Only works in the ICO stage, after that the token is going to be traded on the exchanges | |
if (!isICOOpened) throw; | |
if (isICOClosed) throw; | |
// Deciding how many tokens can be bought with the ether received | |
uint tokens = getAttoTokensAmountPerWeiInternal(msg.value); | |
// Don't allow to buy more than 1% per transaction (secures from huge investors swalling the whole thing in 1 second) | |
uint allowedInOneTransaction = current_supply / 100; | |
if (tokens > allowedInOneTransaction) throw; | |
// Just in case | |
if (tokens > balances[ico_address]) throw; | |
// Transfer from the ICO pool | |
balances[ico_address] = balances[ico_address].sub(tokens); // if not enough, will throw | |
balances[msg.sender] = balances[msg.sender].add(tokens); | |
// Kick the price changing algo | |
uint old_price = current_price_atto_tokens_per_wei; | |
current_price_atto_tokens_per_wei = calculateCurrentPrice(getAttoTokensBoughtInICO()); | |
if (current_price_atto_tokens_per_wei == 0) current_price_atto_tokens_per_wei = 1; // in case it is too small that it gets rounded to zero | |
if (current_price_atto_tokens_per_wei > old_price) current_price_atto_tokens_per_wei = old_price; // in case some weird overflow happens | |
// Broadcasting price change event | |
if (old_price != current_price_atto_tokens_per_wei) PriceChanged(old_price, current_price_atto_tokens_per_wei); | |
// Broadcasting the buying event | |
RKCAcquired(msg.sender, msg.value, tokens); | |
} | |
// Formula for the dynamic price change algorithm | |
function calculateCurrentPrice(uint attoTokensBought) constant returns (uint result) { | |
// see http://www.wolframalpha.com/input/?i=f(x)+%3D+395500000+%2F+(x+%2B+150000)+-+136 | |
return (395500000 / ((attoTokensBought / atto) + 150000)).sub(136); // mixing safe and usual math here because the division will throw on inconsistency | |
} | |
// *************************************************************************** | |
// Functions for the contract owner | |
function openICO() onlyOwner { | |
if (isICOOpened) throw; | |
if (isICOClosed) throw; | |
isICOOpened = true; | |
ICOOpened(); | |
} | |
function closeICO() onlyOwner { | |
if (isICOClosed) throw; | |
if (!isICOOpened) throw; | |
isICOOpened = false; | |
isICOClosed = true; | |
// Redistribute ICO Tokens that were not bought as the first premiums | |
premiumPacks.length = 1; | |
premiumPacks[0] = balances[ico_address]; | |
balances[ico_address] = 0; | |
ICOClosed(); | |
} | |
function pullEtherFromContract() onlyOwner { | |
// Only when ICO is closed | |
if (!isICOClosed) throw; | |
if (!teamWallet.send(this.balance)) { | |
throw; | |
} | |
} | |
// *************************************************************************** | |
// Some percentage of the tokens is already reserved by early employees and investors | |
// Here we're initializing their balances | |
function distributePreSoldShares() onlyOwner { | |
// Making it impossible to call this function twice | |
if (preSoldSharesDistributed) throw; | |
preSoldSharesDistributed = true; | |
// Values are in atto tokens | |
balances[0x7A3c869603E28b0242c129440c9dD97F8A5bEe80] = 7508811 * atto; | |
balances[0x24a541dEAe0Fc87C990A208DE28a293fb2A982d9] = 4025712 * atto; | |
balances[0xEcF843458e76052E6363fFb78C7535Cd87AA3AB2] = 300275 * atto; | |
balances[0x947963ED2da750a0712AE0BF96E08C798813F277] = 150000 * atto; | |
balances[0x82Bc8452Ab76fBA446e16b57C080F5258F557734] = 150000 * atto; | |
balances[0x0959Ed48d55e580BB58df6E5ee01BAa787d80848] = 90000 * atto; | |
balances[0x530A8016fB5B3d7A0F92910b4814e383835Bd51E] = 75000 * atto; | |
balances[0xC3e934D3ADE0Ab9F61F824a9a824462c790e47B0] = 202 * atto; | |
current_supply = (7508811 + 4025712 + 300275 + 150000 + 150000 + 90000 + 75000 + 202) * atto; | |
// Sending the rest to ICO pool | |
balances[ico_address] = INITIAL_SUPPLY.sub(current_supply); | |
// Initializing the supply variables | |
ico_starting_supply = balances[ico_address]; | |
current_supply = INITIAL_SUPPLY; | |
SupplyChanged(0, current_supply); | |
} | |
// *************************************************************************** | |
// Some useful getters (although you can just query the public variables) | |
function getCurrentPriceAttoTokensPerWei() constant returns (uint result) { | |
return current_price_atto_tokens_per_wei; | |
} | |
function getAttoTokensAmountPerWeiInternal(uint value) payable returns (uint result) { | |
return value * current_price_atto_tokens_per_wei; | |
} | |
function getAttoTokensAmountPerWei(uint value) constant returns (uint result) { | |
return value * current_price_atto_tokens_per_wei; | |
} | |
function getSupply() constant returns (uint result) { | |
return current_supply; | |
} | |
function getAttoTokensLeftForICO() constant returns (uint result) { | |
return balances[ico_address]; | |
} | |
function getAttoTokensBoughtInICO() constant returns (uint result) { | |
return ico_starting_supply - getAttoTokensLeftForICO(); | |
} | |
function getBalance(address addr) constant returns (uint balance) { | |
return balances[addr]; | |
} | |
function getPremiumPack(uint index) constant returns (uint premium) { | |
return premiumPacks[index]; | |
} | |
function getPremiumCount() constant returns (uint length) { | |
return premiumPacks.length; | |
} | |
function getBalancePremiumsPaid(address account) constant returns (uint result) { | |
return premiumPacksPaid[account]; | |
} | |
// *************************************************************************** | |
// Premiums | |
function sendPremiumPack(uint amount) onlyOwner allowedPayments(msg.sender, amount) { | |
premiumPacks.length += 1; | |
premiumPacks[premiumPacks.length-1] = amount; | |
balances[msg.sender] = balances[msg.sender].sub(amount); // will throw and revert the whole thing if doesn't have this amount | |
} | |
function updatePremiums(address account) private { | |
if (premiumPacks.length > premiumPacksPaid[account]) { | |
uint startPackIndex = premiumPacksPaid[account]; | |
uint finishPackIndex = premiumPacks.length - 1; | |
for(uint i = startPackIndex; i <= finishPackIndex; i++) { | |
if (current_supply != 0) { // just in case | |
uint owing = balances[account] * premiumPacks[i] / current_supply; | |
balances[account] = balances[account].add(owing); | |
} | |
} | |
premiumPacksPaid[account] = premiumPacks.length; | |
} | |
} | |
// *************************************************************************** | |
// Overriding payment functions to take control over the logic | |
modifier allowedPayments(address payer, uint value) { | |
// Don't allow to transfer coins until the ICO ends | |
if (isICOOpened) throw; | |
if (!isICOClosed) throw; | |
// Limit the quick dump possibility | |
uint diff = 0; | |
uint allowed = 0; | |
if (balances[payer] > current_supply / 100) { // for balances > 1% of total supply | |
if (block.timestamp > ICO_START_TIME) { | |
diff = block.timestamp - ICO_START_TIME; | |
} else { | |
diff = ICO_START_TIME - block.timestamp; | |
} | |
allowed = (current_supply / 20) * (diff / (60 * 60 * 24 * 30)); // 5% unlocked every month | |
if (value > allowed) throw; | |
} | |
_; | |
} | |
function transferFrom(address _from, address _to, uint _value) allowedPayments(_from, _value) { | |
updatePremiums(_from); | |
updatePremiums(_to); | |
super.transferFrom(_from, _to, _value); | |
} | |
function transfer(address _to, uint _value) onlyPayloadSize(2 * 32) allowedPayments(msg.sender, _value) { | |
updatePremiums(msg.sender); | |
updatePremiums(_to); | |
super.transfer(_to, _value); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment