273 lines
7.4 KiB
Solidity
273 lines
7.4 KiB
Solidity
/**
|
|
* This smart contract code is Copyright 2017 TokenMarket Ltd. For more information see https://tokenmarket.net
|
|
*
|
|
* Licensed under the Apache License, version 2.0: https://github.com/TokenMarketNet/ico/blob/master/LICENSE.txt
|
|
*/
|
|
|
|
pragma solidity ^0.4.15;
|
|
|
|
/**
|
|
* Math operations with safety checks
|
|
*/
|
|
contract SafeMath {
|
|
function safeMul(uint a, uint b) internal returns (uint) {
|
|
uint c = a * b;
|
|
assert(a == 0 || c / a == b);
|
|
return c;
|
|
}
|
|
|
|
function safeDiv(uint a, uint b) internal returns (uint) {
|
|
assert(b > 0);
|
|
uint c = a / b;
|
|
assert(a == b * c + a % b);
|
|
return c;
|
|
}
|
|
|
|
function safeSub(uint a, uint b) internal returns (uint) {
|
|
assert(b <= a);
|
|
return a - b;
|
|
}
|
|
|
|
function safeAdd(uint a, uint b) internal returns (uint) {
|
|
uint c = a + b;
|
|
assert(c>=a && c>=b);
|
|
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;
|
|
}
|
|
|
|
}
|
|
|
|
library SafeMathLib {
|
|
|
|
function times(uint a, uint b) returns (uint) {
|
|
uint c = a * b;
|
|
assert(a == 0 || c / a == b);
|
|
return c;
|
|
}
|
|
|
|
function minus(uint a, uint b) returns (uint) {
|
|
assert(b <= a);
|
|
return a - b;
|
|
}
|
|
|
|
function plus(uint a, uint b) returns (uint) {
|
|
uint c = a + b;
|
|
assert(c>=a);
|
|
return c;
|
|
}
|
|
|
|
}
|
|
|
|
contract ERC20Basic {
|
|
uint256 public totalSupply;
|
|
function balanceOf(address who) public constant 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 constant 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 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;
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Standard ERC20 token with Short Hand Attack and approve() race condition mitigation.
|
|
*
|
|
* Based on code by FirstBlood:
|
|
* https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
|
|
*/
|
|
contract StandardToken is ERC20, SafeMath {
|
|
|
|
/* Token supply got increased and a new owner received these tokens */
|
|
event Minted(address receiver, uint amount);
|
|
|
|
/* Actual balances of token holders */
|
|
mapping(address => uint) balances;
|
|
|
|
/* approve() allowances */
|
|
mapping (address => mapping (address => uint)) allowed;
|
|
|
|
/* Interface declaration */
|
|
function isToken() public constant returns (bool weAre) {
|
|
return true;
|
|
}
|
|
|
|
function transfer(address _to, uint _value) returns (bool success) {
|
|
balances[msg.sender] = safeSub(balances[msg.sender], _value);
|
|
balances[_to] = safeAdd(balances[_to], _value);
|
|
Transfer(msg.sender, _to, _value);
|
|
return true;
|
|
}
|
|
|
|
function transferFrom(address _from, address _to, uint _value) returns (bool success) {
|
|
uint _allowance = allowed[_from][msg.sender];
|
|
|
|
balances[_to] = safeAdd(balances[_to], _value);
|
|
balances[_from] = safeSub(balances[_from], _value);
|
|
allowed[_from][msg.sender] = safeSub(_allowance, _value);
|
|
Transfer(_from, _to, _value);
|
|
return true;
|
|
}
|
|
|
|
function balanceOf(address _owner) constant returns (uint balance) {
|
|
return balances[_owner];
|
|
}
|
|
|
|
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)) throw;
|
|
|
|
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];
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* A token that can increase its supply by another contract.
|
|
*
|
|
* This allows uncapped crowdsale by dynamically increasing the supply when money pours in.
|
|
* Only mint agents, contracts whitelisted by owner, can mint new tokens.
|
|
*
|
|
*/
|
|
contract MintableToken is StandardToken, Ownable {
|
|
|
|
bool public mintingFinished = false;
|
|
|
|
/** List of agents that are allowed to create new tokens */
|
|
mapping (address => bool) public mintAgents;
|
|
|
|
event MintingAgentChanged(address addr, bool state );
|
|
|
|
/**
|
|
* Create new tokens and allocate them to an address..
|
|
*
|
|
* Only callably by a crowdsale contract (mint agent).
|
|
*/
|
|
function mint(address receiver, uint amount) onlyMintAgent canMint public {
|
|
|
|
uint arranged_amount = amount * 1 ether;
|
|
|
|
totalSupply = safeAdd(totalSupply, arranged_amount);
|
|
balances[receiver] = safeAdd(balances[receiver], arranged_amount);
|
|
|
|
// This will make the mint transaction apper in EtherScan.io
|
|
// We can remove this after there is a standardized minting event
|
|
Transfer(0, receiver, arranged_amount);
|
|
}
|
|
|
|
/**
|
|
* Owner can allow a crowdsale contract to mint new tokens.
|
|
*/
|
|
function setMintAgent(address addr, bool state) onlyOwner canMint public {
|
|
mintAgents[addr] = state;
|
|
MintingAgentChanged(addr, state);
|
|
}
|
|
|
|
modifier onlyMintAgent() {
|
|
// Only crowdsale contracts are allowed to mint new tokens
|
|
if(!mintAgents[msg.sender]) {
|
|
throw;
|
|
}
|
|
_;
|
|
}
|
|
|
|
/** Make sure we are not done yet. */
|
|
modifier canMint() {
|
|
if(mintingFinished) throw;
|
|
_;
|
|
}
|
|
}
|
|
|
|
contract ApproveAndCallFallBack {
|
|
function receiveApproval(address from, uint256 tokens, address token, bytes data) public;
|
|
}
|
|
|
|
contract BridgeableToken is MintableToken {
|
|
function approveAndCall(address spender, uint tokens, bytes data) public returns (bool) {
|
|
allowed[msg.sender][spender] = tokens;
|
|
Approval(msg.sender, spender, tokens);
|
|
ApproveAndCallFallBack(spender).receiveApproval(msg.sender, tokens, this, data);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// For test purposes
|
|
contract Token is BridgeableToken {
|
|
|
|
function Token() {
|
|
}
|
|
}
|