pragma solidity ^0.4.11;
/*
* LOK 'LookRev Token' crowdfunding contract Version 2.0
*
* Refer to https://lookrev.com/ for further information.
*
* Developer: LookRev (TM) 2017.
*
* Audited by BokkyPooBah / Bok Consulting Pty Ltd 2017.
*
* The MIT License.
*
*/
/*
* ERC20 Token Standard
* https://github.com/ethereum/EIPs/issues/20
*
*/
contract ERC20 {
uint public totalSupply;
function balanceOf(address _who) constant returns (uint balance);
function allowance(address _owner, address _spender) constant returns (uint remaining);
function transfer(address _to, uint _value) returns (bool ok);
function transferFrom(address _from, address _to, uint _value) returns (bool ok);
function approve(address _spender, uint _value) returns (bool ok);
event Transfer(address indexed _from, address indexed _to, uint _value);
event Approval(address indexed _owner, address indexed _spender, uint _value);
}
/**
* Math operations with safety checks
*/
contract SafeMath {
function safeAdd(uint a, uint b) internal returns (uint) {
uint c = a + b;
assert(c >= a && c >= b);
return c;
}
function safeSub(uint a, uint b) internal returns (uint) {
assert(b <= a);
uint c = a - b;
assert(c <= a);
return c;
}
}
contract Ownable {
address owner;
address newOwner;
function Ownable() {
owner = msg.sender;
}
modifier onlyOwner {
require(msg.sender == owner);
_;
}
function transferOwnership(address _newOwner) onlyOwner {
if (_newOwner != address(0)) {
newOwner = _newOwner;
}
}
function acceptOwnership() {
require(msg.sender == newOwner);
OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
event OwnershipTransferred(address indexed _from, address indexed _to);
}
/**
* Standard ERC20 token with Short Hand Attack and approve() race condition mitigation.
*
* Based on code by InvestSeed
*/
contract StandardToken is ERC20, Ownable, SafeMath {
mapping (address => uint) balances;
mapping (address => mapping (address => uint)) allowed;
function balanceOf(address _owner) constant returns (uint balance) {
return balances[_owner];
}
function transfer(address _to, uint _amount) returns (bool success) {
// avoid wasting gas on 0 token transfers
if(_amount == 0) return true;
if (msg.sender == _to) return false;
if (balances[msg.sender] >= _amount
&& _amount > 0
&& balances[_to] + _amount > balances[_to]) {
balances[msg.sender] = safeSub(balances[msg.sender],_amount);
balances[_to] = safeAdd(balances[_to],_amount);
Transfer(msg.sender, _to, _amount);
return true;
} else {
return false;
}
}
function transferFrom(address _from, address _to, uint _amount) returns (bool success) {
// avoid wasting gas on 0 token transfers
if(_amount == 0) return true;
if(_from == _to) return false;
if (balances[_from] >= _amount
&& allowed[_from][msg.sender] >= _amount
&& _amount > 0
&& balances[_to] + _amount > balances[_to]) {
balances[_from] = safeSub(balances[_from],_amount);
allowed[_from][msg.sender] = safeSub(allowed[_from][msg.sender],_amount);
balances[_to] = safeAdd(balances[_to],_amount);
Transfer(_from, _to, _amount);
return true;
} else {
return false;
}
}
function approve(address _spender, uint _value) returns (bool success) {
// To change the approve amount you first have to reduce the addresses`
// allowance to zero by calling `approve(_spender, 0)` if it is not
// already 0 to mitigate the race condition described here:
// https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
if ((_value != 0) && (allowed[msg.sender][_spender] != 0)) {
return false;
}
if (balances[msg.sender] < _value) {
return false;
}
allowed[msg.sender][_spender] = _value;
Approval(msg.sender, _spender, _value);
return true;
}
function allowance(address _owner, address _spender) constant returns (uint remaining) {
return allowed[_owner][_spender];
}
}
/**
* LookRev token initial offering.
*
* Token supply is created in the token contract creation and allocated to owner.
*
*/
contract LookRevToken is StandardToken {
/*
* Token meta data
*/
string public constant name = "LookRev";
string public constant symbol = "LOOK";
uint8 public constant decimals = 18;
string public VERSION = 'LOK2.0';
bool public finalised = false;
address wallet = 0x0;
mapping(address => bool) public kycRequired;
// Start - Sunday, October 8, 2017 3:00:01 PM (8:00:01 AM GMT-07:00 DST)
uint public constant START_DATE = 1507474801;
uint public constant DECIMALSFACTOR = 10**uint(decimals);
uint public constant TOKENS_SOFT_CAP = 10000000 * DECIMALSFACTOR;
uint public constant TOKENS_HARD_CAP = 4500000000 * DECIMALSFACTOR;
uint public constant TOKENS_TOTAL = 5000000000 * DECIMALSFACTOR;
uint public constant INITIAL_SUPPLY = 10000000 * DECIMALSFACTOR;
// 1 KETHER = 2,400,000 tokens
// 1 ETH = 2,400 tokens
uint public tokensPerKEther = 2400000;
uint public CONTRIBUTIONS_MIN = 0 ether;
uint public CONTRIBUTIONS_MAX = 0 ether;
uint public constant KYC_THRESHOLD = 100 * DECIMALSFACTOR;
function LookRevToken() {
owner = msg.sender;
wallet = owner;
totalSupply = INITIAL_SUPPLY;
balances[owner] = totalSupply;
}
// LookRev can change the crowdsale wallet address
function setWallet(address _wallet) onlyOwner {
wallet = _wallet;
WalletUpdated(wallet);
}
event WalletUpdated(address newWallet);
// Accept ethers to buy tokens during the crowdsale
function () payable {
proxyPayment(msg.sender);
}
// Accept ethers and exchanges to purchase tokens on behalf of user
// msg.value (in units of wei)
function proxyPayment(address participant) payable {
require(!finalised);
require(msg.value > CONTRIBUTIONS_MIN);
require(CONTRIBUTIONS_MAX == 0 || msg.value < CONTRIBUTIONS_MAX);
// Calculate number of tokens for contributed ETH
// `18` is the ETH decimals
// `- decimals` is the token decimals
uint tokens = msg.value * tokensPerKEther / 10**uint(18 - decimals + 3);
// Check if the hard cap will be exceeded
require(totalSupply + tokens <= TOKENS_HARD_CAP);
// Add tokens purchased to account's balance and total supply
balances[participant] = safeAdd(balances[participant],tokens);
totalSupply = safeAdd(totalSupply,tokens);
// Log the tokens purchased
Transfer(0x0, participant, tokens);
// - buyer = participant
// - ethers = msg.value
// - participantTokenBalance = balances[participant]
// - tokens = tokens
// - newTotalSupply = totalSupply
// - tokensPerKEther = tokensPerKEther
TokensBought(participant, msg.value, balances[participant], tokens,
totalSupply, tokensPerKEther);
if (msg.value > KYC_THRESHOLD) {
// KYC verification required before participant can transfer the tokens
kycRequired[participant] = true;
}
// Transfer the contributed ethers to the crowdsale wallet
// throw is deprecated starting from Ethereum v0.9.0
wallet.transfer(msg.value);
}
event TokensBought(address indexed buyer, uint ethers,
uint participantTokenBalance, uint tokens, uint newTotalSupply,
uint tokensPerKEther);
function finalise() onlyOwner {
// Can only finalise if raised > soft cap
require(totalSupply >= TOKENS_SOFT_CAP);
require(!finalised);
finalised = true;
}
// Tokens purchased using other types of cryptocurrency
function addPrecommitment(address participant, uint balance) onlyOwner {
require(balance > 0);
balances[participant] = safeAdd(balances[participant],balance);
totalSupply = safeAdd(totalSupply,balance);
Transfer(0x0, participant, balance);
PrecommitmentAdded(participant, balance);
}
event PrecommitmentAdded(address indexed participant, uint balance);
function transfer(address _to, uint _amount) returns (bool success) {
// Allow token transfer
require(!kycRequired[msg.sender] || msg.sender == owner);
return super.transfer(_to, _amount);
}
function transferFrom(address _from, address _to, uint _amount) returns (bool success)
{
require(!kycRequired[_from] || msg.sender == owner);
return super.transferFrom(_from, _to, _amount);
}
function kycVerify(address participant, bool _required) onlyOwner {
kycRequired[participant] = _required;
KycVerified(participant, kycRequired[participant]);
}
event KycVerified(address indexed participant, bool required);
// Any account can burn _from's tokens as long as the _from account has
// approved the _amount to be burnt using approve(0x0, _amount)
function burnFrom(address _from, uint _amount) returns (bool success) {
require(totalSupply >= _amount);
if (balances[_from] >= _amount
&& allowed[_from][0x0] >= _amount
&& _amount > 0
&& balances[0x0] + _amount > balances[0x0]
) {
balances[_from] = safeSub(balances[_from],_amount);
balances[0x0] = safeAdd(balances[0x0],_amount);
allowed[_from][0x0] = safeSub(allowed[_from][0x0],_amount);
totalSupply = safeSub(totalSupply,_amount);
Transfer(_from, 0x0, _amount);
return true;
} else {
return false;
}
}
// LookRev can transfer out any accidentally sent ERC20 tokens
function transferAnyERC20Token(address tokenAddress, uint amount) onlyOwner returns (bool success)
{
return ERC20(tokenAddress).transfer(owner, amount);
}
}
{
"compilationTarget": {
"LookRevToken.sol": "LookRevToken"
},
"libraries": {},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"TOKENS_TOTAL","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"participant","type":"address"},{"name":"_required","type":"bool"}],"name":"kycVerify","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"finalised","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"KYC_THRESHOLD","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"CONTRIBUTIONS_MIN","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"INITIAL_SUPPLY","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"START_DATE","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"participant","type":"address"},{"name":"balance","type":"uint256"}],"name":"addPrecommitment","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"TOKENS_SOFT_CAP","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"acceptOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_amount","type":"uint256"}],"name":"burnFrom","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"TOKENS_HARD_CAP","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"DECIMALSFACTOR","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"CONTRIBUTIONS_MAX","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"finalise","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"tokensPerKEther","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"kycRequired","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"tokenAddress","type":"address"},{"name":"amount","type":"uint256"}],"name":"transferAnyERC20Token","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_wallet","type":"address"}],"name":"setWallet","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":"participant","type":"address"}],"name":"proxyPayment","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"VERSION","outputs":[{"name":"","type":"string"}],"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":"newWallet","type":"address"}],"name":"WalletUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"buyer","type":"address"},{"indexed":false,"name":"ethers","type":"uint256"},{"indexed":false,"name":"participantTokenBalance","type":"uint256"},{"indexed":false,"name":"tokens","type":"uint256"},{"indexed":false,"name":"newTotalSupply","type":"uint256"},{"indexed":false,"name":"tokensPerKEther","type":"uint256"}],"name":"TokensBought","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"participant","type":"address"},{"indexed":false,"name":"balance","type":"uint256"}],"name":"PrecommitmentAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"participant","type":"address"},{"indexed":false,"name":"required","type":"bool"}],"name":"KycVerified","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Approval","type":"event"}]