Skip to content

Instantly share code, notes, and snippets.

@safead
Last active February 5, 2018 10:16
Show Gist options
  • Save safead/17f523bad49327ab5a706606757da51b to your computer and use it in GitHub Desktop.
Save safead/17f523bad49327ab5a706606757da51b to your computer and use it in GitHub Desktop.
SAFE Token
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;
}
}
@safead
Copy link
Author

safead commented Jan 27, 2018

SAFE token truffle tests https://gist.github.com/safead/1f1b78550f031df73fe0308366f10487 (improved ConsenSys tests)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment