ETH Price: $2,403.81 (+7.21%)

Transaction Decoder

Block:
10693628 at Aug-19-2020 11:45:33 PM +UTC
Transaction Fee:
0.012698846 ETH $30.53
Gas Used:
147,661 Gas / 86 Gwei

Emitted Events:

191 LinkToken.0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef( 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, 0x00000000000000000000000073282a63f0e3d7e9604575420f777361eca3c86a, 0x00000000000000000000000078914f639e159d65067e3aa9db99b013aaf6107e, 000000000000000000000000000000000000000000000000000000003b9aca00 )
192 AdminUpgradeabilityProxy.0xd6d4f5681c246c9f42c203e287975af1601f8df8035a9251f79aab5c8f09e2f8( 0xd6d4f5681c246c9f42c203e287975af1601f8df8035a9251f79aab5c8f09e2f8, 0000000000000000000000003411088783b3bc94f1a916a1db2d8c6dfa4ca102, 00000000000000000000000078914f639e159d65067e3aa9db99b013aaf6107e, 000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca, 0000000000000000000000000000000000000000000000000000000000000000, 000000000000000000000000000000000000000000000000000000003b9aca00, 0000000000000000000000000000000000000000000000000de0b6b3a7640000 )

Account State Difference:

  Address   Before After State Difference Code
0x34110887...dfa4CA102 0.332203831 Eth1.330203831 Eth0.998
0x51491077...4EcF986CA
(Miner: 0x6eb...31a)
171.193455213360331834 Eth171.206154059360331834 Eth0.012698846
0x73282A63...1ecA3C86A
(Bounce Finance: Bounce Swap Proxy)
0x78914f63...3aaf6107E
18.933517657469846688 Eth
Nonce: 3658
17.920818811469846688 Eth
Nonce: 3659
1.012698846
0x98945BC6...c2431c48E 21.528271309727185962 Eth21.530271309727185962 Eth0.002

Execution Trace

ETH 1 AdminUpgradeabilityProxy.ebeee70c( )
  • ETH 1 0xa557d4d359fafeac4f66d82a4ebeb97a6ce7935f.ebeee70c( )
    • LinkToken.transfer( _to=0x78914f639e159D65067e3aA9DB99B013aaf6107E, _value=1000000000 ) => ( success=True )
    • ETH 0.998 0x3411088783b3bc94f1a916a1db2d8c6dfa4ca102.CALL( )
    • ETH 0.002 AdminUpgradeabilityProxy.CALL( )
      • ETH 0.002 0x9f782f47ea010b333c0b86c17cff248bdbfae2ed.DELEGATECALL( )
        File 1 of 3: AdminUpgradeabilityProxy
        // File: @openzeppelin/upgrades/contracts/upgradeability/Proxy.sol
        
        pragma solidity ^0.5.0;
        
        /**
         * @title Proxy
         * @dev Implements delegation of calls to other contracts, with proper
         * forwarding of return values and bubbling of failures.
         * It defines a fallback function that delegates all calls to the address
         * returned by the abstract _implementation() internal function.
         */
        contract Proxy {
          /**
           * @dev Fallback function.
           * Implemented entirely in `_fallback`.
           */
          function () payable external {
            _fallback();
          }
        
          /**
           * @return The Address of the implementation.
           */
          function _implementation() internal view returns (address);
        
          /**
           * @dev Delegates execution to an implementation contract.
           * This is a low level function that doesn't return to its internal call site.
           * It will return to the external caller whatever the implementation returns.
           * @param implementation Address to delegate.
           */
          function _delegate(address implementation) internal {
            assembly {
              // Copy msg.data. We take full control of memory in this inline assembly
              // block because it will not return to Solidity code. We overwrite the
              // Solidity scratch pad at memory position 0.
              calldatacopy(0, 0, calldatasize)
        
              // Call the implementation.
              // out and outsize are 0 because we don't know the size yet.
              let result := delegatecall(gas, implementation, 0, calldatasize, 0, 0)
        
              // Copy the returned data.
              returndatacopy(0, 0, returndatasize)
        
              switch result
              // delegatecall returns 0 on error.
              case 0 { revert(0, returndatasize) }
              default { return(0, returndatasize) }
            }
          }
        
          /**
           * @dev Function that is run as the first thing in the fallback function.
           * Can be redefined in derived contracts to add functionality.
           * Redefinitions must call super._willFallback().
           */
          function _willFallback() internal {
          }
        
          /**
           * @dev fallback implementation.
           * Extracted to enable manual triggering.
           */
          function _fallback() internal {
            _willFallback();
            _delegate(_implementation());
          }
        }
        
        // File: @openzeppelin/upgrades/contracts/utils/Address.sol
        
        pragma solidity ^0.5.0;
        
        /**
         * Utility library of inline functions on addresses
         *
         * Source https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-solidity/v2.1.3/contracts/utils/Address.sol
         * This contract is copied here and renamed from the original to avoid clashes in the compiled artifacts
         * when the user imports a zos-lib contract (that transitively causes this contract to be compiled and added to the
         * build/artifacts folder) as well as the vanilla Address implementation from an openzeppelin version.
         */
        library OpenZeppelinUpgradesAddress {
            /**
             * Returns whether the target address is a contract
             * @dev This function will return false if invoked during the constructor of a contract,
             * as the code is not actually created until after the constructor finishes.
             * @param account address of the account to check
             * @return whether the target address is a contract
             */
            function isContract(address account) internal view returns (bool) {
                uint256 size;
                // XXX Currently there is no better way to check if there is a contract in an address
                // than to check the size of the code at that address.
                // See https://ethereum.stackexchange.com/a/14016/36603
                // for more details about how this works.
                // TODO Check this again before the Serenity release, because all addresses will be
                // contracts then.
                // solhint-disable-next-line no-inline-assembly
                assembly { size := extcodesize(account) }
                return size > 0;
            }
        }
        
        // File: @openzeppelin/upgrades/contracts/upgradeability/BaseUpgradeabilityProxy.sol
        
        pragma solidity ^0.5.0;
        
        
        
        /**
         * @title BaseUpgradeabilityProxy
         * @dev This contract implements a proxy that allows to change the
         * implementation address to which it will delegate.
         * Such a change is called an implementation upgrade.
         */
        contract BaseUpgradeabilityProxy is Proxy {
          /**
           * @dev Emitted when the implementation is upgraded.
           * @param implementation Address of the new implementation.
           */
          event Upgraded(address indexed implementation);
        
          /**
           * @dev Storage slot with the address of the current implementation.
           * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
           * validated in the constructor.
           */
          bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
        
          /**
           * @dev Returns the current implementation.
           * @return Address of the current implementation
           */
          function _implementation() internal view returns (address impl) {
            bytes32 slot = IMPLEMENTATION_SLOT;
            assembly {
              impl := sload(slot)
            }
          }
        
          /**
           * @dev Upgrades the proxy to a new implementation.
           * @param newImplementation Address of the new implementation.
           */
          function _upgradeTo(address newImplementation) internal {
            _setImplementation(newImplementation);
            emit Upgraded(newImplementation);
          }
        
          /**
           * @dev Sets the implementation address of the proxy.
           * @param newImplementation Address of the new implementation.
           */
          function _setImplementation(address newImplementation) internal {
            require(OpenZeppelinUpgradesAddress.isContract(newImplementation), "Cannot set a proxy implementation to a non-contract address");
        
            bytes32 slot = IMPLEMENTATION_SLOT;
        
            assembly {
              sstore(slot, newImplementation)
            }
          }
        }
        
        // File: @openzeppelin/upgrades/contracts/upgradeability/UpgradeabilityProxy.sol
        
        pragma solidity ^0.5.0;
        
        
        /**
         * @title UpgradeabilityProxy
         * @dev Extends BaseUpgradeabilityProxy with a constructor for initializing
         * implementation and init data.
         */
        contract UpgradeabilityProxy is BaseUpgradeabilityProxy {
          /**
           * @dev Contract constructor.
           * @param _logic Address of the initial implementation.
           * @param _data Data to send as msg.data to the implementation to initialize the proxied contract.
           * It should include the signature and the parameters of the function to be called, as described in
           * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.
           * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped.
           */
          constructor(address _logic, bytes memory _data) public payable {
            assert(IMPLEMENTATION_SLOT == bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1));
            _setImplementation(_logic);
            if(_data.length > 0) {
              (bool success,) = _logic.delegatecall(_data);
              require(success);
            }
          }  
        }
        
        // File: @openzeppelin/upgrades/contracts/upgradeability/BaseAdminUpgradeabilityProxy.sol
        
        pragma solidity ^0.5.0;
        
        
        /**
         * @title BaseAdminUpgradeabilityProxy
         * @dev This contract combines an upgradeability proxy with an authorization
         * mechanism for administrative tasks.
         * All external functions in this contract must be guarded by the
         * `ifAdmin` modifier. See ethereum/solidity#3864 for a Solidity
         * feature proposal that would enable this to be done automatically.
         */
        contract BaseAdminUpgradeabilityProxy is BaseUpgradeabilityProxy {
          /**
           * @dev Emitted when the administration has been transferred.
           * @param previousAdmin Address of the previous admin.
           * @param newAdmin Address of the new admin.
           */
          event AdminChanged(address previousAdmin, address newAdmin);
        
          /**
           * @dev Storage slot with the admin of the contract.
           * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
           * validated in the constructor.
           */
        
          bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
        
          /**
           * @dev Modifier to check whether the `msg.sender` is the admin.
           * If it is, it will run the function. Otherwise, it will delegate the call
           * to the implementation.
           */
          modifier ifAdmin() {
            if (msg.sender == _admin()) {
              _;
            } else {
              _fallback();
            }
          }
        
          /**
           * @return The address of the proxy admin.
           */
          function admin() external ifAdmin returns (address) {
            return _admin();
          }
        
          /**
           * @return The address of the implementation.
           */
          function implementation() external ifAdmin returns (address) {
            return _implementation();
          }
        
          /**
           * @dev Changes the admin of the proxy.
           * Only the current admin can call this function.
           * @param newAdmin Address to transfer proxy administration to.
           */
          function changeAdmin(address newAdmin) external ifAdmin {
            require(newAdmin != address(0), "Cannot change the admin of a proxy to the zero address");
            emit AdminChanged(_admin(), newAdmin);
            _setAdmin(newAdmin);
          }
        
          /**
           * @dev Upgrade the backing implementation of the proxy.
           * Only the admin can call this function.
           * @param newImplementation Address of the new implementation.
           */
          function upgradeTo(address newImplementation) external ifAdmin {
            _upgradeTo(newImplementation);
          }
        
          /**
           * @dev Upgrade the backing implementation of the proxy and call a function
           * on the new implementation.
           * This is useful to initialize the proxied contract.
           * @param newImplementation Address of the new implementation.
           * @param data Data to send as msg.data in the low level call.
           * It should include the signature and the parameters of the function to be called, as described in
           * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.
           */
          function upgradeToAndCall(address newImplementation, bytes calldata data) payable external ifAdmin {
            _upgradeTo(newImplementation);
            (bool success,) = newImplementation.delegatecall(data);
            require(success);
          }
        
          /**
           * @return The admin slot.
           */
          function _admin() internal view returns (address adm) {
            bytes32 slot = ADMIN_SLOT;
            assembly {
              adm := sload(slot)
            }
          }
        
          /**
           * @dev Sets the address of the proxy admin.
           * @param newAdmin Address of the new proxy admin.
           */
          function _setAdmin(address newAdmin) internal {
            bytes32 slot = ADMIN_SLOT;
        
            assembly {
              sstore(slot, newAdmin)
            }
          }
        
          /**
           * @dev Only fall back when the sender is not the admin.
           */
          function _willFallback() internal {
            require(msg.sender != _admin(), "Cannot call fallback function from the proxy admin");
            super._willFallback();
          }
        }
        
        // File: @openzeppelin/upgrades/contracts/upgradeability/AdminUpgradeabilityProxy.sol
        
        pragma solidity ^0.5.0;
        
        
        /**
         * @title AdminUpgradeabilityProxy
         * @dev Extends from BaseAdminUpgradeabilityProxy with a constructor for 
         * initializing the implementation, admin, and init data.
         */
        contract AdminUpgradeabilityProxy is BaseAdminUpgradeabilityProxy, UpgradeabilityProxy {
          /**
           * Contract constructor.
           * @param _logic address of the initial implementation.
           * @param _admin Address of the proxy administrator.
           * @param _data Data to send as msg.data to the implementation to initialize the proxied contract.
           * It should include the signature and the parameters of the function to be called, as described in
           * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.
           * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped.
           */
          constructor(address _logic, address _admin, bytes memory _data) UpgradeabilityProxy(_logic, _data) public payable {
            assert(ADMIN_SLOT == bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1));
            _setAdmin(_admin);
          }
        }

        File 2 of 3: LinkToken
        pragma solidity ^0.4.16;
        
        
        /**
         * @title SafeMath
         * @dev Math operations with safety checks that throw on error
         */
        library SafeMath {
          function mul(uint256 a, uint256 b) internal constant returns (uint256) {
            uint256 c = a * b;
            assert(a == 0 || c / a == b);
            return c;
          }
        
          function div(uint256 a, uint256 b) internal constant 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 constant returns (uint256) {
            assert(b <= a);
            return a - b;
          }
        
          function add(uint256 a, uint256 b) internal constant returns (uint256) {
            uint256 c = a + b;
            assert(c >= a);
            return c;
          }
        }
        
        
        /**
         * @title ERC20Basic
         * @dev Simpler version of ERC20 interface
         * @dev see https://github.com/ethereum/EIPs/issues/179
         */
        contract ERC20Basic {
          uint256 public totalSupply;
          function balanceOf(address who) constant returns (uint256);
          function transfer(address to, uint256 value) returns (bool);
          event Transfer(address indexed from, address indexed to, uint256 value);
        }
        /**
         * @title ERC20 interface
         * @dev see https://github.com/ethereum/EIPs/issues/20
         */
        contract ERC20 is ERC20Basic {
          function allowance(address owner, address spender) constant returns (uint256);
          function transferFrom(address from, address to, uint256 value) returns (bool);
          function approve(address spender, uint256 value) returns (bool);
          event Approval(address indexed owner, address indexed spender, uint256 value);
        }
        
        contract ERC677 is ERC20 {
          function transferAndCall(address to, uint value, bytes data) returns (bool success);
        
          event Transfer(address indexed from, address indexed to, uint value, bytes data);
        }
        
        contract ERC677Receiver {
          function onTokenTransfer(address _sender, uint _value, bytes _data);
        }
        
        /**
         * @title Basic token
         * @dev Basic version of StandardToken, with no allowances. 
         */
        contract BasicToken is ERC20Basic {
          using SafeMath for uint256;
        
          mapping(address => uint256) balances;
        
          /**
          * @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) returns (bool) {
            balances[msg.sender] = balances[msg.sender].sub(_value);
            balances[_to] = balances[_to].add(_value);
            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) constant returns (uint256 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 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)) 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) returns (bool) {
            var _allowance = allowed[_from][msg.sender];
        
            // Check is not needed because sub(_allowance, _value) will already throw if this condition is not met
            // require (_value <= _allowance);
        
            balances[_from] = balances[_from].sub(_value);
            balances[_to] = balances[_to].add(_value);
            allowed[_from][msg.sender] = _allowance.sub(_value);
            Transfer(_from, _to, _value);
            return true;
          }
        
          /**
           * @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, uint256 _value) returns (bool) {
            allowed[msg.sender][_spender] = _value;
            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) constant returns (uint256 remaining) {
            return allowed[_owner][_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
           */
          function increaseApproval (address _spender, uint _addedValue) 
            returns (bool success) {
            allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_addedValue);
            Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
            return true;
          }
        
          function decreaseApproval (address _spender, uint _subtractedValue) 
            returns (bool success) {
            uint oldValue = allowed[msg.sender][_spender];
            if (_subtractedValue > oldValue) {
              allowed[msg.sender][_spender] = 0;
            } else {
              allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue);
            }
            Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
            return true;
          }
        
        }
        
        contract ERC677Token is ERC677 {
        
          /**
          * @dev transfer token to a contract address with additional data if the recipient is a contact.
          * @param _to The address to transfer to.
          * @param _value The amount to be transferred.
          * @param _data The extra data to be passed to the receiving contract.
          */
          function transferAndCall(address _to, uint _value, bytes _data)
            public
            returns (bool success)
          {
            super.transfer(_to, _value);
            Transfer(msg.sender, _to, _value, _data);
            if (isContract(_to)) {
              contractFallback(_to, _value, _data);
            }
            return true;
          }
        
        
          // PRIVATE
        
          function contractFallback(address _to, uint _value, bytes _data)
            private
          {
            ERC677Receiver receiver = ERC677Receiver(_to);
            receiver.onTokenTransfer(msg.sender, _value, _data);
          }
        
          function isContract(address _addr)
            private
            returns (bool hasCode)
          {
            uint length;
            assembly { length := extcodesize(_addr) }
            return length > 0;
          }
        
        }
        
        contract LinkToken is StandardToken, ERC677Token {
        
          uint public constant totalSupply = 10**27;
          string public constant name = 'ChainLink Token';
          uint8 public constant decimals = 18;
          string public constant symbol = 'LINK';
        
          function LinkToken()
            public
          {
            balances[msg.sender] = totalSupply;
          }
        
          /**
          * @dev transfer token to a specified address with additional data if the recipient is a contract.
          * @param _to The address to transfer to.
          * @param _value The amount to be transferred.
          * @param _data The extra data to be passed to the receiving contract.
          */
          function transferAndCall(address _to, uint _value, bytes _data)
            public
            validRecipient(_to)
            returns (bool success)
          {
            return super.transferAndCall(_to, _value, _data);
          }
        
          /**
          * @dev transfer token to a specified address.
          * @param _to The address to transfer to.
          * @param _value The amount to be transferred.
          */
          function transfer(address _to, uint _value)
            public
            validRecipient(_to)
            returns (bool success)
          {
            return super.transfer(_to, _value);
          }
        
          /**
           * @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, uint256 _value)
            public
            validRecipient(_spender)
            returns (bool)
          {
            return super.approve(_spender,  _value);
          }
        
          /**
           * @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
            validRecipient(_to)
            returns (bool)
          {
            return super.transferFrom(_from, _to, _value);
          }
        
        
          // MODIFIERS
        
          modifier validRecipient(address _recipient) {
            require(_recipient != address(0) && _recipient != address(this));
            _;
          }
        
        }

        File 3 of 3: AdminUpgradeabilityProxy
        // File: @openzeppelin/upgrades/contracts/upgradeability/Proxy.sol
        
        pragma solidity ^0.5.0;
        
        /**
         * @title Proxy
         * @dev Implements delegation of calls to other contracts, with proper
         * forwarding of return values and bubbling of failures.
         * It defines a fallback function that delegates all calls to the address
         * returned by the abstract _implementation() internal function.
         */
        contract Proxy {
          /**
           * @dev Fallback function.
           * Implemented entirely in `_fallback`.
           */
          function () payable external {
            _fallback();
          }
        
          /**
           * @return The Address of the implementation.
           */
          function _implementation() internal view returns (address);
        
          /**
           * @dev Delegates execution to an implementation contract.
           * This is a low level function that doesn't return to its internal call site.
           * It will return to the external caller whatever the implementation returns.
           * @param implementation Address to delegate.
           */
          function _delegate(address implementation) internal {
            assembly {
              // Copy msg.data. We take full control of memory in this inline assembly
              // block because it will not return to Solidity code. We overwrite the
              // Solidity scratch pad at memory position 0.
              calldatacopy(0, 0, calldatasize)
        
              // Call the implementation.
              // out and outsize are 0 because we don't know the size yet.
              let result := delegatecall(gas, implementation, 0, calldatasize, 0, 0)
        
              // Copy the returned data.
              returndatacopy(0, 0, returndatasize)
        
              switch result
              // delegatecall returns 0 on error.
              case 0 { revert(0, returndatasize) }
              default { return(0, returndatasize) }
            }
          }
        
          /**
           * @dev Function that is run as the first thing in the fallback function.
           * Can be redefined in derived contracts to add functionality.
           * Redefinitions must call super._willFallback().
           */
          function _willFallback() internal {
          }
        
          /**
           * @dev fallback implementation.
           * Extracted to enable manual triggering.
           */
          function _fallback() internal {
            _willFallback();
            _delegate(_implementation());
          }
        }
        
        // File: @openzeppelin/upgrades/contracts/utils/Address.sol
        
        pragma solidity ^0.5.0;
        
        /**
         * Utility library of inline functions on addresses
         *
         * Source https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-solidity/v2.1.3/contracts/utils/Address.sol
         * This contract is copied here and renamed from the original to avoid clashes in the compiled artifacts
         * when the user imports a zos-lib contract (that transitively causes this contract to be compiled and added to the
         * build/artifacts folder) as well as the vanilla Address implementation from an openzeppelin version.
         */
        library OpenZeppelinUpgradesAddress {
            /**
             * Returns whether the target address is a contract
             * @dev This function will return false if invoked during the constructor of a contract,
             * as the code is not actually created until after the constructor finishes.
             * @param account address of the account to check
             * @return whether the target address is a contract
             */
            function isContract(address account) internal view returns (bool) {
                uint256 size;
                // XXX Currently there is no better way to check if there is a contract in an address
                // than to check the size of the code at that address.
                // See https://ethereum.stackexchange.com/a/14016/36603
                // for more details about how this works.
                // TODO Check this again before the Serenity release, because all addresses will be
                // contracts then.
                // solhint-disable-next-line no-inline-assembly
                assembly { size := extcodesize(account) }
                return size > 0;
            }
        }
        
        // File: @openzeppelin/upgrades/contracts/upgradeability/BaseUpgradeabilityProxy.sol
        
        pragma solidity ^0.5.0;
        
        
        
        /**
         * @title BaseUpgradeabilityProxy
         * @dev This contract implements a proxy that allows to change the
         * implementation address to which it will delegate.
         * Such a change is called an implementation upgrade.
         */
        contract BaseUpgradeabilityProxy is Proxy {
          /**
           * @dev Emitted when the implementation is upgraded.
           * @param implementation Address of the new implementation.
           */
          event Upgraded(address indexed implementation);
        
          /**
           * @dev Storage slot with the address of the current implementation.
           * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
           * validated in the constructor.
           */
          bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
        
          /**
           * @dev Returns the current implementation.
           * @return Address of the current implementation
           */
          function _implementation() internal view returns (address impl) {
            bytes32 slot = IMPLEMENTATION_SLOT;
            assembly {
              impl := sload(slot)
            }
          }
        
          /**
           * @dev Upgrades the proxy to a new implementation.
           * @param newImplementation Address of the new implementation.
           */
          function _upgradeTo(address newImplementation) internal {
            _setImplementation(newImplementation);
            emit Upgraded(newImplementation);
          }
        
          /**
           * @dev Sets the implementation address of the proxy.
           * @param newImplementation Address of the new implementation.
           */
          function _setImplementation(address newImplementation) internal {
            require(OpenZeppelinUpgradesAddress.isContract(newImplementation), "Cannot set a proxy implementation to a non-contract address");
        
            bytes32 slot = IMPLEMENTATION_SLOT;
        
            assembly {
              sstore(slot, newImplementation)
            }
          }
        }
        
        // File: @openzeppelin/upgrades/contracts/upgradeability/UpgradeabilityProxy.sol
        
        pragma solidity ^0.5.0;
        
        
        /**
         * @title UpgradeabilityProxy
         * @dev Extends BaseUpgradeabilityProxy with a constructor for initializing
         * implementation and init data.
         */
        contract UpgradeabilityProxy is BaseUpgradeabilityProxy {
          /**
           * @dev Contract constructor.
           * @param _logic Address of the initial implementation.
           * @param _data Data to send as msg.data to the implementation to initialize the proxied contract.
           * It should include the signature and the parameters of the function to be called, as described in
           * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.
           * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped.
           */
          constructor(address _logic, bytes memory _data) public payable {
            assert(IMPLEMENTATION_SLOT == bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1));
            _setImplementation(_logic);
            if(_data.length > 0) {
              (bool success,) = _logic.delegatecall(_data);
              require(success);
            }
          }  
        }
        
        // File: @openzeppelin/upgrades/contracts/upgradeability/BaseAdminUpgradeabilityProxy.sol
        
        pragma solidity ^0.5.0;
        
        
        /**
         * @title BaseAdminUpgradeabilityProxy
         * @dev This contract combines an upgradeability proxy with an authorization
         * mechanism for administrative tasks.
         * All external functions in this contract must be guarded by the
         * `ifAdmin` modifier. See ethereum/solidity#3864 for a Solidity
         * feature proposal that would enable this to be done automatically.
         */
        contract BaseAdminUpgradeabilityProxy is BaseUpgradeabilityProxy {
          /**
           * @dev Emitted when the administration has been transferred.
           * @param previousAdmin Address of the previous admin.
           * @param newAdmin Address of the new admin.
           */
          event AdminChanged(address previousAdmin, address newAdmin);
        
          /**
           * @dev Storage slot with the admin of the contract.
           * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
           * validated in the constructor.
           */
        
          bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
        
          /**
           * @dev Modifier to check whether the `msg.sender` is the admin.
           * If it is, it will run the function. Otherwise, it will delegate the call
           * to the implementation.
           */
          modifier ifAdmin() {
            if (msg.sender == _admin()) {
              _;
            } else {
              _fallback();
            }
          }
        
          /**
           * @return The address of the proxy admin.
           */
          function admin() external ifAdmin returns (address) {
            return _admin();
          }
        
          /**
           * @return The address of the implementation.
           */
          function implementation() external ifAdmin returns (address) {
            return _implementation();
          }
        
          /**
           * @dev Changes the admin of the proxy.
           * Only the current admin can call this function.
           * @param newAdmin Address to transfer proxy administration to.
           */
          function changeAdmin(address newAdmin) external ifAdmin {
            require(newAdmin != address(0), "Cannot change the admin of a proxy to the zero address");
            emit AdminChanged(_admin(), newAdmin);
            _setAdmin(newAdmin);
          }
        
          /**
           * @dev Upgrade the backing implementation of the proxy.
           * Only the admin can call this function.
           * @param newImplementation Address of the new implementation.
           */
          function upgradeTo(address newImplementation) external ifAdmin {
            _upgradeTo(newImplementation);
          }
        
          /**
           * @dev Upgrade the backing implementation of the proxy and call a function
           * on the new implementation.
           * This is useful to initialize the proxied contract.
           * @param newImplementation Address of the new implementation.
           * @param data Data to send as msg.data in the low level call.
           * It should include the signature and the parameters of the function to be called, as described in
           * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.
           */
          function upgradeToAndCall(address newImplementation, bytes calldata data) payable external ifAdmin {
            _upgradeTo(newImplementation);
            (bool success,) = newImplementation.delegatecall(data);
            require(success);
          }
        
          /**
           * @return The admin slot.
           */
          function _admin() internal view returns (address adm) {
            bytes32 slot = ADMIN_SLOT;
            assembly {
              adm := sload(slot)
            }
          }
        
          /**
           * @dev Sets the address of the proxy admin.
           * @param newAdmin Address of the new proxy admin.
           */
          function _setAdmin(address newAdmin) internal {
            bytes32 slot = ADMIN_SLOT;
        
            assembly {
              sstore(slot, newAdmin)
            }
          }
        
          /**
           * @dev Only fall back when the sender is not the admin.
           */
          function _willFallback() internal {
            require(msg.sender != _admin(), "Cannot call fallback function from the proxy admin");
            super._willFallback();
          }
        }
        
        // File: @openzeppelin/upgrades/contracts/upgradeability/AdminUpgradeabilityProxy.sol
        
        pragma solidity ^0.5.0;
        
        
        /**
         * @title AdminUpgradeabilityProxy
         * @dev Extends from BaseAdminUpgradeabilityProxy with a constructor for 
         * initializing the implementation, admin, and init data.
         */
        contract AdminUpgradeabilityProxy is BaseAdminUpgradeabilityProxy, UpgradeabilityProxy {
          /**
           * Contract constructor.
           * @param _logic address of the initial implementation.
           * @param _admin Address of the proxy administrator.
           * @param _data Data to send as msg.data to the implementation to initialize the proxied contract.
           * It should include the signature and the parameters of the function to be called, as described in
           * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.
           * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped.
           */
          constructor(address _logic, address _admin, bytes memory _data) UpgradeabilityProxy(_logic, _data) public payable {
            assert(ADMIN_SLOT == bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1));
            _setAdmin(_admin);
          }
        }