pragma solidity ^0.4.15;
/**
* assert(2 + 2 is 4 - 1 thats 3) Quick Mafs
*/
library QuickMafs {
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;
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;
}
}
/**
* The ownable contract contains an owner address. This give us simple ownership privledges and can allow ownship transfer.
*/
contract Ownable {
/**
* The owner/admin of the contract
*/
address public owner;
/**
* Constructor for contract. Sets The contract creator to the default owner.
*/
function Ownable() public {
owner = msg.sender;
}
/**
* Modifier to apply to methods to restrict access to the owner
*/
modifier onlyOwner(){
require(msg.sender == owner);
_; //Placeholder for method content
}
/**
* Transfer the ownership to a new owner can only be done by the current owner.
*/
function transferOwnership(address _newOwner) public onlyOwner {
//Only make the change if required
if (_newOwner != address(0)) {
owner = _newOwner;
}
}
}
/**
* ERC Token Standard #20 Interface
*/
contract ERC20 {
/**
* Get the total token supply
*/
function totalSupply() public constant returns (uint256 _totalSupply);
/**
* Get the account balance of another account with address _owner
*/
function balanceOf(address _owner) public constant returns (uint256 balance);
/**
* Send _amount of tokens to address _to
*/
function transfer(address _to, uint256 _amount) public returns (bool success);
/**
* Send _amount of tokens from address _from to address _to
*/
function transferFrom(address _from, address _to, uint256 _amount) public returns (bool success);
/**
* Allow _spender to withdraw from your account, multiple times, up to the _amount.
* If this function is called again it overwrites the current allowance with _amount.
* this function is required for some DEX functionality
*/
function approve(address _spender, uint256 _amount) public returns (bool success);
/**
* Returns the amount which _spender is still allowed to withdraw from _owner
*/
function allowance(address _owner, address _spender) public constant returns (uint256 remaining);
/**
* Triggered when tokens are transferred.
*/
event Transfer(address indexed _from, address indexed _to, uint256 _amount);
/**
* Triggered whenever approve(address _spender, uint256 _amount) is called.
*/
event Approval(address indexed _owner, address indexed _spender, uint256 _amount);
}
/**
* The CTN Token
*/
contract Token is ERC20, Ownable {
using QuickMafs for uint256;
string public constant SYMBOL = "CTN";
string public constant NAME = "Crypto Trust Network";
uint8 public constant DECIMALS = 18;
/**
* Total supply of tokens
*/
uint256 totalTokens;
/**
* The initial supply of coins before minting
*/
uint256 initialSupply;
/**
* Balances for each account
*/
mapping(address => uint256) balances;
/**
* Whos allowed to withdrawl funds from which accounts
*/
mapping(address => mapping (address => uint256)) allowed;
/**
* If the token is tradable
*/
bool tradable;
/**
* The address to store the initialSupply
*/
address public vault;
/**
* If the coin can be minted
*/
bool public mintingFinished = false;
/**
* Event for when new coins are created
*/
event Mint(address indexed _to, uint256 _value);
/**
* Event that is fired when token sale is over
*/
event MintFinished();
/**
* Tokens can now be traded
*/
event TradableTokens();
/**
* Allows this coin to be traded between users
*/
modifier isTradable(){
require(tradable);
_;
}
/**
* If this coin can be minted modifier
*/
modifier canMint() {
require(!mintingFinished);
_;
}
/**
* Initializing the token, setting the owner, initial supply & vault
*/
function Token() public {
initialSupply = 4500000 * 1 ether;
totalTokens = initialSupply;
tradable = false;
vault = 0x6e794AAA2db51fC246b1979FB9A9849f53919D1E;
balances[vault] = balances[vault].add(initialSupply); //Set initial supply to the vault
}
/**
* Obtain current total supply of CTN tokens
*/
function totalSupply() public constant returns (uint256 totalAmount) {
totalAmount = totalTokens;
}
/**
* Get the initial supply of CTN coins
*/
function baseSupply() public constant returns (uint256 initialAmount) {
initialAmount = initialSupply;
}
/**
* Returns the balance of a wallet
*/
function balanceOf(address _address) public constant returns (uint256 balance) {
return balances[_address];
}
/**
* Transfer CTN between wallets
*/
function transfer(address _to, uint256 _amount) public isTradable returns (bool) {
balances[msg.sender] = balances[msg.sender].sub(_amount);
balances[_to] = balances[_to].add(_amount);
Transfer(msg.sender, _to, _amount);
return true;
}
/**
* Send _amount of tokens from address _from to address _to
* The transferFrom method is used for a withdraw workflow, allowing contracts to send
* tokens on your behalf, for example to "deposit" to a contract address and/or to charge
* fees in sub-currencies; the command should fail unless the _from account has
* deliberately authorized the sender of the message via some mechanism; we propose
* these standardized APIs for approval:
*/
function transferFrom(
address _from,
address _to,
uint256 _amount
) public isTradable returns (bool success)
{
var _allowance = allowed[_from][msg.sender];
/**
* QuickMaf will roll back any changes so no need to check before these operations
*/
balances[_to] = balances[_to].add(_amount);
balances[_from] = balances[_from].sub(_amount);
allowed[_from][msg.sender] = _allowance.sub(_amount);
Transfer(_from, _to, _amount);
return true;
}
/**
* Allows an address to transfer money out this is administered by the contract owner who can specify how many coins an account can take.
* Needs to be called to feault the amount to 0 first -> https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*/
function approve(address _spender, uint256 _amount) public returns (bool) {
/**
*Set the amount they are able to spend to 0 first so that transaction ordering cannot allow multiple withdrawls asyncly
*This function always requires to calls if a user has an amount they can withdrawl.
*/
require((_amount == 0) || (allowed[msg.sender][_spender] == 0));
allowed[msg.sender][_spender] = _amount;
Approval(msg.sender, _spender, _amount);
return true;
}
/**
* Check the amount of tokens the owner has allowed to a spender
*/
function allowance(address _owner, address _spender) public constant returns (uint256 remaining) {
return allowed[_owner][_spender];
}
/**
* Makes the coin tradable between users cannot be undone
*/
function makeTradable() public onlyOwner {
tradable = true;
TradableTokens();
}
/**
* Mint tokens to users
*/
function mint(address _to, uint256 _amount) public onlyOwner canMint returns (bool) {
totalTokens = totalTokens.add(_amount);
balances[_to] = balances[_to].add(_amount);
Mint(_to, _amount);
return true;
}
/**
* Function to stop minting tokens irreversable
*/
function finishMinting() public onlyOwner returns (bool) {
mintingFinished = true;
MintFinished();
return true;
}
}
/**
* The initial crowdsale of the token
*/
contract Sale is Ownable {
using QuickMafs for uint256;
/**
* The hard cap of the token sale
*/
uint256 hardCap;
/**
* The soft cap of the token sale
*/
uint256 softCap;
/**
* The bonus cap for the token sale
*/
uint256 bonusCap;
/**
* How many tokens you get per ETH
*/
uint256 tokensPerETH;
/**
* //the start time of the sale (new Date("Jan 22 2018 18:00:00 GMT").getTime() / 1000)
*/
uint256 public start = 1516644000;
/**
* The end time of the sale (new Date("Feb 22 2018 18:00:00 GMT").getTime() / 1000)
*/
uint256 public end = 1519322400;
/**
* Two months after the sale ends used to retrieve unclaimed refunds (new Date("Apr 22 2018 18:00:00 GMT").getTime() / 1000)
*/
uint256 public twoMonthsLater = 1524420000;
/**
* Token for minting purposes
*/
Token public token;
/**
* The address to store eth in during sale
*/
address public vault;
/**
* How much ETH each user has sent to this contract. For softcap unmet refunds
*/
mapping(address => uint256) investments;
/**
* Every purchase during the sale
*/
event TokenSold(address recipient, uint256 etherAmount, uint256 ctnAmount, bool preSale, bool bonus);
/**
* Triggered when tokens are transferred.
*/
event PriceUpdated(uint256 amount);
/**
* Only make certain changes before the sale starts
*/
modifier isPreSale(){
require(now < start);
_;
}
/**
* Is the sale still on
*/
modifier isSaleOn() {
require(now >= start && now <= end);
_;
}
/**
* Has the sale completed
*/
modifier isSaleFinished() {
bool hitHardCap = token.totalSupply().sub(token.baseSupply()) >= hardCap;
require(now > end || hitHardCap);
_;
}
/**
* Has the sale completed
*/
modifier isTwoMonthsLater() {
require(now > twoMonthsLater);
_;
}
/**
* Make sure we are under the hardcap
*/
modifier isUnderHardCap() {
bool underHard = token.totalSupply().sub(token.baseSupply()) <= hardCap;
require(underHard);
_;
}
/**
* Make sure we are over the soft cap
*/
modifier isOverSoftCap() {
bool overSoft = token.totalSupply().sub(token.baseSupply()) >= softCap;
require(overSoft);
_;
}
/**
* Make sure we are over the soft cap
*/
modifier isUnderSoftCap() {
bool underSoft = token.totalSupply().sub(token.baseSupply()) < softCap;
require(underSoft);
_;
}
/**
* The token sale constructor
*/
function Sale() public {
hardCap = 10500000 * 1 ether;
softCap = 500000 * 1 ether;
bonusCap = 2000000 * 1 ether;
tokensPerETH = 630; //Tokens per 1 ETH
token = new Token();
vault = 0x6e794AAA2db51fC246b1979FB9A9849f53919D1E;
}
/**
* Fallback function which receives ether and created the appropriate number of tokens for the
* msg.sender.
*/
function() external payable {
//If we can not purchase tokens presale then try purchase them normally
if ( now < start ) {
purchaseTokensPreSale(msg.sender);
} else {
purchaseTokens(msg.sender);
}
}
/**
* If the soft cap has not been reached and the sale is over investors can reclaim their funds
*/
function refund() public isSaleFinished isUnderSoftCap {
uint256 amount = investments[msg.sender];
investments[msg.sender] = investments[msg.sender].sub(amount);
msg.sender.transfer(amount);
}
/**
* Withdrawl the funds from the contract.
* Make the token tradeable and finish minting
*/
function withdrawl() public isSaleFinished isOverSoftCap {
vault.transfer(this.balance);
//Stop minting of the token and make the token tradeable
token.finishMinting();
token.makeTradable();
}
/**
* Update the ETH price for the token sale
*/
function updatePrice(uint256 _newPrice) public onlyOwner isPreSale {
tokensPerETH = _newPrice;
PriceUpdated(_newPrice);
}
/**
* Temp function for change start times for debuging
*/
function updateStart(uint256 _newStart) public onlyOwner {
start = _newStart;
}
/**
* The pre sale purchase of tokens. Is avaliable up until the soft cap is hit.
*/
function purchaseTokensPreSale(address recipient) public isUnderSoftCap isPreSale payable {
uint256 amount = msg.value;
uint256 tokens = tokensPerETH.mul(amount);
//Tokens purchased pre sale get an additional 25% CTN
tokens = tokens.add(tokens.div(4));
//Add the amount to a users investment total
investments[msg.sender] = investments[msg.sender].add(msg.value);
token.mint(recipient, tokens);
TokenSold(recipient, amount, tokens, true, true);
}
/**
* Allows user to buy coins if we are under the hardcap also adds a bonus if under the bonus amount
*/
function purchaseTokens(address recipient) public isUnderHardCap isSaleOn payable {
uint256 amount = msg.value;
uint256 tokens = tokensPerETH.mul(amount);
bool bonus = false;
if (token.totalSupply().sub(token.baseSupply()) < bonusCap) {
bonus = true;
//Tokens purchased before the bonus cap get an additional 20% CTN
tokens = tokens.add(tokens.div(5));
}
//Add the amount to user investment total
investments[msg.sender] = investments[msg.sender].add(msg.value);
token.mint(recipient, tokens);
TokenSold(recipient, amount, tokens, false, bonus);
}
/**
* Withdrawl the funds from the contract.
* Make the token tradeable and finish minting
*/
function cleanup() public isTwoMonthsLater {
vault.transfer(this.balance);
token.finishMinting();
token.makeTradable();
}
function destroy() public onlyOwner isTwoMonthsLater {
token.finishMinting();
token.makeTradable();
token.transferOwnership(owner);
selfdestruct(vault);
}
/**
* Get the ETH balance of this contract
*/
function getBalance() public constant returns (uint256 totalAmount) {
totalAmount = this.balance;
}
}
{
"compilationTarget": {
"Sale.sol": "Sale"
},
"libraries": {},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"constant":true,"inputs":[],"name":"getBalance","outputs":[{"name":"totalAmount","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"withdrawl","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"cleanup","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"twoMonthsLater","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"recipient","type":"address"}],"name":"purchaseTokensPreSale","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[],"name":"refund","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"destroy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_newPrice","type":"uint256"}],"name":"updatePrice","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"start","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"recipient","type":"address"}],"name":"purchaseTokens","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"end","outputs":[{"name":"","type":"uint256"}],"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":"_newStart","type":"uint256"}],"name":"updateStart","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"vault","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"token","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":false,"name":"recipient","type":"address"},{"indexed":false,"name":"etherAmount","type":"uint256"},{"indexed":false,"name":"ctnAmount","type":"uint256"},{"indexed":false,"name":"preSale","type":"bool"},{"indexed":false,"name":"bonus","type":"bool"}],"name":"TokenSold","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"PriceUpdated","type":"event"}]