pragma solidity ^0.4.15;
/**
* 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
*
* This is the token contract for Dealbox. It utilizes Majoolr's TokenLib library
* to reduce custom source code surface area and increase overall security.
* Majoolr provides smart contract services and security reviews for contract
* deployments in addition to working on open source projects in the Ethereum
* Community.
* For further information: dlbx.io, majoolr.io
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
contract DLBXToken {
using TokenLib for TokenLib.TokenStorage;
TokenLib.TokenStorage token;
function DLBXToken(address owner,
string name, //DealBox Token
string symbol, //DLBX
uint8 decimals, //0
uint256 initialSupply, //500000000
bool allowMinting) //false
{
token.init(owner, name, symbol, decimals, initialSupply, allowMinting);
}
/*EVENTS*/
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
event OwnerChange(address from, address to);
event Burn(address indexed burner, uint256 value);
event MintingClosed(bool mintingClosed);
/*FUNCTIONS*/
function owner() constant returns (address) {
return token.owner;
}
function name() constant returns (string) {
return token.name;
}
function symbol() constant returns (string) {
return token.symbol;
}
function decimals() constant returns (uint8) {
return token.decimals;
}
function initialSupply() constant returns (uint256) {
return token.INITIAL_SUPPLY;
}
function totalSupply() constant returns (uint256) {
return token.totalSupply;
}
function balanceOf(address who) constant returns (uint256) {
return token.balanceOf(who);
}
function allowance(address owner, address spender) constant returns (uint256) {
return token.allowance(owner, spender);
}
function transfer(address to, uint value) returns (bool ok) {
return token.transfer(to, value);
}
function transferFrom(address from, address to, uint value) returns (bool ok) {
return token.transferFrom(from, to, value);
}
function approve(address spender, uint value) returns (bool ok) {
return token.approve(spender, value);
}
function changeOwner(address newOwner) returns (bool ok) {
return token.changeOwner(newOwner);
}
function burnToken(uint256 amount) returns (bool ok) {
return token.burnToken(amount);
}
}
library TokenLib {
using BasicMathLib for uint256;
struct TokenStorage {
mapping (address => uint256) balances;
mapping (address => mapping (address => uint256)) allowed;
string name;
string symbol;
uint256 totalSupply;
uint256 INITIAL_SUPPLY;
address owner;
uint8 decimals;
bool stillMinting;
}
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
event OwnerChange(address from, address to);
event Burn(address indexed burner, uint256 value);
event MintingClosed(bool mintingClosed);
/// @dev Called by the Standard Token upon creation.
/// @param self Stored token from token contract
/// @param _name Name of the new token
/// @param _symbol Symbol of the new token
/// @param _decimals Decimal places for the token represented
/// @param _initial_supply The initial token supply
/// @param _allowMinting True if additional tokens can be created, false otherwise
function init(TokenStorage storage self,
address _owner,
string _name,
string _symbol,
uint8 _decimals,
uint256 _initial_supply,
bool _allowMinting)
{
require(self.INITIAL_SUPPLY == 0);
self.name = _name;
self.symbol = _symbol;
self.totalSupply = _initial_supply;
self.INITIAL_SUPPLY = _initial_supply;
self.decimals = _decimals;
self.owner = _owner;
self.stillMinting = _allowMinting;
self.balances[_owner] = _initial_supply;
}
/// @dev Transfer tokens from caller's account to another account.
/// @param self Stored token from token contract
/// @param _to Address to send tokens
/// @param _value Number of tokens to send
/// @return True if completed
function transfer(TokenStorage storage self, address _to, uint256 _value) returns (bool) {
bool err;
uint256 balance;
(err,balance) = self.balances[msg.sender].minus(_value);
require(!err);
self.balances[msg.sender] = balance;
//It's not possible to overflow token supply
self.balances[_to] = self.balances[_to] + _value;
Transfer(msg.sender, _to, _value);
return true;
}
/// @dev Authorized caller transfers tokens from one account to another
/// @param self Stored token from token contract
/// @param _from Address to send tokens from
/// @param _to Address to send tokens to
/// @param _value Number of tokens to send
/// @return True if completed
function transferFrom(TokenStorage storage self,
address _from,
address _to,
uint256 _value)
returns (bool)
{
var _allowance = self.allowed[_from][msg.sender];
bool err;
uint256 balanceOwner;
uint256 balanceSpender;
(err,balanceOwner) = self.balances[_from].minus(_value);
require(!err);
(err,balanceSpender) = _allowance.minus(_value);
require(!err);
self.balances[_from] = balanceOwner;
self.allowed[_from][msg.sender] = balanceSpender;
self.balances[_to] = self.balances[_to] + _value;
Transfer(_from, _to, _value);
return true;
}
/// @dev Retrieve token balance for an account
/// @param self Stored token from token contract
/// @param _owner Address to retrieve balance of
/// @return balance The number of tokens in the subject account
function balanceOf(TokenStorage storage self, address _owner) constant returns (uint256 balance) {
return self.balances[_owner];
}
/// @dev Authorize an account to send tokens on caller's behalf
/// @param self Stored token from token contract
/// @param _spender Address to authorize
/// @param _value Number of tokens authorized account may send
/// @return True if completed
function approve(TokenStorage storage self, address _spender, uint256 _value) returns (bool) {
self.allowed[msg.sender][_spender] = _value;
Approval(msg.sender, _spender, _value);
return true;
}
/// @dev Remaining tokens third party spender has to send
/// @param self Stored token from token contract
/// @param _owner Address of token holder
/// @param _spender Address of authorized spender
/// @return remaining Number of tokens spender has left in owner's account
function allowance(TokenStorage storage self, address _owner, address _spender) constant returns (uint256 remaining) {
return self.allowed[_owner][_spender];
}
/// @dev Authorize third party transfer by increasing/decreasing allowed rather than setting it
/// @param self Stored token from token contract
/// @param _spender Address to authorize
/// @param _valueChange Increase or decrease in number of tokens authorized account may send
/// @param _increase True if increasing allowance, false if decreasing allowance
/// @return True if completed
function approveChange (TokenStorage storage self, address _spender, uint256 _valueChange, bool _increase)
returns (bool)
{
uint256 _newAllowed;
bool err;
if(_increase) {
(err, _newAllowed) = self.allowed[msg.sender][_spender].plus(_valueChange);
require(!err);
self.allowed[msg.sender][_spender] = _newAllowed;
} else {
if (_valueChange > self.allowed[msg.sender][_spender]) {
self.allowed[msg.sender][_spender] = 0;
} else {
_newAllowed = self.allowed[msg.sender][_spender] - _valueChange;
self.allowed[msg.sender][_spender] = _newAllowed;
}
}
Approval(msg.sender, _spender, _newAllowed);
return true;
}
/// @dev Change owning address of the token contract, specifically for minting
/// @param self Stored token from token contract
/// @param _newOwner Address for the new owner
/// @return True if completed
function changeOwner(TokenStorage storage self, address _newOwner) returns (bool) {
require((self.owner == msg.sender) && (_newOwner > 0));
self.owner = _newOwner;
OwnerChange(msg.sender, _newOwner);
return true;
}
/// @dev Mints additional tokens, new tokens go to owner
/// @param self Stored token from token contract
/// @param _amount Number of tokens to mint
/// @return True if completed
function mintToken(TokenStorage storage self, uint256 _amount) returns (bool) {
require((self.owner == msg.sender) && self.stillMinting);
uint256 _newAmount;
bool err;
(err, _newAmount) = self.totalSupply.plus(_amount);
require(!err);
self.totalSupply = _newAmount;
self.balances[self.owner] = self.balances[self.owner] + _amount;
Transfer(0x0, self.owner, _amount);
return true;
}
/// @dev Permanent stops minting
/// @param self Stored token from token contract
/// @return True if completed
function closeMint(TokenStorage storage self) returns (bool) {
require(self.owner == msg.sender);
self.stillMinting = false;
MintingClosed(true);
return true;
}
/// @dev Permanently burn tokens
/// @param self Stored token from token contract
/// @param _amount Amount of tokens to burn
/// @return True if completed
function burnToken(TokenStorage storage self, uint256 _amount) returns (bool) {
uint256 _newBalance;
bool err;
(err, _newBalance) = self.balances[msg.sender].minus(_amount);
require(!err);
self.balances[msg.sender] = _newBalance;
self.totalSupply = self.totalSupply - _amount;
Burn(msg.sender, _amount);
Transfer(msg.sender, 0x0, _amount);
return true;
}
}
library BasicMathLib {
event Err(string typeErr);
/// @dev Multiplies two numbers and checks for overflow before returning.
/// Does not throw but rather logs an Err event if there is overflow.
/// @param a First number
/// @param b Second number
/// @return err False normally, or true if there is overflow
/// @return res The product of a and b, or 0 if there is overflow
function times(uint256 a, uint256 b) constant returns (bool err,uint256 res) {
assembly{
res := mul(a,b)
switch or(iszero(b), eq(div(res,b), a))
case 0 {
err := 1
res := 0
}
}
if (err)
Err("times func overflow");
}
/// @dev Divides two numbers but checks for 0 in the divisor first.
/// Does not throw but rather logs an Err event if 0 is in the divisor.
/// @param a First number
/// @param b Second number
/// @return err False normally, or true if `b` is 0
/// @return res The quotient of a and b, or 0 if `b` is 0
function dividedBy(uint256 a, uint256 b) constant returns (bool err,uint256 res) {
assembly{
switch iszero(b)
case 0 {
res := div(a,b)
mstore(add(mload(0x40),0x20),res)
return(mload(0x40),0x40)
}
}
Err("tried to divide by zero");
return (true, 0);
}
/// @dev Adds two numbers and checks for overflow before returning.
/// Does not throw but rather logs an Err event if there is overflow.
/// @param a First number
/// @param b Second number
/// @return err False normally, or true if there is overflow
/// @return res The sum of a and b, or 0 if there is overflow
function plus(uint256 a, uint256 b) constant returns (bool err, uint256 res) {
assembly{
res := add(a,b)
switch and(eq(sub(res,b), a), or(gt(res,b),eq(res,b)))
case 0 {
err := 1
res := 0
}
}
if (err)
Err("plus func overflow");
}
/// @dev Subtracts two numbers and checks for underflow before returning.
/// Does not throw but rather logs an Err event if there is underflow.
/// @param a First number
/// @param b Second number
/// @return err False normally, or true if there is underflow
/// @return res The difference between a and b, or 0 if there is underflow
function minus(uint256 a, uint256 b) constant returns (bool err,uint256 res) {
assembly{
res := sub(a,b)
switch eq(and(eq(add(res,b), a), or(lt(res,a), eq(res,a))), 1)
case 0 {
err := 1
res := 0
}
}
if (err)
Err("minus func underflow");
}
}
{
"compilationTarget": {
"DLBXToken.sol": "DLBXToken"
},
"libraries": {},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"value","type":"uint256"}],"name":"approve","outputs":[{"name":"ok","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"from","type":"address"},{"name":"to","type":"address"},{"name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"ok","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"initialSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"who","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"amount","type":"uint256"}],"name":"burnToken","outputs":[{"name":"ok","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"changeOwner","outputs":[{"name":"ok","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"}],"name":"transfer","outputs":[{"name":"ok","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"},{"name":"spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[{"name":"owner","type":"address"},{"name":"name","type":"string"},{"name":"symbol","type":"string"},{"name":"decimals","type":"uint8"},{"name":"initialSupply","type":"uint256"},{"name":"allowMinting","type":"bool"}],"payable":false,"type":"constructor"},{"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"},{"anonymous":false,"inputs":[{"indexed":false,"name":"from","type":"address"},{"indexed":false,"name":"to","type":"address"}],"name":"OwnerChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"burner","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"mintingClosed","type":"bool"}],"name":"MintingClosed","type":"event"}]