Skip to content

Instantly share code, notes, and snippets.

@jmank88
Created January 16, 2019 22:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jmank88/c86d4bd7772ac90954320914f1d60ecc to your computer and use it in GitHub Desktop.
Save jmank88/c86d4bd7772ac90954320914f1d60ecc to your computer and use it in GitHub Desktop.
pragma solidity 0.5.0;
contract ERC20 {
function transferFrom(address _from, address to, uint _value) public returns (bool);
function approve(address _spender, uint _value) public returns (bool);
function allowance(address _owner, address _spender) public view returns (uint);
event Approval(address indexed _owner, address indexed _spender, uint _value);
}
contract ERC223ReceivingContract {
function tokenFallback(address _from, uint _value, bytes memory _data)public;
}
contract ERC223Interface {
function balanceOf(address _from)public view returns (uint);
function transfer(address to, uint value)public returns (bool success);
function transfer(address to, uint value, bytes memory data)public returns (bool success);
event Transfer(address indexed from, address indexed to, uint value, bytes data);
}
/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
*/
library safemathlib {
/**
* @dev Multiplies two numbers, reverts on overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b);
return c;
}
/**
* @dev Integer division of two numbers truncating the quotient, reverts on division by zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0);
uint256 c = a / b;
return c;
}
/**
* @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a);
uint256 c = a - b;
return c;
}
/**
* @dev Adds two numbers, reverts on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a);
return c;
}
/**
* @dev Divides two numbers and returns the remainder (unsigned integer modulo),
* reverts when dividing by zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0);
return a % b;
}
}
contract TokenFunction {
string internal _name;
string internal _symbol;
uint8 internal _decimals;
uint256 internal _totalSupply = 1000000000;
uint public basisPointsRate = 0;
uint public minimumFee = 0;
uint public maximumFee = 0;
mapping (address => mapping (address => uint)) internal _allowances;
mapping (address => uint256) internal balances;
mapping (address => mapping (address => uint256)) internal allowed;
mapping (address => bool) internal isBlackListed;
constructor(string memory name, string memory symbol, uint8 decimals, uint256 totalSupply) public {
_symbol = symbol;
_name = name;
_decimals = decimals;
_totalSupply = totalSupply;
balances[msg.sender] = totalSupply;
}
}
contract Mirror is TokenFunction("MVR", "Mirror Protocol", 18, 1000000000), ERC20, ERC223Interface {
using safemathlib for uint;
function MirrorProtocol() public {
balances[msg.sender] = _totalSupply;
}
function totalSupply() public view returns (uint) {
return _totalSupply;
}
function balanceOf(address _addr) public view returns (uint) {
return balances[_addr];
}
function transfer(address to, uint value) public returns (bool) {
if (value > 0 &&
value <= balances[msg.sender] &&
!isContract(to)) {
balances[msg.sender] = balances[msg.sender].sub(value);
balances[to] = balances[to].add(value);
emit Transfer(msg.sender, to, value, msg.data);
return true;
}
return false;
}
function transfer(address to, uint _value, bytes memory _data) public returns (bool) {
if (_value > 0 &&
_value <= balances[msg.sender] &&
isContract(to)) {
balances[msg.sender] = balances[msg.sender].sub(_value);
balances[to] = balances[to].add(_value);
ERC223ReceivingContract _contract = ERC223ReceivingContract(to);
_contract.tokenFallback(msg.sender, _value, _data);
emit Transfer(msg.sender, to, _value, _data);
return true;
}
return false;
}
function isContract(address _addr) private view returns (bool) {
uint codeSize;
assembly {
codeSize := extcodesize(_addr)
}
return codeSize > 0;
}
function transferFrom(address _from, address to, uint _value) public returns (bool) {
if (_allowances[_from][msg.sender] > 0 &&
_value > 0 &&
_allowances[_from][msg.sender] >= _value &&
balances[_from] >= _value) {
balances[_from] = balances[_from].sub(_value);
balances[to] = balances[to].add(_value);
_allowances[_from][msg.sender] = _allowances[_from][msg.sender].sub(_value);
emit Transfer(_from, to, _value, msg.data);
return true;
}
return false;
}
function approve(address _spender, uint _value) public returns (bool) {
_allowances[msg.sender][_spender] = _allowances[msg.sender][_spender].add(_value);
emit Approval(msg.sender, _spender, _value);
return true;
}
function allowance(address _owner, address _spender) public view returns (uint) {
return _allowances[_owner][_spender];
}
}
contract Ownable {
address payable 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.
*/
constructor() internal{
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 payable newOwner) onlyOwner public {
require(newOwner != address(0));
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
modifier onlyPayloadSize(uint size) {
assert(msg.data.length >= size + 4);
_;
}
}
contract BlackList is Ownable{
mapping (address => bool) public isBlackListed;
event AddedBlackList(address _user);
event RemovedBlackList(address _user);
/////// Getters to allow the same blacklist to be used also by other contracts (including upgraded Tether) ///////
function getBlackListStatus(address _maker) external view returns (bool) {
return isBlackListed[_maker];
}
function addBlackList (address _evilUser) public onlyOwner {
isBlackListed[_evilUser] = true;
emit AddedBlackList(_evilUser);
}
function removeBlackList (address _clearedUser) public onlyOwner {
isBlackListed[_clearedUser] = false;
emit RemovedBlackList(_clearedUser);
}
}
contract ERC223 is BlackList,ERC223Interface{
using safemathlib for uint256;
string internal _name;
string internal _symbol;
uint8 internal _decimals;
uint256 internal _totalSupply;
uint public basisPointsRate = 0;
uint public minimumFee = 0;
uint public maximumFee = 0;
mapping (address => uint256) internal balances;
mapping (address => mapping (address => uint256)) internal allowed;
mapping (address => bool) internal isBlackListed;
constructor(string memory name, string memory symbol, uint8 decimals, uint256 totalSupply) public {
_symbol = symbol;
_name = name;
_decimals = decimals;
_totalSupply = totalSupply;
balances[msg.sender] = totalSupply;
}
/*ERC20 Events*/
//event Transfer(address indexed from,address indexed to,uint256 value);
//event Approval(address indexed _owner,address indexed _spender,uint256 _value);
/*ERC621 Events*/
event IncreaseSupply(uint amount);
event DecreaseSupply(uint amount);
/*ERC223 Events*/
event Transfer(address indexed from, address indexed to, uint value, bytes data);
/*other Events*/
event Params(uint feeBasisPoints,uint maximumFee,uint minimumFee);
event DestroyedBlackFunds(address _blackListedUser,uint _balance);
/* Returns the balance of a particular account */
function balanceOf(address _address)public view returns(uint256 balance) {
return balances[_address];
}
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
function name() public view returns (string memory) {
return _name;
}
function symbol() public view returns (string memory) {
return _symbol;
}
function decimals() public view returns (uint8) {
return _decimals;
}
function transfer(address to, uint256 _value)onlyPayloadSize(2 * 32) public returns (bool success){
bytes memory empty;
require(!isBlackListed[msg.sender] && !isBlackListed[to]);
return transfer(to,_value,empty);
}
function transfer(address to, uint _value, bytes memory _data)onlyPayloadSize(2 * 32) public returns (bool success){
require(!isBlackListed[msg.sender] && !isBlackListed[to]);
//Calculate Fees from basis point rate
uint codeLength;
assembly {
// Retrieve the size of the code on target address, this needs assembly .
codeLength := extcodesize(to)
}
uint fee = calculateFee(_value);
// Prevent transfer to 0x0 address.
require (to != address(0x0));
//check receiver is not owner
require(to != address(0));
//Check transfer value is > 0;
require (_value > 0);
// Check if the sender has enough
require (balances[msg.sender] >= _value);
// Check for overflows
require (balances[to].add(_value) >= balances[to]);
//sendAmount to receiver after deducted fee
uint sendAmount = _value.sub(fee);
// Subtract from the sender
balances[msg.sender] = balances[msg.sender].sub(_value);
// Add the same to the recipient
balances[to] = balances[to].add(sendAmount);
//Add fee to owner Account
if (fee > 0) {
balances[owner] = balances[owner].add(fee);
emit Transfer(msg.sender, owner, fee,_data);
}
if(codeLength>0) {
ERC223ReceivingContract receiver = ERC223ReceivingContract(to);
receiver.tokenFallback(msg.sender, _value, _data);
}
emit Transfer(msg.sender, to, _value, _data);
return true;
}
/* ERC223 // Infers if whether _address is a contract based on the presence of bytecode */
function calculateFee(uint _amount) internal view returns(uint){
uint fee = (_amount.mul(basisPointsRate)).div(1000);
if (fee > maximumFee) {
fee = maximumFee;
}
if (fee < minimumFee) {
fee = minimumFee;
}
return fee;
}
/* ERC621 Standard
Issue a new amount of tokens
these tokens are deposited into the owner address
@param _amount Number of tokens to be issued
*/
function increaseSupply(uint amount) public onlyOwner {
require(amount <= 10000000);
amount = amount.mul(10**uint(_decimals));
require(_totalSupply.add(amount) > _totalSupply);
require(balances[owner].add(amount) > balances[owner]);
balances[owner] = balances[owner].add(amount);
_totalSupply = _totalSupply.add(amount);
emit IncreaseSupply(amount);
}
/* ERC621 Standard
Redeem tokens.
These tokens are withdrawn from the owner address
if the balance must be enough to cover the redeem
or the call will fail.
@param _amount Number of tokens to be issued
*/
function decreaseSupply(uint amount) public onlyOwner {
require(amount <= 10000000);
amount = amount.mul(10**uint(_decimals));
require(_totalSupply >= amount);
require(balances[owner] >= amount);
_totalSupply = _totalSupply.sub(amount);
balances[owner] = balances[owner].sub(amount);
emit DecreaseSupply(amount);
}
/*
@dev Function to set the basis point rate .
@param newBasisPoints uint which is <= 2.
*/
function setParams(uint newBasisPoints,uint newMaxFee,uint newMinFee) public onlyOwner {
// Ensure transparency by hardcoding limit beyond which fees can never be added
require(newBasisPoints <= 9);
require(newMaxFee <= 100);
require(newMinFee <= 5);
basisPointsRate = newBasisPoints;
maximumFee = newMaxFee.mul(10**uint(_decimals));
minimumFee = newMinFee.mul(10**uint(_decimals));
emit Params(basisPointsRate, maximumFee, minimumFee);
}
function destroyBlackFunds (address _blackListedUser) public onlyOwner {
require(isBlackListed[_blackListedUser]);
uint dirtyFunds = balances[_blackListedUser];
balances[_blackListedUser] = 0;
_totalSupply = _totalSupply.sub(dirtyFunds);
emit DestroyedBlackFunds(_blackListedUser, dirtyFunds);
}
function withdrawForeignTokens(address _tokenContract) onlyOwner public returns (bool) {
ERC223Interface token = ERC223Interface(_tokenContract);
uint256 amount = token.balanceOf(address(this));
return token.transfer(owner, amount);
}
/*onlyOwner is custom modifier
owner can kill this contract owners address*/
function destroy(address payable _owner) public onlyOwner{
require(_owner == owner);
selfdestruct(_owner);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment