ETH Price: $1,969.59 (-1.18%)

Transaction Decoder

Block:
21176941 at Nov-13-2024 06:20:47 AM +UTC
Transaction Fee:
0.00200752293849745 ETH $3.95
Gas Used:
122,870 Gas / 16.338593135 Gwei

Emitted Events:

379 WBTC.Transfer( from=0x56534741CD8B152df6d48AdF7ac51f75169A83b2, to=[Receiver] 0x5050e08626c499411b5d0e0b5af0e83d3fd82edf, value=17602660 )
380 TetherToken.Transfer( from=[Receiver] 0x5050e08626c499411b5d0e0b5af0e83d3fd82edf, to=0x56534741CD8B152df6d48AdF7ac51f75169A83b2, value=15241334171 )
381 0x56534741cd8b152df6d48adf7ac51f75169a83b2.0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67( 0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67, 0x0000000000000000000000005050e08626c499411b5d0e0b5af0e83d3fd82edf, 0x0000000000000000000000005050e08626c499411b5d0e0b5af0e83d3fd82edf, fffffffffffffffffffffffffffffffffffffffffffffffffffffffffef3679c, 000000000000000000000000000000000000000000000000000000038c744d9b, 000000000000000000000000000000000000001d6c3ddf3a8825415092187b4e, 0000000000000000000000000000000000000000000000000000017319198d56, 0000000000000000000000000000000000000000000000000000000000010836 )

Account State Difference:

  Address   Before After State Difference Code
0x2260FAC5...93bc2C599
0x2528b985...CC336b057
4.205459685021584984 Eth
Nonce: 22904
4.203452162070737326 Eth
Nonce: 22905
0.002007522950847658
0x5050e086...d3fD82EDF
(MEV Bot: 0x50...EDF)
5.788141619093876055 Eth5.788107930634869812 Eth0.000033688459006243
0x56534741...5169A83b2
(Uniswap V3: WBTC-USDT 2)
(beaverbuild)
18.827185073328241149 Eth18.8272187617995976 Eth0.000033688471356451
0xdAC17F95...13D831ec7

Execution Trace

ETH 0.000000000012350208 MEV Bot: 0x50...EDF.78e111f6( )
  • ETH 0.000000000012350208 0x63c973112115e33293fca39a08677efb3dde01a2.f4ff5295( )
    • Uniswap V3: WBTC-USDT 2.128acb08( )
      • WBTC.transfer( _to=0x5050e08626c499411B5D0E0b5AF0E83d3fD82EDF, _value=17602660 ) => ( True )
      • TetherToken.balanceOf( who=0x56534741CD8B152df6d48AdF7ac51f75169A83b2 ) => ( 5016066118524 )
      • MEV Bot: 0x50...EDF.fa461e33( )
        • TetherToken.transfer( _to=0x56534741CD8B152df6d48AdF7ac51f75169A83b2, _value=15241334171 )
        • TetherToken.balanceOf( who=0x56534741CD8B152df6d48AdF7ac51f75169A83b2 ) => ( 5031307452695 )
        • ETH 0.000033688471356451 beaverbuild.CALL( )
          File 1 of 2: WBTC
          pragma solidity 0.4.24;
          
          // File: openzeppelin-solidity/contracts/token/ERC20/ERC20Basic.sol
          
          /**
           * @title ERC20Basic
           * @dev Simpler version of ERC20 interface
           * See https://github.com/ethereum/EIPs/issues/179
           */
          contract ERC20Basic {
            function totalSupply() public view returns (uint256);
            function balanceOf(address _who) public view returns (uint256);
            function transfer(address _to, uint256 _value) public returns (bool);
            event Transfer(address indexed from, address indexed to, uint256 value);
          }
          
          // File: openzeppelin-solidity/contracts/math/SafeMath.sol
          
          /**
           * @title SafeMath
           * @dev Math operations with safety checks that throw on error
           */
          library SafeMath {
          
            /**
            * @dev Multiplies two numbers, throws on overflow.
            */
            function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
              // Gas optimization: this is cheaper than asserting 'a' not being zero, but the
              // benefit is lost if 'b' is also tested.
              // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
              if (_a == 0) {
                return 0;
              }
          
              c = _a * _b;
              assert(c / _a == _b);
              return c;
            }
          
            /**
            * @dev Integer division of two numbers, truncating the quotient.
            */
            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 _a / _b;
            }
          
            /**
            * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
            */
            function sub(uint256 _a, uint256 _b) internal pure returns (uint256) {
              assert(_b <= _a);
              return _a - _b;
            }
          
            /**
            * @dev Adds two numbers, throws on overflow.
            */
            function add(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
              c = _a + _b;
              assert(c >= _a);
              return c;
            }
          }
          
          // File: openzeppelin-solidity/contracts/token/ERC20/BasicToken.sol
          
          /**
           * @title Basic token
           * @dev Basic version of StandardToken, with no allowances.
           */
          contract BasicToken is ERC20Basic {
            using SafeMath for uint256;
          
            mapping(address => uint256) internal balances;
          
            uint256 internal totalSupply_;
          
            /**
            * @dev Total number of tokens in existence
            */
            function totalSupply() public view returns (uint256) {
              return totalSupply_;
            }
          
            /**
            * @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, uint256 _value) public returns (bool) {
              require(_value <= balances[msg.sender]);
              require(_to != address(0));
          
              balances[msg.sender] = balances[msg.sender].sub(_value);
              balances[_to] = balances[_to].add(_value);
              emit Transfer(msg.sender, _to, _value);
              return true;
            }
          
            /**
            * @dev Gets the balance of the specified address.
            * @param _owner The address to query the the balance of.
            * @return An uint256 representing the amount owned by the passed address.
            */
            function balanceOf(address _owner) public view returns (uint256) {
              return balances[_owner];
            }
          
          }
          
          // File: openzeppelin-solidity/contracts/token/ERC20/ERC20.sol
          
          /**
           * @title ERC20 interface
           * @dev see https://github.com/ethereum/EIPs/issues/20
           */
          contract ERC20 is ERC20Basic {
            function allowance(address _owner, address _spender)
              public view returns (uint256);
          
            function transferFrom(address _from, address _to, uint256 _value)
              public returns (bool);
          
            function approve(address _spender, uint256 _value) public returns (bool);
            event Approval(
              address indexed owner,
              address indexed spender,
              uint256 value
            );
          }
          
          // File: openzeppelin-solidity/contracts/token/ERC20/StandardToken.sol
          
          /**
           * @title Standard ERC20 token
           *
           * @dev Implementation of the basic standard token.
           * https://github.com/ethereum/EIPs/issues/20
           * Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
           */
          contract StandardToken is ERC20, BasicToken {
          
            mapping (address => mapping (address => uint256)) internal allowed;
          
          
            /**
             * @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 uint256 the amount of tokens to be transferred
             */
            function transferFrom(
              address _from,
              address _to,
              uint256 _value
            )
              public
              returns (bool)
            {
              require(_value <= balances[_from]);
              require(_value <= allowed[_from][msg.sender]);
              require(_to != address(0));
          
              balances[_from] = balances[_from].sub(_value);
              balances[_to] = balances[_to].add(_value);
              allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
              emit Transfer(_from, _to, _value);
              return true;
            }
          
            /**
             * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
             * 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
             * @param _spender The address which will spend the funds.
             * @param _value The amount of tokens to be spent.
             */
            function approve(address _spender, uint256 _value) public returns (bool) {
              allowed[msg.sender][_spender] = _value;
              emit Approval(msg.sender, _spender, _value);
              return true;
            }
          
            /**
             * @dev Function to check the amount of tokens that 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 uint256 specifying the amount of tokens still available for the spender.
             */
            function allowance(
              address _owner,
              address _spender
             )
              public
              view
              returns (uint256)
            {
              return allowed[_owner][_spender];
            }
          
            /**
             * @dev Increase the amount of tokens that an owner allowed to a spender.
             * approve should be called when allowed[_spender] == 0. To increment
             * allowed value is better to use this function to avoid 2 calls (and wait until
             * the first transaction is mined)
             * From MonolithDAO Token.sol
             * @param _spender The address which will spend the funds.
             * @param _addedValue The amount of tokens to increase the allowance by.
             */
            function increaseApproval(
              address _spender,
              uint256 _addedValue
            )
              public
              returns (bool)
            {
              allowed[msg.sender][_spender] = (
                allowed[msg.sender][_spender].add(_addedValue));
              emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
              return true;
            }
          
            /**
             * @dev Decrease the amount of tokens that an owner allowed to a spender.
             * approve should be called when allowed[_spender] == 0. To decrement
             * allowed value is better to use this function to avoid 2 calls (and wait until
             * the first transaction is mined)
             * From MonolithDAO Token.sol
             * @param _spender The address which will spend the funds.
             * @param _subtractedValue The amount of tokens to decrease the allowance by.
             */
            function decreaseApproval(
              address _spender,
              uint256 _subtractedValue
            )
              public
              returns (bool)
            {
              uint256 oldValue = allowed[msg.sender][_spender];
              if (_subtractedValue >= oldValue) {
                allowed[msg.sender][_spender] = 0;
              } else {
                allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue);
              }
              emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
              return true;
            }
          
          }
          
          // File: openzeppelin-solidity/contracts/token/ERC20/DetailedERC20.sol
          
          /**
           * @title DetailedERC20 token
           * @dev The decimals are only for visualization purposes.
           * All the operations are done using the smallest and indivisible token unit,
           * just as on Ethereum all the operations are done in wei.
           */
          contract DetailedERC20 is ERC20 {
            string public name;
            string public symbol;
            uint8 public decimals;
          
            constructor(string _name, string _symbol, uint8 _decimals) public {
              name = _name;
              symbol = _symbol;
              decimals = _decimals;
            }
          }
          
          // File: openzeppelin-solidity/contracts/ownership/Ownable.sol
          
          /**
           * @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;
          
          
            event OwnershipRenounced(address indexed previousOwner);
            event OwnershipTransferred(
              address indexed previousOwner,
              address indexed newOwner
            );
          
          
            /**
             * @dev The Ownable constructor sets the original `owner` of the contract to the sender
             * account.
             */
            constructor() 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 relinquish control of the contract.
             * @notice Renouncing to ownership will leave the contract without an owner.
             * It will not be possible to call the functions with the `onlyOwner`
             * modifier anymore.
             */
            function renounceOwnership() public onlyOwner {
              emit OwnershipRenounced(owner);
              owner = address(0);
            }
          
            /**
             * @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 {
              _transferOwnership(_newOwner);
            }
          
            /**
             * @dev Transfers control of the contract to a newOwner.
             * @param _newOwner The address to transfer ownership to.
             */
            function _transferOwnership(address _newOwner) internal {
              require(_newOwner != address(0));
              emit OwnershipTransferred(owner, _newOwner);
              owner = _newOwner;
            }
          }
          
          // File: openzeppelin-solidity/contracts/token/ERC20/MintableToken.sol
          
          /**
           * @title Mintable token
           * @dev Simple ERC20 Token example, with mintable token creation
           * Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol
           */
          contract MintableToken is StandardToken, Ownable {
            event Mint(address indexed to, uint256 amount);
            event MintFinished();
          
            bool public mintingFinished = false;
          
          
            modifier canMint() {
              require(!mintingFinished);
              _;
            }
          
            modifier hasMintPermission() {
              require(msg.sender == owner);
              _;
            }
          
            /**
             * @dev Function to mint tokens
             * @param _to The address that will receive the minted tokens.
             * @param _amount The amount of tokens to mint.
             * @return A boolean that indicates if the operation was successful.
             */
            function mint(
              address _to,
              uint256 _amount
            )
              public
              hasMintPermission
              canMint
              returns (bool)
            {
              totalSupply_ = totalSupply_.add(_amount);
              balances[_to] = balances[_to].add(_amount);
              emit Mint(_to, _amount);
              emit Transfer(address(0), _to, _amount);
              return true;
            }
          
            /**
             * @dev Function to stop minting new tokens.
             * @return True if the operation was successful.
             */
            function finishMinting() public onlyOwner canMint returns (bool) {
              mintingFinished = true;
              emit MintFinished();
              return true;
            }
          }
          
          // File: openzeppelin-solidity/contracts/token/ERC20/BurnableToken.sol
          
          /**
           * @title Burnable Token
           * @dev Token that can be irreversibly burned (destroyed).
           */
          contract BurnableToken is BasicToken {
          
            event Burn(address indexed burner, uint256 value);
          
            /**
             * @dev Burns a specific amount of tokens.
             * @param _value The amount of token to be burned.
             */
            function burn(uint256 _value) public {
              _burn(msg.sender, _value);
            }
          
            function _burn(address _who, uint256 _value) internal {
              require(_value <= balances[_who]);
              // no need to require value <= totalSupply, since that would imply the
              // sender's balance is greater than the totalSupply, which *should* be an assertion failure
          
              balances[_who] = balances[_who].sub(_value);
              totalSupply_ = totalSupply_.sub(_value);
              emit Burn(_who, _value);
              emit Transfer(_who, address(0), _value);
            }
          }
          
          // File: openzeppelin-solidity/contracts/lifecycle/Pausable.sol
          
          /**
           * @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() public onlyOwner whenNotPaused {
              paused = true;
              emit Pause();
            }
          
            /**
             * @dev called by the owner to unpause, returns to normal state
             */
            function unpause() public onlyOwner whenPaused {
              paused = false;
              emit Unpause();
            }
          }
          
          // File: openzeppelin-solidity/contracts/token/ERC20/PausableToken.sol
          
          /**
           * @title Pausable token
           * @dev StandardToken modified with pausable transfers.
           **/
          contract PausableToken is StandardToken, Pausable {
          
            function transfer(
              address _to,
              uint256 _value
            )
              public
              whenNotPaused
              returns (bool)
            {
              return super.transfer(_to, _value);
            }
          
            function transferFrom(
              address _from,
              address _to,
              uint256 _value
            )
              public
              whenNotPaused
              returns (bool)
            {
              return super.transferFrom(_from, _to, _value);
            }
          
            function approve(
              address _spender,
              uint256 _value
            )
              public
              whenNotPaused
              returns (bool)
            {
              return super.approve(_spender, _value);
            }
          
            function increaseApproval(
              address _spender,
              uint _addedValue
            )
              public
              whenNotPaused
              returns (bool success)
            {
              return super.increaseApproval(_spender, _addedValue);
            }
          
            function decreaseApproval(
              address _spender,
              uint _subtractedValue
            )
              public
              whenNotPaused
              returns (bool success)
            {
              return super.decreaseApproval(_spender, _subtractedValue);
            }
          }
          
          // File: openzeppelin-solidity/contracts/ownership/Claimable.sol
          
          /**
           * @title Claimable
           * @dev Extension for the Ownable contract, where the ownership needs to be claimed.
           * This allows the new owner to accept the transfer.
           */
          contract Claimable is Ownable {
            address public pendingOwner;
          
            /**
             * @dev Modifier throws if called by any account other than the pendingOwner.
             */
            modifier onlyPendingOwner() {
              require(msg.sender == pendingOwner);
              _;
            }
          
            /**
             * @dev Allows the current owner to set the pendingOwner address.
             * @param newOwner The address to transfer ownership to.
             */
            function transferOwnership(address newOwner) public onlyOwner {
              pendingOwner = newOwner;
            }
          
            /**
             * @dev Allows the pendingOwner address to finalize the transfer.
             */
            function claimOwnership() public onlyPendingOwner {
              emit OwnershipTransferred(owner, pendingOwner);
              owner = pendingOwner;
              pendingOwner = address(0);
            }
          }
          
          // File: openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol
          
          /**
           * @title SafeERC20
           * @dev Wrappers around ERC20 operations that throw on failure.
           * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract,
           * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
           */
          library SafeERC20 {
            function safeTransfer(
              ERC20Basic _token,
              address _to,
              uint256 _value
            )
              internal
            {
              require(_token.transfer(_to, _value));
            }
          
            function safeTransferFrom(
              ERC20 _token,
              address _from,
              address _to,
              uint256 _value
            )
              internal
            {
              require(_token.transferFrom(_from, _to, _value));
            }
          
            function safeApprove(
              ERC20 _token,
              address _spender,
              uint256 _value
            )
              internal
            {
              require(_token.approve(_spender, _value));
            }
          }
          
          // File: openzeppelin-solidity/contracts/ownership/CanReclaimToken.sol
          
          /**
           * @title Contracts that should be able to recover tokens
           * @author SylTi
           * @dev This allow a contract to recover any ERC20 token received in a contract by transferring the balance to the contract owner.
           * This will prevent any accidental loss of tokens.
           */
          contract CanReclaimToken is Ownable {
            using SafeERC20 for ERC20Basic;
          
            /**
             * @dev Reclaim all ERC20Basic compatible tokens
             * @param _token ERC20Basic The address of the token contract
             */
            function reclaimToken(ERC20Basic _token) external onlyOwner {
              uint256 balance = _token.balanceOf(this);
              _token.safeTransfer(owner, balance);
            }
          
          }
          
          // File: contracts/utils/OwnableContract.sol
          
          // empty block is used as this contract just inherits others.
          contract OwnableContract is CanReclaimToken, Claimable { } /* solhint-disable-line no-empty-blocks */
          
          // File: contracts/token/WBTC.sol
          
          contract WBTC is StandardToken, DetailedERC20("Wrapped BTC", "WBTC", 8),
              MintableToken, BurnableToken, PausableToken, OwnableContract {
          
              function burn(uint value) public onlyOwner {
                  super.burn(value);
              }
          
              function finishMinting() public onlyOwner returns (bool) {
                  return false;
              }
          
              function renounceOwnership() public onlyOwner {
                  revert("renouncing ownership is blocked");
              }
          }

          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);
          }