Transaction Hash:
Block:
18285969 at Oct-05-2023 06:02:47 PM +UTC
Transaction Fee:
0.000722068428593408 ETH
$1.74
Gas Used:
60,736 Gas / 11.888639828 Gwei
Emitted Events:
284 |
TetherToken.Transfer( from=[Receiver] DividendDistributor, to=[Sender] 0x389346e15bd2d4cfb046e1c70911dc1d9b9b639b, value=1374928552 )
|
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x1f9090aa...8e676c326
Miner
| 2.382556887139251157 Eth | 2.382562960739251157 Eth | 0.0000060736 | ||
0x389346E1...D9b9B639B |
30.083528964881947187 Eth
Nonce: 435
|
30.082806896453353779 Eth
Nonce: 436
| 0.000722068428593408 | ||
0x4671746B...0765F7dFE | |||||
0xdAC17F95...13D831ec7 |
Execution Trace
DividendDistributor.repurposeSacrificed( percent=100 )
-
TetherToken.transfer( _to=0x389346E15bd2D4CFB046E1C70911Dc1D9b9B639B, _value=1374928552 )
repurposeSacrificed[DividendDistributor (ln:489)]
transfer[DividendDistributor (ln:492)]
File 1 of 2: DividendDistributor
File 2 of 2: TetherToken
/* AUDINALS Website: https://www.audinals.io/ Telegram: https://t.me/audinalsofficial Twitter: https://twitter.com/audinalsmusic */ // SPDX-License-Identifier: MIT pragma solidity 0.8.21; abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. C U ON THE MOON */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval( address indexed owner, address indexed spender, uint256 value ); } interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); } contract ERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } function name() public view virtual override returns (string memory) { return _name; } function symbol() public view virtual override returns (string memory) { return _symbol; } function decimals() public view virtual override returns (uint8) { return 18; } function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), spender, amount); return true; } function transferFrom( address sender, address recipient, uint256 amount ) public virtual override returns (bool) { _transfer(sender, recipient, amount); uint256 currentAllowance = _allowances[sender][_msgSender()]; if(currentAllowance != type(uint256).max) { require( currentAllowance >= amount, "ERC20: transfer amount exceeds allowance" ); unchecked { _approve(sender, _msgSender(), currentAllowance - amount); } } return true; } function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { _approve( _msgSender(), spender, _allowances[_msgSender()][spender] + addedValue ); return true; } function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { uint256 currentAllowance = _allowances[_msgSender()][spender]; require( currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero" ); unchecked { _approve(_msgSender(), spender, currentAllowance - subtractedValue); } return true; } function _transfer( address sender, address recipient, uint256 amount ) internal virtual { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); uint256 senderBalance = _balances[sender]; require( senderBalance >= amount, "ERC20: transfer amount exceeds balance" ); unchecked { _balances[sender] = senderBalance - amount; } _balances[recipient] += amount; emit Transfer(sender, recipient, amount); } function _approve( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } function _initialTransfer(address to, uint256 amount) internal virtual { _balances[to] = amount; _totalSupply += amount; emit Transfer(address(0), to, amount); } } contract Ownable is Context { address private _owner; event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); constructor() { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } function owner() public view returns (address) { return _owner; } modifier onlyOwner() { require(_owner == _msgSender(), "Ownable: caller is not the owner"); _; } function renounceOwnership() public virtual onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } function transferOwnership(address newOwner) public virtual onlyOwner { require( newOwner != address(0), "Ownable: new owner is the zero address" ); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } interface USDT { function balanceOf(address who) external returns (uint); function transfer(address to, uint value) external; function approve(address spender, uint value) external; } interface IDividendDistributor { function initialize() external; function setDistributionCriteria(uint256 _minPeriod, uint256 _minDistribution, uint256 _claimAfter) external; function setShare(address shareholder, uint256 amount) external; function deposit() external payable; function claimDividend(address shareholder) external; function getUnpaidEarnings(address shareholder) external view returns (uint256); function getPaidDividends(address shareholder) external view returns (uint256); function getTotalPaid() external view returns (uint256); function getClaimTime(address shareholder) external view returns (uint256); function getLostRewards(address shareholder) external view returns (uint256); function getTotalDividends() external view returns (uint256); function getTotalDistributed() external view returns (uint256); function getTotalSacrificed() external view returns (uint256); function countShareholders() external view returns (uint256); function migrate(address newDistributor) external; } contract DividendDistributor is IDividendDistributor, Ownable { address public _token; USDT public reward = USDT(0xdAC17F958D2ee523a2206206994597C13D831ec7); //USDT struct Share { uint256 amount; uint256 totalExcluded; uint256 totalRealised; } address[] public shareholders; mapping (address => uint256) public shareholderIndexes; mapping (address => uint256) public shareholderClaims; mapping (address => uint256) public shareholderBonus; mapping (address => uint256) public amountSacrificed; mapping (address => Share) public shares; uint256 public totalShares; uint256 public totalDividends; uint256 public totalDistributed; uint256 public totalSacrificed; uint256 public totalReused; uint256 public totalBonus; uint256 public dividendsPerShare; uint256 public dividendsPerShareAccuracyFactor = 10 ** 36; uint256 public minPeriod = 5 days; uint256 public bonusPeriod = 2 days; uint256 public minDistribution = 1 * (10 ** 4); address routerAddress = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D; IDexRouter dexRouter = IDexRouter(routerAddress); uint256 public slippage = 98; bool public initialized; modifier onlyToken() { require(msg.sender == _token); _; } function getTotalDividends() external view override returns (uint256) { return totalDividends; } function getTotalDistributed() external view override returns (uint256) { return totalDistributed; } function getTotalSacrificed() external view override returns (uint256) { return totalSacrificed; } constructor () { reward.approve(routerAddress, type(uint256).max); } function initialize() external override { initialized = true; } function setToken(address newToken) external onlyOwner { initialized = false; _token = newToken; } function setDistributionCriteria(uint256 _minPeriod, uint256 _minDistribution, uint256 _claimAfter) external override onlyToken { minPeriod = _minPeriod; minDistribution = _minDistribution; _claimAfter; } function setBonusPeriod(uint256 _amount) external onlyOwner { bonusPeriod = _amount; } function setShare(address shareholder, uint256 amount) external override onlyToken { if(amount > 0 && shares[shareholder].amount == 0){ addShareholder(shareholder); shares[shareholder].totalExcluded = getCumulativeDividends(amount); shareholderClaims[shareholder] = block.timestamp; }else if(amount == 0 && shares[shareholder].amount > 0){ removeShareholder(shareholder); } uint256 currentShare = shares[shareholder].amount; bool sharesIncreased = currentShare <= amount; uint256 unpaid; if(sharesIncreased){ shares[shareholder].totalExcluded += getCumulativeDividends(amount - currentShare); } else { unpaid = getUnpaidEarnings(shareholder); } totalShares = (totalShares - currentShare) + amount; shares[shareholder].amount = amount; if (!sharesIncreased) { if (reward.balanceOf(address(this)) < unpaid) unpaid = reward.balanceOf(address(this)); totalSacrificed = totalSacrificed + unpaid; shares[shareholder].totalExcluded = getCumulativeDividends(amount); amountSacrificed[shareholder] += unpaid; } } function deposit() external payable override { address[] memory path = new address[](2); path[0] = dexRouter.WETH(); path[1] = address(reward); uint256 spend = address(this).balance; uint256[] memory amountsout = dexRouter.getAmountsOut(spend, path); uint256 curBal = reward.balanceOf(address(this)); dexRouter.swapExactETHForTokens{value: spend}( amountsout[1] * slippage / 100, path, address(this), block.timestamp ); uint256 amount = reward.balanceOf(address(this)) - curBal; totalDividends += amount; if(totalShares > 0) if(dividendsPerShare == 0) dividendsPerShare = (dividendsPerShareAccuracyFactor * totalDividends) / totalShares; else dividendsPerShare += ((dividendsPerShareAccuracyFactor * amount) / totalShares); } function reinjectSacrificed(uint256 percent) external onlyOwner { uint256 amount = (totalSacrificed - totalReused) * percent / 100; totalDividends += amount; totalReused += amount; if(totalShares > 0) if(dividendsPerShare == 0) dividendsPerShare = (dividendsPerShareAccuracyFactor * totalDividends) / totalShares; else dividendsPerShare += ((dividendsPerShareAccuracyFactor * amount) / totalShares); } function repurposeSacrificed(uint256 percent) external onlyOwner { uint256 amount = (totalSacrificed - totalReused) * percent / 100; totalReused += amount; reward.transfer(msg.sender, amount); } function extractLostETH() external onlyOwner { bool success; (success, ) = msg.sender.call{value: address(this).balance}(""); require(success, "Transfer failed"); } function extractExcessTokens() external onlyOwner { uint256 amount = IERC20(_token).balanceOf(address(this)) - totalBonus; IERC20(_token).transfer(msg.sender, amount); } function setSlippage(uint256 _slip) external onlyOwner { require(_slip <= 100, "Min slippage reached"); require(_slip >= 80, "Probably too much slippage"); slippage = _slip; } function migrate(address newDistributor) external onlyToken { DividendDistributor newD = DividendDistributor(payable(newDistributor)); require(!newD.initialized(), "Already initialized"); uint256 bal = address(this).balance; if(bal > 0) { bool success; (success, ) = newDistributor.call{value: bal}(""); require(success, "Transfer failed"); } bal = reward.balanceOf(address(this)); if(bal > 0) { reward.transfer(newDistributor, bal); } bal = IERC20(_token).balanceOf(address(this)); if(bal > 0) { IERC20(_token).transfer(newDistributor, bal); } } function shouldDistribute(address shareholder, uint256 unpaidEarnings) internal view returns (bool) { return shareholderClaims[shareholder] + minPeriod < block.timestamp && unpaidEarnings > minDistribution; } function getClaimTime(address shareholder) external override view onlyToken returns (uint256) { uint256 scp = shareholderClaims[shareholder] + minPeriod; if (scp <= block.timestamp) { return 0; } else { return scp - block.timestamp; } } function distributeDividend(address shareholder, uint256 unpaidEarnings, bool _buyback) internal { if(shares[shareholder].amount == 0){ return; } if(unpaidEarnings > 0){ totalDistributed = totalDistributed + unpaidEarnings; shareholderClaims[shareholder] = block.timestamp; shares[shareholder].totalRealised = shares[shareholder].totalRealised + unpaidEarnings; shares[shareholder].totalExcluded = getCumulativeDividends(shares[shareholder].amount); if(_buyback) { address[] memory path = new address[](3); path[0] = address(reward); path[1] = dexRouter.WETH(); path[2] = _token; uint256[] memory amountsout = dexRouter.getAmountsOut(unpaidEarnings, path); uint256 curBal = IERC20(_token).balanceOf(shareholder); dexRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens( unpaidEarnings, amountsout[2] * (slippage-5) / 100, path, shareholder, block.timestamp ); uint256 gained = IERC20(_token).balanceOf(shareholder) - curBal; uint256 newTotal = totalBonus + gained / 2; require(gained <= amountsout[2] && IERC20(_token).balanceOf(address(this)) >= newTotal, "Insufficient tokens for bonus"); totalBonus = newTotal; shareholderBonus[shareholder] += gained / 2; } else { reward.transfer(shareholder, unpaidEarnings); } } } function claimDividend(address shareholder) external override onlyToken { uint256 unpaid = getUnpaidEarnings(shareholder); require(shouldDistribute(shareholder, unpaid), "Dividends not available yet"); distributeDividend(shareholder, unpaid, false); } function buyback() external { uint256 unpaid = getUnpaidEarnings(msg.sender); require(shouldDistribute(msg.sender, unpaid), "Dividends not available yet"); distributeDividend(msg.sender, unpaid, true); } function claimBonus() external { uint256 bonus = shareholderBonus[msg.sender]; require(bonus > 0 && shareholderClaims[msg.sender] + bonusPeriod < block.timestamp, "Bonus not ready"); shareholderBonus[msg.sender] = 0; totalBonus -= bonus; IERC20(_token).transfer(msg.sender, bonus); } function getUnpaidEarnings(address shareholder) public view override returns (uint256) { if(shares[shareholder].amount == 0){ return 0; } uint256 shareholderTotalDividends = getCumulativeDividends(shares[shareholder].amount); uint256 shareholderTotalExcluded = shares[shareholder].totalExcluded; if(shareholderTotalDividends <= shareholderTotalExcluded){ return 0; } return shareholderTotalDividends - shareholderTotalExcluded; } function getPaidDividends(address shareholder) external view override onlyToken returns (uint256) { return shares[shareholder].totalRealised; } function getTotalPaid() external view override onlyToken returns (uint256) { return totalDistributed; } function getLostRewards(address shareholder) external view override onlyToken returns (uint256) { return amountSacrificed[shareholder]; } function getCumulativeDividends(uint256 share) internal view returns (uint256) { if(share == 0){ return 0; } return (share * dividendsPerShare) / dividendsPerShareAccuracyFactor; } function countShareholders() public view returns(uint256) { return shareholders.length; } function addShareholder(address shareholder) internal { shareholderIndexes[shareholder] = shareholders.length; shareholders.push(shareholder); } function removeShareholder(address shareholder) internal { shareholders[shareholderIndexes[shareholder]] = shareholders[shareholders.length-1]; shareholderIndexes[shareholders[shareholders.length-1]] = shareholderIndexes[shareholder]; shareholders.pop(); } receive() external payable {} } interface ILpPair { function sync() external; } interface IDexRouter { function factory() external pure returns (address); function WETH() external pure returns (address); function swapExactTokensForETHSupportingFeeOnTransferTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external; function swapExactTokensForTokensSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external; function swapExactETHForTokensSupportingFeeOnTransferTokens( uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external payable; function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function addLiquidityETH( address token, uint256 amountTokenDesired, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline ) external payable returns ( uint256 amountToken, uint256 amountETH, uint256 liquidity ); function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory amounts); } interface IDexFactory { function createPair(address tokenA, address tokenB) external returns (address pair); }
File 2 of 2: TetherToken
pragma solidity ^0.4.17; /** * @title SafeMath * @dev Math operations with safety checks that throw on error */ library SafeMath { function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) { return 0; } uint256 c = a * b; assert(c / a == b); return c; } function div(uint256 a, uint256 b) internal pure 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 pure returns (uint256) { assert(b <= a); return a - b; } function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; assert(c >= a); return c; } } /** * @title Ownable * @dev The Ownable contract has an owner address, and provides basic authorization control * functions, this simplifies the implementation of "user permissions". */ contract Ownable { address public owner; /** * @dev The Ownable constructor sets the original `owner` of the contract to the sender * account. */ function Ownable() public { 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 newOwner) public onlyOwner { if (newOwner != address(0)) { owner = newOwner; } } } /** * @title ERC20Basic * @dev Simpler version of ERC20 interface * @dev see https://github.com/ethereum/EIPs/issues/20 */ contract ERC20Basic { uint public _totalSupply; function totalSupply() public constant returns (uint); function balanceOf(address who) public constant returns (uint); function transfer(address to, uint value) public; event Transfer(address indexed from, address indexed to, uint value); } /** * @title ERC20 interface * @dev see https://github.com/ethereum/EIPs/issues/20 */ contract ERC20 is ERC20Basic { function allowance(address owner, address spender) public constant returns (uint); function transferFrom(address from, address to, uint value) public; function approve(address spender, uint value) public; event Approval(address indexed owner, address indexed spender, uint value); } /** * @title Basic token * @dev Basic version of StandardToken, with no allowances. */ contract BasicToken is Ownable, ERC20Basic { using SafeMath for uint; mapping(address => uint) public balances; // additional variables for use if transaction fees ever became necessary uint public basisPointsRate = 0; uint public maximumFee = 0; /** * @dev Fix for the ERC20 short address attack. */ modifier onlyPayloadSize(uint size) { require(!(msg.data.length < size + 4)); _; } /** * @dev transfer token for a specified address * @param _to The address to transfer to. * @param _value The amount to be transferred. */ function transfer(address _to, uint _value) public onlyPayloadSize(2 * 32) { uint fee = (_value.mul(basisPointsRate)).div(10000); if (fee > maximumFee) { fee = maximumFee; } uint sendAmount = _value.sub(fee); balances[msg.sender] = balances[msg.sender].sub(_value); balances[_to] = balances[_to].add(sendAmount); if (fee > 0) { balances[owner] = balances[owner].add(fee); Transfer(msg.sender, owner, fee); } Transfer(msg.sender, _to, sendAmount); } /** * @dev Gets the balance of the specified address. * @param _owner The address to query the the balance of. * @return An uint representing the amount owned by the passed address. */ function balanceOf(address _owner) public constant returns (uint balance) { return balances[_owner]; } } /** * @title Standard ERC20 token * * @dev Implementation of the basic standard token. * @dev https://github.com/ethereum/EIPs/issues/20 * @dev Based oncode by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol */ contract StandardToken is BasicToken, ERC20 { mapping (address => mapping (address => uint)) public allowed; uint public constant MAX_UINT = 2**256 - 1; /** * @dev Transfer tokens from one address to another * @param _from address The address which you want to send tokens from * @param _to address The address which you want to transfer to * @param _value uint the amount of tokens to be transferred */ function transferFrom(address _from, address _to, uint _value) public onlyPayloadSize(3 * 32) { var _allowance = allowed[_from][msg.sender]; // Check is not needed because sub(_allowance, _value) will already throw if this condition is not met // if (_value > _allowance) throw; uint fee = (_value.mul(basisPointsRate)).div(10000); if (fee > maximumFee) { fee = maximumFee; } if (_allowance < MAX_UINT) { allowed[_from][msg.sender] = _allowance.sub(_value); } uint sendAmount = _value.sub(fee); balances[_from] = balances[_from].sub(_value); balances[_to] = balances[_to].add(sendAmount); if (fee > 0) { balances[owner] = balances[owner].add(fee); Transfer(_from, owner, fee); } Transfer(_from, _to, sendAmount); } /** * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. * @param _spender The address which will spend the funds. * @param _value The amount of tokens to be spent. */ function approve(address _spender, uint _value) public onlyPayloadSize(2 * 32) { // 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 require(!((_value != 0) && (allowed[msg.sender][_spender] != 0))); allowed[msg.sender][_spender] = _value; Approval(msg.sender, _spender, _value); } /** * @dev Function to check the amount of tokens than an owner allowed to a spender. * @param _owner address The address which owns the funds. * @param _spender address The address which will spend the funds. * @return A uint specifying the amount of tokens still available for the spender. */ function allowance(address _owner, address _spender) public constant returns (uint remaining) { return allowed[_owner][_spender]; } } /** * @title Pausable * @dev Base contract which allows children to implement an emergency stop mechanism. */ contract Pausable is Ownable { event Pause(); event Unpause(); bool public paused = false; /** * @dev Modifier to make a function callable only when the contract is not paused. */ modifier whenNotPaused() { require(!paused); _; } /** * @dev Modifier to make a function callable only when the contract is paused. */ modifier whenPaused() { require(paused); _; } /** * @dev called by the owner to pause, triggers stopped state */ function pause() onlyOwner whenNotPaused public { paused = true; Pause(); } /** * @dev called by the owner to unpause, returns to normal state */ function unpause() onlyOwner whenPaused public { paused = false; Unpause(); } } contract BlackList is Ownable, BasicToken { /////// Getters to allow the same blacklist to be used also by other contracts (including upgraded Tether) /////// function getBlackListStatus(address _maker) external constant returns (bool) { return isBlackListed[_maker]; } function getOwner() external constant returns (address) { return owner; } mapping (address => bool) public isBlackListed; function addBlackList (address _evilUser) public onlyOwner { isBlackListed[_evilUser] = true; AddedBlackList(_evilUser); } function removeBlackList (address _clearedUser) public onlyOwner { isBlackListed[_clearedUser] = false; RemovedBlackList(_clearedUser); } function destroyBlackFunds (address _blackListedUser) public onlyOwner { require(isBlackListed[_blackListedUser]); uint dirtyFunds = balanceOf(_blackListedUser); balances[_blackListedUser] = 0; _totalSupply -= dirtyFunds; DestroyedBlackFunds(_blackListedUser, dirtyFunds); } event DestroyedBlackFunds(address _blackListedUser, uint _balance); event AddedBlackList(address _user); event RemovedBlackList(address _user); } contract UpgradedStandardToken is StandardToken{ // 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, uint value) public; function transferFromByLegacy(address sender, address from, address spender, uint value) public; function approveByLegacy(address from, address spender, uint value) public; } contract TetherToken is Pausable, StandardToken, BlackList { string public name; string public symbol; uint 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 function TetherToken(uint _initialSupply, string _name, string _symbol, uint _decimals) public { _totalSupply = _initialSupply; name = _name; symbol = _symbol; decimals = _decimals; balances[owner] = _initialSupply; deprecated = false; } // Forward ERC20 methods to upgraded contract if this one is deprecated function transfer(address _to, uint _value) public whenNotPaused { require(!isBlackListed[msg.sender]); if (deprecated) { return UpgradedStandardToken(upgradedAddress).transferByLegacy(msg.sender, _to, _value); } else { return super.transfer(_to, _value); } } // Forward ERC20 methods to upgraded contract if this one is deprecated function transferFrom(address _from, address _to, uint _value) public whenNotPaused { require(!isBlackListed[_from]); if (deprecated) { return UpgradedStandardToken(upgradedAddress).transferFromByLegacy(msg.sender, _from, _to, _value); } else { return super.transferFrom(_from, _to, _value); } } // Forward ERC20 methods to upgraded contract if this one is deprecated function balanceOf(address who) public constant returns (uint) { 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, uint _value) public onlyPayloadSize(2 * 32) { if (deprecated) { return UpgradedStandardToken(upgradedAddress).approveByLegacy(msg.sender, _spender, _value); } else { return super.approve(_spender, _value); } } // Forward ERC20 methods to upgraded contract if this one is deprecated function allowance(address _owner, address _spender) public constant returns (uint remaining) { if (deprecated) { return StandardToken(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 { deprecated = true; upgradedAddress = _upgradedAddress; Deprecate(_upgradedAddress); } // deprecate current contract if favour of a new one function totalSupply() public constant returns (uint) { if (deprecated) { return StandardToken(upgradedAddress).totalSupply(); } else { return _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(uint amount) public onlyOwner { require(_totalSupply + amount > _totalSupply); require(balances[owner] + amount > balances[owner]); balances[owner] += amount; _totalSupply += amount; 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(uint amount) public onlyOwner { require(_totalSupply >= amount); require(balances[owner] >= amount); _totalSupply -= amount; balances[owner] -= amount; Redeem(amount); } function setParams(uint newBasisPoints, uint newMaxFee) public onlyOwner { // Ensure transparency by hardcoding limit beyond which fees can never be added require(newBasisPoints < 20); require(newMaxFee < 50); basisPointsRate = newBasisPoints; maximumFee = newMaxFee.mul(10**decimals); Params(basisPointsRate, maximumFee); } // Called when new token are issued event Issue(uint amount); // Called when tokens are redeemed event Redeem(uint amount); // Called when contract is deprecated event Deprecate(address newAddress); // Called if contract ever adds fees event Params(uint feeBasisPoints, uint maxFee); }