Last active
February 5, 2018 10:16
-
-
Save safead/17f523bad49327ab5a706606757da51b to your computer and use it in GitHub Desktop.
SAFE Token
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.18; | |
contract ERC20Interface{ | |
function balanceOf(address) public constant returns (uint256); | |
function transfer(address, uint256) public returns (bool); | |
} | |
contract SAFEToken{ | |
event Transfer(address indexed _from, address indexed _to, uint256 _value); | |
event Approval(address indexed _owner, address indexed _spender, uint256 _value); | |
event MintingAgentChanged(address _addr, bool _state); | |
event Mint(address indexed _to, uint256 _value); | |
event MintFinished(); | |
event UpdatedTokenInformation(string _newName, string _newSymbol, uint8 _newDecimals); | |
event OwnershipTransferred(address indexed _previousOwner, address indexed _newOwner); | |
event TransfersAreAllowed(); | |
event Error(address indexed _self, uint8 _errorCode); | |
uint256 constant private MAX_UINT256 = 2**256 - 1; | |
uint8 constant private ERROR_ZERO_ADDRESS = 1; | |
uint8 constant private ERROR_INSUFICIENT_BALANCE = 2; | |
uint8 constant private ERROR_INSUFICIENT_ALLOWENCE = 3; | |
uint8 constant private ERROR_ARRAYS_LENGTH_DIFF = 4; | |
uint8 constant private ERROR_INT_OVERFLOW = 5; | |
uint8 constant private ERROR_UNAUTHORIZED = 6; | |
uint8 constant private ERROR_TRANSFER_NOT_ALLOWED = 7; | |
string public name; | |
string public symbol; | |
uint8 public decimals; | |
bool public transfersSuspended = true; | |
address owner; | |
uint256 totalSupply_ = 0; | |
bool mintingFinished = false; | |
mapping(address => uint256) balances; | |
mapping(address => mapping(address => uint256)) internal allowed; | |
mapping(address => bool) mintAgents; | |
modifier onlyOwner(){ | |
require(msg.sender == owner); | |
_; | |
} | |
modifier onlyMintAgent(){ | |
require(mintAgents[msg.sender]); | |
_; | |
} | |
modifier canMint(){ | |
require(!mintingFinished); | |
_; | |
} | |
function SAFEToken(uint256 _totalSupply, string _name, string _symbol, uint8 _decimals) public{ | |
totalSupply_ = _totalSupply; | |
owner = msg.sender; | |
name = _name; | |
symbol = _symbol; | |
decimals = _decimals; | |
balances[owner] = totalSupply_; | |
} | |
function totalSupply() public view returns (uint256){ | |
return totalSupply_; | |
} | |
function transfer(address _to, uint256 _value) public returns (bool){ | |
if(transfersSuspended) return isError(ERROR_TRANSFER_NOT_ALLOWED); | |
if(_to == address(0)) return isError(ERROR_ZERO_ADDRESS); | |
if(balances[msg.sender] < _value) return isError(ERROR_INSUFICIENT_BALANCE); | |
balances[msg.sender] -= _value; | |
balances[_to] += _value; | |
Transfer(msg.sender, _to, _value); | |
return true; | |
} | |
function balanceOf(address _owner) public view returns (uint256){ | |
return balances[_owner]; | |
} | |
function transferFrom(address _from, address _to, uint256 _value) public returns (bool){ | |
if(transfersSuspended) return isError(ERROR_TRANSFER_NOT_ALLOWED); | |
uint256 allowance = allowed[_from][msg.sender]; | |
if(balances[_from] < _value) return isError(ERROR_INSUFICIENT_BALANCE); | |
if(allowance < _value) return isError(ERROR_INSUFICIENT_ALLOWENCE); | |
balances[_to] += _value; | |
balances[_from] -= _value; | |
if(allowance < MAX_UINT256) allowed[_from][msg.sender] -= _value; | |
Transfer(_from, _to, _value); | |
return true; | |
} | |
function approve(address _spender, uint256 _value) public returns (bool success){ | |
if(transfersSuspended) return isError(ERROR_TRANSFER_NOT_ALLOWED); | |
if(_spender == address(0)) return isError(ERROR_ZERO_ADDRESS); | |
allowed[msg.sender][_spender] = _value; | |
Approval(msg.sender, _spender, _value); | |
return true; | |
} | |
function allowance(address _owner, address _spender) public view returns (uint256){ | |
return allowed[_owner][_spender]; | |
} | |
function mint(address[] _receivers, uint256[] _values) public onlyMintAgent canMint returns (bool){ | |
if(_receivers.length != _values.length) return isError(ERROR_ARRAYS_LENGTH_DIFF); | |
for(uint256 i = 0; i < _receivers.length; ++i){ | |
if(totalSupply_ + _values[i] < totalSupply_) return isError(ERROR_INT_OVERFLOW); | |
totalSupply_ += _values[i]; | |
} | |
for(i = 0; i < _receivers.length; ++i){ | |
balances[_receivers[i]] += _values[i]; | |
Mint(_receivers[i], _values[i]); | |
Transfer(address(0), _receivers[i], _values[i]); | |
} | |
return true; | |
} | |
function setMintAgent(address _addr, bool _state) onlyOwner canMint public returns (bool){ | |
if(_addr == address(0)) return isError(ERROR_ZERO_ADDRESS); | |
mintAgents[_addr] = _state; | |
MintingAgentChanged(_addr, _state); | |
return true; | |
} | |
function finishMinting() onlyOwner canMint public returns (bool){ | |
mintingFinished = true; | |
MintFinished(); | |
return true; | |
} | |
function allowTransfers() onlyOwner public returns (bool){ | |
transfersSuspended = false; | |
TransfersAreAllowed(); | |
return true; | |
} | |
function changeOwner(address _newOwner) public onlyOwner returns(bool){ | |
if(_newOwner == address(0)) return isError(ERROR_ZERO_ADDRESS); | |
address prevOwner = owner; | |
owner = _newOwner; | |
OwnershipTransferred(prevOwner, owner); | |
return true; | |
} | |
function setTokenInformation(string _name, string _symbol, uint8 _decimals) public onlyOwner returns (bool){ | |
name = _name; | |
symbol = _symbol; | |
decimals = _decimals; | |
UpdatedTokenInformation(_name, _symbol, _decimals); | |
return true; | |
} | |
function withdrawnTokens(address[] _tokens, address _to) public onlyOwner returns (bool){ | |
for(uint256 i = 0; i < _tokens.length; i++){ | |
address token = _tokens[i]; | |
uint256 balance = ERC20Interface(token).balanceOf(this); | |
if(balance != 0) ERC20Interface(token).transfer(_to, balance); | |
} | |
return true; | |
} | |
function isError(uint8 _error) private returns (bool){ | |
Error(msg.sender, _error); | |
return false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
SAFE token truffle tests https://gist.github.com/safead/1f1b78550f031df73fe0308366f10487 (improved ConsenSys tests)