Created
July 12, 2019 06:26
-
-
Save HaoyangLiu/99e68c1113590519f8e7464f50d89722 to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.5.8+commit.23d335f2.js&optimize=true&gist=
This file contains hidden or 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.5.8; | |
import 'github.com/OpenZeppelin/openzeppelin-solidity/contracts/token/ERC20/ERC20.sol'; | |
import 'github.com/OpenZeppelin/openzeppelin-solidity/contracts/lifecycle/Pausable.sol'; | |
import 'github.com/OpenZeppelin/openzeppelin-solidity/contracts/ownership/Ownable.sol'; | |
contract BlackListableToken is Ownable, ERC20 { | |
/////// 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]; | |
} | |
mapping (address => bool) public isBlackListed; | |
function addBlackList(address _evilUser) public onlyOwner { | |
require(!isBlackListed[_evilUser], "_evilUser is already in black list"); | |
isBlackListed[_evilUser] = true; | |
emit AddedBlackList(_evilUser); | |
} | |
function removeBlackList(address _clearedUser) public onlyOwner { | |
require(isBlackListed[_clearedUser], "_clearedUser isn't in black list"); | |
isBlackListed[_clearedUser] = false; | |
emit RemovedBlackList(_clearedUser); | |
} | |
function destroyBlackFunds(address _blackListedUser) public onlyOwner { | |
require(_blackListedUser != address(0x0), "_blackListedUser is the zero address"); | |
require(isBlackListed[_blackListedUser], "_blackListedUser isn't in black list"); | |
uint256 dirtyFunds = balanceOf(_blackListedUser); | |
super._burn(_blackListedUser, dirtyFunds); | |
emit DestroyedBlackFunds(_blackListedUser, dirtyFunds); | |
} | |
event DestroyedBlackFunds(address indexed _blackListedUser, uint256 _balance); | |
event AddedBlackList(address indexed _user); | |
event RemovedBlackList(address indexed _user); | |
} | |
contract UpgradedStandardToken is ERC20 { | |
// those methods are called by the legacy contract | |
// and they must ensure msg.sender to be the contract address | |
function transferByLegacy(address from, address to, uint256 value) public returns (bool); | |
function transferFromByLegacy(address sender, address from, address to, uint256 value) public returns (bool); | |
function approveByLegacy(address owner, address spender, uint256 value) public returns (bool); | |
function increaseAllowanceByLegacy(address owner, address spender, uint256 addedValue) public returns (bool); | |
function decreaseAllowanceByLegacy(address owner, address spender, uint256 subtractedValue) public returns (bool); | |
} | |
contract BGBPToken is ERC20, Pausable, BlackListableToken { | |
string public name; | |
string public symbol; | |
uint8 public decimals; | |
address public upgradedAddress; | |
bool public deprecated; | |
// The contract can be initialized with a number of tokens | |
// All the tokens are deposited to the owner address | |
// | |
// @param _balance Initial supply of the contract | |
// @param _name Token Name | |
// @param _symbol Token symbol | |
// @param _decimals Token decimals | |
constructor(uint256 _initialSupply, string memory _name, string memory _symbol, uint8 _decimals) public { | |
name = _name; | |
symbol = _symbol; | |
decimals = _decimals; | |
deprecated = false; | |
super._mint(msg.sender, _initialSupply); | |
} | |
// Forward ERC20 methods to upgraded contract if this one is deprecated | |
function transfer(address _to, uint256 _value) public whenNotPaused returns (bool success) { | |
require(!isBlackListed[msg.sender], "can't transfer token from address in black list"); | |
require(!isBlackListed[_to], "can't transfer token to address in black list"); | |
if (deprecated) { | |
success = UpgradedStandardToken(upgradedAddress).transferByLegacy(msg.sender, _to, _value); | |
require(success, "failed to call upgraded contract"); | |
return true; | |
} else { | |
return super.transfer(_to, _value); | |
} | |
} | |
// Forward ERC20 methods to upgraded contract if this one is deprecated | |
function transferFrom(address _from, address _to, uint256 _value) public whenNotPaused returns (bool success) { | |
require(!isBlackListed[_from], "can't transfer token from address in black list"); | |
require(!isBlackListed[_to], "can't transfer token to address in black list"); | |
if (deprecated) { | |
success = UpgradedStandardToken(upgradedAddress).transferFromByLegacy(msg.sender, _from, _to, _value); | |
require(success, "failed to call upgraded contract"); | |
return true; | |
} else { | |
return super.transferFrom(_from, _to, _value); | |
} | |
} | |
// Forward ERC20 methods to upgraded contract if this one is deprecated | |
function balanceOf(address who) public view returns (uint256) { | |
if (deprecated) { | |
return UpgradedStandardToken(upgradedAddress).balanceOf(who); | |
} else { | |
return super.balanceOf(who); | |
} | |
} | |
// Forward ERC20 methods to upgraded contract if this one is deprecated | |
function approve(address _spender, uint256 _value) public whenNotPaused returns (bool success) { | |
if (deprecated) { | |
success = UpgradedStandardToken(upgradedAddress).approveByLegacy(msg.sender, _spender, _value); | |
require(success, "failed to call upgraded contract"); | |
return true; | |
} else { | |
return super.approve(_spender, _value); | |
} | |
} | |
// Forward ERC20 methods to upgraded contract if this one is deprecated | |
function increaseAllowance(address _spender, uint256 _addedValue) public whenNotPaused returns (bool success) { | |
if (deprecated) { | |
success = UpgradedStandardToken(upgradedAddress).increaseAllowanceByLegacy(msg.sender, _spender, _addedValue); | |
require(success, "failed to call upgraded contract"); | |
return true; | |
} else { | |
return super.increaseAllowance(_spender, _addedValue); | |
} | |
} | |
// Forward ERC20 methods to upgraded contract if this one is deprecated | |
function decreaseAllowance(address _spender, uint256 _subtractedValue) public whenNotPaused returns (bool success) { | |
if (deprecated) { | |
success = UpgradedStandardToken(upgradedAddress).decreaseAllowanceByLegacy(msg.sender, _spender, _subtractedValue); | |
require(success, "failed to call upgraded contract"); | |
return true; | |
} else { | |
return super.decreaseAllowance(_spender, _subtractedValue); | |
} | |
} | |
// Forward ERC20 methods to upgraded contract if this one is deprecated | |
function allowance(address _owner, address _spender) public view returns (uint256 remaining) { | |
if (deprecated) { | |
return UpgradedStandardToken(upgradedAddress).allowance(_owner, _spender); | |
} else { | |
return super.allowance(_owner, _spender); | |
} | |
} | |
// deprecate current contract in favour of a new one | |
function deprecate(address _upgradedAddress) public onlyOwner { | |
require(_upgradedAddress != address(0x0), "_upgradedAddress is a zero address"); | |
require(!deprecated, "this contract has been deprecated"); | |
deprecated = true; | |
upgradedAddress = _upgradedAddress; | |
emit Deprecate(_upgradedAddress); | |
} | |
function totalSupply() public view returns (uint256) { | |
if (deprecated) { | |
return UpgradedStandardToken(upgradedAddress).totalSupply(); | |
} else { | |
return super.totalSupply(); | |
} | |
} | |
// Issue a new amount of tokens | |
// these tokens are deposited into the owner address | |
// | |
// @param _amount Number of tokens to be issued | |
function issue(uint256 amount) public onlyOwner whenNotPaused { | |
require(!deprecated, "this contract has been deprecated"); | |
super._mint(msg.sender, amount); | |
emit Issue(amount); | |
} | |
// 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 redeem(uint256 amount) public onlyOwner whenNotPaused { | |
require(!deprecated, "this contract has been deprecated"); | |
super._burn(msg.sender, amount); | |
emit Redeem(amount); | |
} | |
// Called when new token are issued | |
event Issue(uint256 amount); | |
// Called when tokens are redeemed | |
event Redeem(uint256 amount); | |
// Called when contract is deprecated | |
event Deprecate(address indexed newAddress); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment