Skip to content

Instantly share code, notes, and snippets.

@furusiyya
Last active July 24, 2017 13:18
Show Gist options
  • Save furusiyya/395db5456529e2b86f3c4ac0f7130891 to your computer and use it in GitHub Desktop.
Save furusiyya/395db5456529e2b86f3c4ac0f7130891 to your computer and use it in GitHub Desktop.
/**
* Asset Token contract, ERC20 compliant (see https://github.com/ethereum/EIPs/issues/20)
*
* Code is based on multiple sources:
* https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts
* https://github.com/TokenMarketNet/ico/blob/master/contracts
* https://github.com/ConsenSys/Tokens/blob/master/Token_Contracts/contracts
*/
pragma solidity ^0.4.13;
library SafeMath {
function mul(uint256 a, uint256 b) internal returns (uint256) {
uint256 c = a * b;
assert(a == 0 || c / a == b);
return c;
}
function div(uint256 a, uint256 b) internal returns (uint256) {
// assert(b > 0); // Solidity automatically throws when dividing by 0
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
function sub(uint256 a, uint256 b) internal returns (uint256) {
assert(b <= a);
return a - b;
}
function add(uint256 a, uint256 b) internal returns (uint256) {
uint256 c = a + b;
assert(c >= a);
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;
}
}
contract AssetToken{
address private owner;
address private multiSig;
/* AST functions are paused if there is any emergency */
bool public emergency = false;
bool private sellingEnabled;
uint256 private exchangeRate;
using SafeMath for uint;
string public name;
string public symbol;
uint256 public decimals;
uint256 public totalSupply;
/* Actual balances of token holders */
mapping(address => uint256) balances;
/* approve() allowances */
mapping (address => mapping (address => uint256)) allowed;
/* freezeAccount() frozen() */
mapping (address => bool) frozenAccount;
/* ERC20 standard event */
event Approval(address indexed owner, address indexed spender, uint256 value);
event Transfer(address indexed from, address indexed to, uint256 value);
/* Notify account frozen activity */
event FrozenFunds(address target, bool frozen);
function AssetToken(address _owner, address _multiSig, uint256 _exchangeRate){
name = "Asset Token";
symbol = "AST";
decimals = 18;
owner = _owner;
multiSig = _multiSig;
totalSupply = 1000000000 * 1 ether;
// Allocate initial balance to the owner //
balances[owner] = 1000000000 * 1 ether;
exchangeRate = _exchangeRate;
}
function transfer(address _to, uint256 _value) stopInEmergency onlyPayloadSize(2 * 32) returns (bool success) {
require(_to != 0x00);
// Check if frozen //
require(!frozenAccount[msg.sender]);
balances[msg.sender] = balances[msg.sender].sub( _value);
balances[_to] = balances[_to].add(_value);
Transfer(msg.sender, _to, _value);
return true;
}
function transferFrom(address _from, address _to, uint256 _value) stopInEmergency returns (bool success) {
require(_to != 0x00);
// Check if frozen //
require(!frozenAccount[_from]);
uint256 _allowance = allowed[_from][msg.sender];
balances[_to] = balances[_to].add(_value);
balances[_from] = balances[_from].sub(_value);
allowed[_from][msg.sender] = _allowance.sub(_value);
Transfer(_from, _to, _value);
return true;
}
function balanceOf(address _owner) constant returns (uint256 balance) {
return balances[_owner];
}
function approve(address _spender, uint256 _value) stopInEmergency returns (bool success) {
require(_spender != 0x00);
// 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)) revert();
allowed[msg.sender][_spender] = _value;
Approval(msg.sender, _spender, _value);
return true;
}
function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
return allowed[_owner][_spender];
}
/**
* It is called Circuit Breakers (Pause contract functionality), it stop execution if certain conditions are met,
* and can be useful when new errors are discovered. For example, most actions may be suspended in a contract if a
* bug is discovered, so the most feasible option to stop and updated migration message about launching an updated version of contract.
* @param _stop Switch the circuite breaker on or off
*/
function emergencyStop(bool _stop) onlyOwner {
emergency = _stop;
}
/**
* Owner can set any account into freeze state. It is helpful in case if account holder has
* lost his key and he want administrator to freeze account until account key is recovered
* @param target The account address
* @param freeze The state of account
*/
function freezeAccount(address target, bool freeze) onlyOwner {
frozenAccount[target] = freeze;
FrozenFunds(target, freeze);
}
function frozen(address _target) constant returns (bool frozen) {
return frozenAccount[_target];
}
/**
* @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 {
require(newOwner != 0x00);
balances[newOwner] = balances[owner];
balances[owner] = 0;
owner = newOwner;
Transfer(owner, newOwner,balances[newOwner]);
}
function astPerEther() constant returns (uint256 ast){
return exchangeRate;
}
function exchangeStatus() constant returns(bool enabled){
return sellingEnabled;
}
function contractOwner() constant returns(address _owner){
return owner;
}
function walletAddress() constant returns(address fundsHolder){
return multiSig;
}
function setMultiSig(address _newAddress) onlyOwner{
require(_newAddress != 0x00);
multiSig = _newAddress;
}
function setExchangeRate(uint256 _astPerEther) onlyOwner{
require(_astPerEther > 0);
exchangeRate = _astPerEther;
}
function enableExchange(bool _value) onlyOwner{
sellingEnabled = _value;
}
function () payable nonZero exchangeOn stopInEmergency{
buy(msg.sender);
}
function buy(address _customer) nonZero exchangeOn stopInEmergency payable {
uint256 weiAmount = msg.value;
uint256 tokens = weiAmount * exchangeRate;
require(balances[owner] >= tokens);
balances[_customer] = balances[_customer].add(tokens);
balances[owner] = balances[owner].sub(tokens);
if(!multiSig.send(weiAmount)){
revert();
}
Transfer(owner, _customer, tokens);
}
/* Interface declaration */
function isToken() public constant returns (bool weAre) {
return true;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
if (msg.sender != owner) {
revert();
}
_;
}
/**
* Fix for the ERC20 short address attack
*
* http://vessenes.com/the-erc20-short-address-attack-explained/
*/
modifier onlyPayloadSize(uint256 size) {
if(msg.data.length < size + 4) {
revert();
}
_;
}
modifier stopInEmergency {
require(!emergency);
_;
}
modifier nonZero() {
require(msg.value > 0);
_;
}
modifier exchangeOn() {
require(sellingEnabled);
_;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment