ETH Price: $2,486.48 (+2.86%)
Gas: 8.43 Gwei

Contract

0x2f87b1fca1769BC3361700078e1985b2Dc0f1142
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Transfer Network...151423232022-07-14 18:12:12815 days ago1657822332IN
0x2f87b1fc...2Dc0f1142
0 ETH0.0045216569.83146199
Set Burn Reward150950232022-07-07 10:45:30822 days ago1657190730IN
0x2f87b1fc...2Dc0f1142
0 ETH0.0004760914.34531646
Burn150807792022-07-05 6:03:11825 days ago1657000991IN
0x2f87b1fc...2Dc0f1142
0 ETH0.0053571312.72421762
Accept Ownership146879202022-04-30 21:09:53890 days ago1651352993IN
0x2f87b1fc...2Dc0f1142
0 ETH0.0009499733.41686144
Transfer Ownersh...146878422022-04-30 20:51:46890 days ago1651351906IN
0x2f87b1fc...2Dc0f1142
0 ETH0.0012755627.60357271
Burn141486432022-02-05 22:19:59974 days ago1644099599IN
0x2f87b1fc...2Dc0f1142
0 ETH0.0229127657.16072984
Burn141466122022-02-05 14:45:05974 days ago1644072305IN
0x2f87b1fc...2Dc0f1142
0 ETH0.0410522231.58689279
Burn141456482022-02-05 11:06:24974 days ago1644059184IN
0x2f87b1fc...2Dc0f1142
0 ETH0.0531222640.32613462
Burn141442652022-02-05 6:07:09975 days ago1644041229IN
0x2f87b1fc...2Dc0f1142
0 ETH0.0295986459.29454124
Burn141386902022-02-04 9:26:58975 days ago1643966818IN
0x2f87b1fc...2Dc0f1142
0 ETH0.0312635562.12850204
Burn141367152022-02-04 2:02:48976 days ago1643940168IN
0x2f87b1fc...2Dc0f1142
0 ETH0.0318372379.42469724
Burn141356982022-02-03 22:26:34976 days ago1643927194IN
0x2f87b1fc...2Dc0f1142
0 ETH0.04495016122.07520733
Burn141326382022-02-03 11:05:50976 days ago1643886350IN
0x2f87b1fc...2Dc0f1142
0 ETH0.0347307750.14000183
Burn141313822022-02-03 6:19:19977 days ago1643869159IN
0x2f87b1fc...2Dc0f1142
0 ETH0.0283572770.7432175
Burn141289882022-02-02 21:17:19977 days ago1643836639IN
0x2f87b1fc...2Dc0f1142
0 ETH0.04212738105.09566313
Burn141248492022-02-02 5:56:04978 days ago1643781364IN
0x2f87b1fc...2Dc0f1142
0 ETH0.0419362983.41879437
Burn141227112022-02-01 22:00:36978 days ago1643752836IN
0x2f87b1fc...2Dc0f1142
0 ETH0.02949156115.42504762
Burn141191042022-02-01 8:34:25978 days ago1643704465IN
0x2f87b1fc...2Dc0f1142
0 ETH0.0415954675.49236624
Burn141171172022-02-01 1:18:09979 days ago1643678289IN
0x2f87b1fc...2Dc0f1142
0 ETH0.04143455112.09041803
Burn141149772022-01-31 17:25:16979 days ago1643649916IN
0x2f87b1fc...2Dc0f1142
0 ETH0.05224795131.38486561
Burn141115532022-01-31 4:42:27980 days ago1643604147IN
0x2f87b1fc...2Dc0f1142
0 ETH0.0420274883.36188959
Burn141085422022-01-30 17:31:51980 days ago1643563911IN
0x2f87b1fc...2Dc0f1142
0 ETH0.0381417695.15269302
Burn141057882022-01-30 7:31:07980 days ago1643527867IN
0x2f87b1fc...2Dc0f1142
0 ETH0.0336560166.01704349
Burn141057812022-01-30 7:30:03980 days ago1643527803IN
0x2f87b1fc...2Dc0f1142
0 ETH0.0382009869.70982617
Burn141056612022-01-30 7:05:39981 days ago1643526339IN
0x2f87b1fc...2Dc0f1142
0 ETH0.0660363164.27186792
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
151384142022-07-14 3:57:37816 days ago1657771057
0x2f87b1fc...2Dc0f1142
0.69313141 ETH
151384142022-07-14 3:57:37816 days ago1657771057
0x2f87b1fc...2Dc0f1142
0.69313141 ETH
151325082022-07-13 5:45:19817 days ago1657691119
0x2f87b1fc...2Dc0f1142
0.36905919 ETH
151325082022-07-13 5:45:19817 days ago1657691119
0x2f87b1fc...2Dc0f1142
0.36905919 ETH
151248102022-07-12 1:13:08818 days ago1657588388
0x2f87b1fc...2Dc0f1142
0.40601044 ETH
151248102022-07-12 1:13:08818 days ago1657588388
0x2f87b1fc...2Dc0f1142
0.40601044 ETH
151193242022-07-11 4:54:16819 days ago1657515256
0x2f87b1fc...2Dc0f1142
0.2470654 ETH
151193242022-07-11 4:54:16819 days ago1657515256
0x2f87b1fc...2Dc0f1142
0.2470654 ETH
151132902022-07-10 6:31:17820 days ago1657434677
0x2f87b1fc...2Dc0f1142
0.21936223 ETH
151132902022-07-10 6:31:17820 days ago1657434677
0x2f87b1fc...2Dc0f1142
0.21936223 ETH
151086152022-07-09 13:24:02820 days ago1657373042
0x2f87b1fc...2Dc0f1142
0.20799627 ETH
151086152022-07-09 13:24:02820 days ago1657373042
0x2f87b1fc...2Dc0f1142
0.20799627 ETH
151064352022-07-09 5:23:19821 days ago1657344199
0x2f87b1fc...2Dc0f1142
0.25809723 ETH
151064352022-07-09 5:23:19821 days ago1657344199
0x2f87b1fc...2Dc0f1142
0.25809723 ETH
151000512022-07-08 5:29:52822 days ago1657258192
0x2f87b1fc...2Dc0f1142
0.7274079 ETH
151000512022-07-08 5:29:52822 days ago1657258192
0x2f87b1fc...2Dc0f1142
0.7274079 ETH
150923352022-07-07 0:53:28823 days ago1657155208
0x2f87b1fc...2Dc0f1142
0.11857904 ETH
150923352022-07-07 0:53:28823 days ago1657155208
0x2f87b1fc...2Dc0f1142
0.11857904 ETH
150885612022-07-06 11:04:38823 days ago1657105478
0x2f87b1fc...2Dc0f1142
0.14985863 ETH
150885612022-07-06 11:04:38823 days ago1657105478
0x2f87b1fc...2Dc0f1142
0.14985863 ETH
150876362022-07-06 7:29:40823 days ago1657092580
0x2f87b1fc...2Dc0f1142
0.10738947 ETH
150876362022-07-06 7:29:40823 days ago1657092580
0x2f87b1fc...2Dc0f1142
0.10738947 ETH
150836622022-07-05 16:42:59824 days ago1657039379
0x2f87b1fc...2Dc0f1142
0.24649983 ETH
150836622022-07-05 16:42:59824 days ago1657039379
0x2f87b1fc...2Dc0f1142
0.24649983 ETH
150817762022-07-05 9:49:27824 days ago1657014567
0x2f87b1fc...2Dc0f1142
0.28279584 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
VortexBurner

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2021-04-04
*/

// File: @openzeppelin/contracts/math/SafeMath.sol

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        uint256 c = a + b;
        if (c < a) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b > a) return (false, 0);
        return (true, a - b);
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) return (true, 0);
        uint256 c = a * b;
        if (c / a != b) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a / b);
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a % b);
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");
        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "SafeMath: subtraction overflow");
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) return 0;
        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");
        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0, "SafeMath: division by zero");
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0, "SafeMath: modulo by zero");
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        return a - b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryDiv}.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a % b;
    }
}

// File: @openzeppelin/contracts/math/Math.sol



pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a >= b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow, so we distribute
        return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
    }
}

// File: @openzeppelin/contracts/token/ERC20/IERC20.sol



pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
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.
     */
    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);
}

// File: @openzeppelin/contracts/utils/Address.sol



pragma solidity >=0.6.2 <0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{ value: amount }("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain`call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
      return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: value }(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

// File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol



pragma solidity >=0.6.0 <0.8.0;




/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using SafeMath for uint256;
    using Address for address;

    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        // solhint-disable-next-line max-line-length
        require((value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).add(value);
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) { // Return data is optional
            // solhint-disable-next-line max-line-length
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

// File: @bancor/token-governance/contracts/IClaimable.sol


pragma solidity 0.6.12;

/// @title Claimable contract interface
interface IClaimable {
    function owner() external view returns (address);

    function transferOwnership(address newOwner) external;

    function acceptOwnership() external;
}

// File: @bancor/token-governance/contracts/IMintableToken.sol


pragma solidity 0.6.12;



/// @title Mintable Token interface
interface IMintableToken is IERC20, IClaimable {
    function issue(address to, uint256 amount) external;

    function destroy(address from, uint256 amount) external;
}

// File: @bancor/token-governance/contracts/ITokenGovernance.sol


pragma solidity 0.6.12;


/// @title The interface for mintable/burnable token governance.
interface ITokenGovernance {
    // The address of the mintable ERC20 token.
    function token() external view returns (IMintableToken);

    /// @dev Mints new tokens.
    ///
    /// @param to Account to receive the new amount.
    /// @param amount Amount to increase the supply by.
    ///
    function mint(address to, uint256 amount) external;

    /// @dev Burns tokens from the caller.
    ///
    /// @param amount Amount to decrease the supply by.
    ///
    function burn(uint256 amount) external;
}

// File: solidity/contracts/utility/interfaces/IOwned.sol


pragma solidity 0.6.12;

/*
    Owned contract interface
*/
interface IOwned {
    // this function isn't since the compiler emits automatically generated getter functions as external
    function owner() external view returns (address);

    function transferOwnership(address _newOwner) external;

    function acceptOwnership() external;
}

// File: solidity/contracts/converter/interfaces/IConverterAnchor.sol


pragma solidity 0.6.12;


/*
    Converter Anchor interface
*/
interface IConverterAnchor is IOwned {

}

// File: solidity/contracts/converter/interfaces/IConverterRegistry.sol


pragma solidity 0.6.12;



interface IConverterRegistry {
    function getAnchorCount() external view returns (uint256);

    function getAnchors() external view returns (address[] memory);

    function getAnchor(uint256 _index) external view returns (IConverterAnchor);

    function isAnchor(address _value) external view returns (bool);

    function getLiquidityPoolCount() external view returns (uint256);

    function getLiquidityPools() external view returns (address[] memory);

    function getLiquidityPool(uint256 _index) external view returns (IConverterAnchor);

    function isLiquidityPool(address _value) external view returns (bool);

    function getConvertibleTokenCount() external view returns (uint256);

    function getConvertibleTokens() external view returns (address[] memory);

    function getConvertibleToken(uint256 _index) external view returns (IERC20);

    function isConvertibleToken(address _value) external view returns (bool);

    function getConvertibleTokenAnchorCount(IERC20 _convertibleToken) external view returns (uint256);

    function getConvertibleTokenAnchors(IERC20 _convertibleToken) external view returns (address[] memory);

    function getConvertibleTokenAnchor(IERC20 _convertibleToken, uint256 _index)
        external
        view
        returns (IConverterAnchor);

    function isConvertibleTokenAnchor(IERC20 _convertibleToken, address _value) external view returns (bool);

    function getLiquidityPoolByConfig(
        uint16 _type,
        IERC20[] memory _reserveTokens,
        uint32[] memory _reserveWeights
    ) external view returns (IConverterAnchor);
}

// File: solidity/contracts/converter/interfaces/IConverter.sol


pragma solidity 0.6.12;




/*
    Converter interface
*/
interface IConverter is IOwned {
    function converterType() external pure returns (uint16);

    function anchor() external view returns (IConverterAnchor);

    function isActive() external view returns (bool);

    function targetAmountAndFee(
        IERC20 _sourceToken,
        IERC20 _targetToken,
        uint256 _amount
    ) external view returns (uint256, uint256);

    function convert(
        IERC20 _sourceToken,
        IERC20 _targetToken,
        uint256 _amount,
        address _trader,
        address payable _beneficiary
    ) external payable returns (uint256);

    function conversionFee() external view returns (uint32);

    function maxConversionFee() external view returns (uint32);

    function reserveBalance(IERC20 _reserveToken) external view returns (uint256);

    receive() external payable;

    function transferAnchorOwnership(address _newOwner) external;

    function acceptAnchorOwnership() external;

    function setConversionFee(uint32 _conversionFee) external;

    function addReserve(IERC20 _token, uint32 _weight) external;

    function transferReservesOnUpgrade(address _newConverter) external;

    function onUpgradeComplete() external;

    // deprecated, backward compatibility
    function token() external view returns (IConverterAnchor);

    function transferTokenOwnership(address _newOwner) external;

    function acceptTokenOwnership() external;

    function connectors(IERC20 _address)
        external
        view
        returns (
            uint256,
            uint32,
            bool,
            bool,
            bool
        );

    function getConnectorBalance(IERC20 _connectorToken) external view returns (uint256);

    function connectorTokens(uint256 _index) external view returns (IERC20);

    function connectorTokenCount() external view returns (uint16);

    /**
     * @dev triggered when the converter is activated
     *
     * @param _type        converter type
     * @param _anchor      converter anchor
     * @param _activated   true if the converter was activated, false if it was deactivated
     */
    event Activation(uint16 indexed _type, IConverterAnchor indexed _anchor, bool indexed _activated);

    /**
     * @dev triggered when a conversion between two tokens occurs
     *
     * @param _fromToken       source ERC20 token
     * @param _toToken         target ERC20 token
     * @param _trader          wallet that initiated the trade
     * @param _amount          input amount in units of the source token
     * @param _return          output amount minus conversion fee in units of the target token
     * @param _conversionFee   conversion fee in units of the target token
     */
    event Conversion(
        IERC20 indexed _fromToken,
        IERC20 indexed _toToken,
        address indexed _trader,
        uint256 _amount,
        uint256 _return,
        int256 _conversionFee
    );

    /**
     * @dev triggered when the rate between two tokens in the converter changes
     * note that the event might be dispatched for rate updates between any two tokens in the converter
     *
     * @param  _token1 address of the first token
     * @param  _token2 address of the second token
     * @param  _rateN  rate of 1 unit of `_token1` in `_token2` (numerator)
     * @param  _rateD  rate of 1 unit of `_token1` in `_token2` (denominator)
     */
    event TokenRateUpdate(IERC20 indexed _token1, IERC20 indexed _token2, uint256 _rateN, uint256 _rateD);

    /**
     * @dev triggered when the conversion fee is updated
     *
     * @param  _prevFee    previous fee percentage, represented in ppm
     * @param  _newFee     new fee percentage, represented in ppm
     */
    event ConversionFeeUpdate(uint32 _prevFee, uint32 _newFee);
}

// File: solidity/contracts/utility/Owned.sol


pragma solidity 0.6.12;


/**
 * @dev This contract provides support and utilities for contract ownership.
 */
contract Owned is IOwned {
    address public override owner;
    address public newOwner;

    /**
     * @dev triggered when the owner is updated
     *
     * @param _prevOwner previous owner
     * @param _newOwner  new owner
     */
    event OwnerUpdate(address indexed _prevOwner, address indexed _newOwner);

    /**
     * @dev initializes a new Owned instance
     */
    constructor() public {
        owner = msg.sender;
    }

    // allows execution by the owner only
    modifier ownerOnly {
        _ownerOnly();
        _;
    }

    // error message binary size optimization
    function _ownerOnly() internal view {
        require(msg.sender == owner, "ERR_ACCESS_DENIED");
    }

    /**
     * @dev allows transferring the contract ownership
     * the new owner still needs to accept the transfer
     * can only be called by the contract owner
     *
     * @param _newOwner    new contract owner
     */
    function transferOwnership(address _newOwner) public override ownerOnly {
        require(_newOwner != owner, "ERR_SAME_OWNER");
        newOwner = _newOwner;
    }

    /**
     * @dev used by a new owner to accept an ownership transfer
     */
    function acceptOwnership() public override {
        require(msg.sender == newOwner, "ERR_ACCESS_DENIED");
        emit OwnerUpdate(owner, newOwner);
        owner = newOwner;
        newOwner = address(0);
    }
}

// File: solidity/contracts/utility/Utils.sol


pragma solidity 0.6.12;


/**
 * @dev Utilities & Common Modifiers
 */
contract Utils {
    uint32 internal constant PPM_RESOLUTION = 1000000;
    IERC20 internal constant NATIVE_TOKEN_ADDRESS = IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);

    // verifies that a value is greater than zero
    modifier greaterThanZero(uint256 _value) {
        _greaterThanZero(_value);
        _;
    }

    // error message binary size optimization
    function _greaterThanZero(uint256 _value) internal pure {
        require(_value > 0, "ERR_ZERO_VALUE");
    }

    // validates an address - currently only checks that it isn't null
    modifier validAddress(address _address) {
        _validAddress(_address);
        _;
    }

    // error message binary size optimization
    function _validAddress(address _address) internal pure {
        require(_address != address(0), "ERR_INVALID_ADDRESS");
    }

    // ensures that the portion is valid
    modifier validPortion(uint32 _portion) {
        _validPortion(_portion);
        _;
    }

    // error message binary size optimization
    function _validPortion(uint32 _portion) internal pure {
        require(_portion > 0 && _portion <= PPM_RESOLUTION, "ERR_INVALID_PORTION");
    }

    // validates an external address - currently only checks that it isn't null or this
    modifier validExternalAddress(address _address) {
        _validExternalAddress(_address);
        _;
    }

    // error message binary size optimization
    function _validExternalAddress(address _address) internal view {
        require(_address != address(0) && _address != address(this), "ERR_INVALID_EXTERNAL_ADDRESS");
    }

    // ensures that the fee is valid
    modifier validFee(uint32 fee) {
        _validFee(fee);
        _;
    }

    // error message binary size optimization
    function _validFee(uint32 fee) internal pure {
        require(fee <= PPM_RESOLUTION, "ERR_INVALID_FEE");
    }
}

// File: solidity/contracts/utility/interfaces/IContractRegistry.sol


pragma solidity 0.6.12;

/*
    Contract Registry interface
*/
interface IContractRegistry {
    function addressOf(bytes32 _contractName) external view returns (address);
}

// File: solidity/contracts/utility/ContractRegistryClient.sol


pragma solidity 0.6.12;




/**
 * @dev This is the base contract for ContractRegistry clients.
 */
contract ContractRegistryClient is Owned, Utils {
    bytes32 internal constant CONTRACT_REGISTRY = "ContractRegistry";
    bytes32 internal constant BANCOR_NETWORK = "BancorNetwork";
    bytes32 internal constant BANCOR_FORMULA = "BancorFormula";
    bytes32 internal constant CONVERTER_FACTORY = "ConverterFactory";
    bytes32 internal constant CONVERSION_PATH_FINDER = "ConversionPathFinder";
    bytes32 internal constant CONVERTER_UPGRADER = "BancorConverterUpgrader";
    bytes32 internal constant CONVERTER_REGISTRY = "BancorConverterRegistry";
    bytes32 internal constant CONVERTER_REGISTRY_DATA = "BancorConverterRegistryData";
    bytes32 internal constant BNT_TOKEN = "BNTToken";
    bytes32 internal constant BANCOR_X = "BancorX";
    bytes32 internal constant BANCOR_X_UPGRADER = "BancorXUpgrader";
    bytes32 internal constant LIQUIDITY_PROTECTION = "LiquidityProtection";
    bytes32 internal constant NETWORK_SETTINGS = "NetworkSettings";

    IContractRegistry public registry; // address of the current contract-registry
    IContractRegistry public prevRegistry; // address of the previous contract-registry
    bool public onlyOwnerCanUpdateRegistry; // only an owner can update the contract-registry

    /**
     * @dev verifies that the caller is mapped to the given contract name
     *
     * @param _contractName    contract name
     */
    modifier only(bytes32 _contractName) {
        _only(_contractName);
        _;
    }

    // error message binary size optimization
    function _only(bytes32 _contractName) internal view {
        require(msg.sender == addressOf(_contractName), "ERR_ACCESS_DENIED");
    }

    /**
     * @dev initializes a new ContractRegistryClient instance
     *
     * @param  _registry   address of a contract-registry contract
     */
    constructor(IContractRegistry _registry) internal validAddress(address(_registry)) {
        registry = IContractRegistry(_registry);
        prevRegistry = IContractRegistry(_registry);
    }

    /**
     * @dev updates to the new contract-registry
     */
    function updateRegistry() public {
        // verify that this function is permitted
        require(msg.sender == owner || !onlyOwnerCanUpdateRegistry, "ERR_ACCESS_DENIED");

        // get the new contract-registry
        IContractRegistry newRegistry = IContractRegistry(addressOf(CONTRACT_REGISTRY));

        // verify that the new contract-registry is different and not zero
        require(newRegistry != registry && address(newRegistry) != address(0), "ERR_INVALID_REGISTRY");

        // verify that the new contract-registry is pointing to a non-zero contract-registry
        require(newRegistry.addressOf(CONTRACT_REGISTRY) != address(0), "ERR_INVALID_REGISTRY");

        // save a backup of the current contract-registry before replacing it
        prevRegistry = registry;

        // replace the current contract-registry with the new contract-registry
        registry = newRegistry;
    }

    /**
     * @dev restores the previous contract-registry
     */
    function restoreRegistry() public ownerOnly {
        // restore the previous contract-registry
        registry = prevRegistry;
    }

    /**
     * @dev restricts the permission to update the contract-registry
     *
     * @param _onlyOwnerCanUpdateRegistry  indicates whether or not permission is restricted to owner only
     */
    function restrictRegistryUpdate(bool _onlyOwnerCanUpdateRegistry) public ownerOnly {
        // change the permission to update the contract-registry
        onlyOwnerCanUpdateRegistry = _onlyOwnerCanUpdateRegistry;
    }

    /**
     * @dev returns the address associated with the given contract name
     *
     * @param _contractName    contract name
     *
     * @return contract address
     */
    function addressOf(bytes32 _contractName) internal view returns (address) {
        return registry.addressOf(_contractName);
    }
}

// File: solidity/contracts/utility/interfaces/ITokenHolder.sol


pragma solidity 0.6.12;



/*
    Token Holder interface
*/
interface ITokenHolder is IOwned {
    receive() external payable;

    function withdrawTokens(
        IERC20 token,
        address payable to,
        uint256 amount
    ) external;

    function withdrawTokensMultiple(
        IERC20[] calldata tokens,
        address payable to,
        uint256[] calldata amounts
    ) external;
}

// File: solidity/contracts/utility/TokenHolder.sol


pragma solidity 0.6.12;





/**
 * @dev This contract provides a safety mechanism for allowing the owner to
 * send tokens that were sent to the contract by mistake back to the sender.
 *
 * We consider every contract to be a 'token holder' since it's currently not possible
 * for a contract to deny receiving tokens.
 */
contract TokenHolder is ITokenHolder, Owned, Utils {
    using SafeERC20 for IERC20;

    // prettier-ignore
    receive() external payable override virtual {}

    /**
     * @dev withdraws funds held by the contract and sends them to an account
     * can only be called by the owner
     *
     * @param token ERC20 token contract address (with a special handling of NATIVE_TOKEN_ADDRESS)
     * @param to account to receive the new amount
     * @param amount amount to withdraw
     */
    function withdrawTokens(
        IERC20 token,
        address payable to,
        uint256 amount
    ) public virtual override ownerOnly validAddress(to) {
        safeTransfer(token, to, amount);
    }

    /**
     * @dev withdraws multiple funds held by the contract and sends them to an account
     * can only be called by the owner
     *
     * @param tokens ERC20 token contract addresses (with a special handling of NATIVE_TOKEN_ADDRESS)
     * @param to account to receive the new amount
     * @param amounts amounts to withdraw
     */
    function withdrawTokensMultiple(
        IERC20[] calldata tokens,
        address payable to,
        uint256[] calldata amounts
    ) public virtual override ownerOnly validAddress(to) {
        uint256 length = tokens.length;
        require(length == amounts.length, "ERR_INVALID_LENGTH");

        for (uint256 i = 0; i < length; ++i) {
            safeTransfer(tokens[i], to, amounts[i]);
        }
    }

    /**
     * @dev transfers funds held by the contract and sends them to an account
     *
     * @param token ERC20 token contract address
     * @param to account to receive the new amount
     * @param amount amount to withdraw
     */
    function safeTransfer(
        IERC20 token,
        address payable to,
        uint256 amount
    ) internal {
        if (amount == 0) {
            return;
        }

        if (token == NATIVE_TOKEN_ADDRESS) {
            to.transfer(amount);
        } else {
            token.safeTransfer(to, amount);
        }
    }
}

// File: solidity/contracts/utility/ReentrancyGuard.sol


pragma solidity 0.6.12;

/**
 * @dev This contract provides protection against calling a function
 * (directly or indirectly) from within itself.
 */
contract ReentrancyGuard {
    uint256 private constant UNLOCKED = 1;
    uint256 private constant LOCKED = 2;

    // LOCKED while protected code is being executed, UNLOCKED otherwise
    uint256 private state = UNLOCKED;

    /**
     * @dev ensures instantiation only by sub-contracts
     */
    constructor() internal {}

    // protects a function against reentrancy attacks
    modifier protected() {
        _protected();
        state = LOCKED;
        _;
        state = UNLOCKED;
    }

    // error message binary size optimization
    function _protected() internal view {
        require(state == UNLOCKED, "ERR_REENTRANCY");
    }
}

// File: solidity/contracts/INetworkSettings.sol


pragma solidity 0.6.12;


interface INetworkSettings {
    function networkFeeParams() external view returns (ITokenHolder, uint32);

    function networkFeeWallet() external view returns (ITokenHolder);

    function networkFee() external view returns (uint32);
}

// File: solidity/contracts/IBancorNetwork.sol


pragma solidity 0.6.12;

interface IBancorNetwork {
    function rateByPath(address[] memory path, uint256 amount) external view returns (uint256);

    function convertByPath(
        address[] memory path,
        uint256 amount,
        uint256 minReturn,
        address payable beneficiary,
        address affiliateAccount,
        uint256 affiliateFee
    ) external payable returns (uint256);
}

// File: solidity/contracts/vortex/VortexBurner.sol


pragma solidity 0.6.12;














/**
 * @dev This contract provides any user to trigger a network fee burning event
 */
contract VortexBurner is Owned, Utils, ReentrancyGuard, ContractRegistryClient {
    using SafeMath for uint256;
    using Math for uint256;
    using SafeERC20 for IERC20;

    struct Strategy {
        address[][] paths;
        uint256[] amounts;
        address[] govPath;
    }

    // the mechanism is only designed to work with 50/50 standard pool converters
    uint32 private constant STANDARD_POOL_RESERVE_WEIGHT = PPM_RESOLUTION / 2;

    // the type of the standard pool converter
    uint16 private constant STANDARD_POOL_CONVERTER_TYPE = 3;

    // the address of the network token
    IERC20 private immutable _networkToken;

    // the address of the governance token
    IERC20 private immutable _govToken;

    // the address of the governance token security module
    ITokenGovernance private immutable _govTokenGovernance;

    // the percentage of the converted network tokens to be sent to the caller of the burning event (in units of PPM)
    uint32 private _burnReward;

    // the maximum burn reward to be sent to the caller of the burning event
    uint256 private _maxBurnRewardAmount;

    // stores the total amount of the burned governance tokens
    uint256 private _totalBurnedAmount;

    /**
     * @dev triggered when the burn reward has been changed
     *
     * @param prevBurnReward the previous burn reward (in units of PPM)
     * @param newBurnReward the new burn reward (in units of PPM)
     * @param prevMaxBurnRewardAmount the previous maximum burn reward
     * @param newMaxBurnRewardAmount the new maximum burn reward
     */
    event BurnRewardUpdated(
        uint32 prevBurnReward,
        uint32 newBurnReward,
        uint256 prevMaxBurnRewardAmount,
        uint256 newMaxBurnRewardAmount
    );

    /**
     * @dev triggered during conversion of a single token during the burning event
     *
     * @param token the converted token
     * @param sourceAmount the amount of the converted token
     * @param targetAmount the network token amount the token were converted to
     */
    event Converted(IERC20 token, uint256 sourceAmount, uint256 targetAmount);

    /**
     * @dev triggered after a completed burning event
     *
     * @param tokens the converted tokens
     * @param sourceAmount the total network token amount the tokens were converted to
     * @param burnedAmount the total burned amount in the burning event
     */
    event Burned(IERC20[] tokens, uint256 sourceAmount, uint256 burnedAmount);

    /**
     * @dev initializes a new VortexBurner contract
     *
     * @param networkToken the address of the network token
     * @param govTokenGovernance the address of the governance token security module
     * @param registry the address of the contract registry
     */
    constructor(
        IERC20 networkToken,
        ITokenGovernance govTokenGovernance,
        IContractRegistry registry
    )
        public
        ContractRegistryClient(registry)
        validAddress(address(networkToken))
        validAddress(address(govTokenGovernance))
    {
        _networkToken = networkToken;
        _govTokenGovernance = govTokenGovernance;
        _govToken = govTokenGovernance.token();
    }

    /**
     * @dev ETH receive callback
     */
    receive() external payable {}

    /**
     * @dev returns the burn reward percentage and its maximum amount
     *
     * @return the burn reward percentage and its maximum amount
     */
    function burnReward() external view returns (uint32, uint256) {
        return (_burnReward, _maxBurnRewardAmount);
    }

    /**
     * @dev allows the owner to set the burn reward percentage and its maximum amount
     *
     * @param newBurnReward the percentage of the converted network tokens to be sent to the caller of the burning event (in units of PPM)
     * @param newMaxBurnRewardAmount the maximum burn reward to be sent to the caller of the burning event
     */
    function setBurnReward(uint32 newBurnReward, uint256 newMaxBurnRewardAmount)
        external
        ownerOnly
        validFee(newBurnReward)
    {
        emit BurnRewardUpdated(_burnReward, newBurnReward, _maxBurnRewardAmount, newMaxBurnRewardAmount);

        _burnReward = newBurnReward;
        _maxBurnRewardAmount = newMaxBurnRewardAmount;
    }

    /**
     * @dev returns the total amount of the burned governance tokens
     *
     * @return total amount of the burned governance tokens
     */
    function totalBurnedAmount() external view returns (uint256) {
        return _totalBurnedAmount;
    }

    /**
     * @dev converts the provided tokens to governance tokens and burns them
     *
     * @param tokens the tokens to convert
     */
    function burn(IERC20[] calldata tokens) external protected {
        ITokenHolder feeWallet = networkFeeWallet();

        // retrieve the burning strategy
        Strategy memory strategy = burnStrategy(tokens, feeWallet);

        // withdraw all token/ETH amounts to the contract
        feeWallet.withdrawTokensMultiple(tokens, address(this), strategy.amounts);

        // convert all amounts to the network token and record conversion amounts
        IBancorNetwork network = bancorNetwork();

        for (uint256 i = 0; i < strategy.paths.length; ++i) {
            // avoid empty conversions
            uint256 amount = strategy.amounts[i];
            if (amount == 0) {
                continue;
            }

            address[] memory path = strategy.paths[i];
            IERC20 token = IERC20(path[0]);
            uint256 value = 0;

            if (token == _networkToken || token == _govToken) {
                // if the source token is the network or the governance token, we won't try to convert it, but rather
                // include its amount in either the total amount of tokens to convert or burn.
                continue;
            }

            if (token == NATIVE_TOKEN_ADDRESS) {
                // if the source token is actually an ETH reserve, make sure to pass its value to the network
                value = amount;
            } else {
                // if the source token is a regular token, approve the network to withdraw the token amount
                ensureAllowance(token, network, amount);
            }

            // perform the actual conversion and optionally send ETH to the network
            uint256 targetAmount = network.convertByPath{ value: value }(path, amount, 1, address(this), address(0), 0);

            emit Converted(token, amount, targetAmount);
        }

        // calculate the burn reward and reduce it from the total amount to convert
        (uint256 sourceAmount, uint256 burnRewardAmount) = netNetworkConversionAmounts();

        // in case there are network tokens to burn, convert them to the governance token
        if (sourceAmount > 0) {
            // approve the network to withdraw the network token amount
            ensureAllowance(_networkToken, network, sourceAmount);

            // convert the entire network token amount to the governance token
            network.convertByPath(strategy.govPath, sourceAmount, 1, address(this), address(0), 0);
        }

        // get the governance token balance
        uint256 govTokenBalance = _govToken.balanceOf(address(this));
        require(govTokenBalance > 0, "ERR_ZERO_BURN_AMOUNT");

        // update the stats of the burning event
        _totalBurnedAmount = _totalBurnedAmount.add(govTokenBalance);

        // burn the entire governance token balance
        _govTokenGovernance.burn(govTokenBalance);

        // if there is a burn reward, transfer it to the caller
        if (burnRewardAmount > 0) {
            _networkToken.transfer(msg.sender, burnRewardAmount);
        }

        emit Burned(tokens, sourceAmount + burnRewardAmount, govTokenBalance);
    }

    /**
     * @dev transfers the ownership of the network fee wallet
     *
     * @param newOwner the new owner of the network fee wallet
     */
    function transferNetworkFeeWalletOwnership(address newOwner) external ownerOnly {
        networkFeeWallet().transferOwnership(newOwner);
    }

    /**
     * @dev accepts the ownership of he network fee wallet
     */
    function acceptNetworkFeeOwnership() external ownerOnly {
        networkFeeWallet().acceptOwnership();
    }

    /**
     * @dev returns the burning strategy for the specified tokens
     *
     * @param tokens the tokens to convert
     *
     * @return the the burning strategy for the specified tokens
     */
    function burnStrategy(IERC20[] calldata tokens, ITokenHolder feeWallet) private view returns (Strategy memory) {
        IConverterRegistry registry = converterRegistry();

        Strategy memory strategy =
            Strategy({
                paths: new address[][](tokens.length),
                amounts: new uint256[](tokens.length),
                govPath: new address[](3)
            });

        for (uint256 i = 0; i < tokens.length; ++i) {
            IERC20 token = tokens[i];

            address[] memory path = new address[](3);
            path[0] = address(token);

            // don't look up for a converter for either the network or the governance token, since they are going to be
            // handled in a special way during the burn itself
            if (token != _networkToken && token != _govToken) {
                path[1] = address(networkTokenConverterAnchor(token, registry));
                path[2] = address(_networkToken);
            }

            strategy.paths[i] = path;

            // make sure to retrieve the balance of either an ERC20 or an ETH reserve
            if (token == NATIVE_TOKEN_ADDRESS) {
                strategy.amounts[i] = address(feeWallet).balance;
            } else {
                strategy.amounts[i] = token.balanceOf(address(feeWallet));
            }
        }

        // get the governance token converter path
        strategy.govPath[0] = address(_networkToken);
        strategy.govPath[1] = address(networkTokenConverterAnchor(_govToken, registry));
        strategy.govPath[2] = address(_govToken);

        return strategy;
    }

    /**
     * @dev applies the burn reward on the whole balance and returns the net amount and the reward
     *
     * @return network token target amount
     * @return burn reward amount
     */
    function netNetworkConversionAmounts() private view returns (uint256, uint256) {
        uint256 amount = _networkToken.balanceOf(address(this));
        uint256 burnRewardAmount = Math.min(amount.mul(_burnReward) / PPM_RESOLUTION, _maxBurnRewardAmount);

        return (amount - burnRewardAmount, burnRewardAmount);
    }

    /**
     * @dev finds the converter anchor of the 50/50 standard pool converter between the specified token and the network token
     *
     * @param token the source token
     * @param converterRegistry the converter registry
     *
     * @return the converter anchor of the 50/50 standard pool converter between the specified token
     */
    function networkTokenConverterAnchor(IERC20 token, IConverterRegistry converterRegistry)
        private
        view
        returns (IConverterAnchor)
    {
        // initialize both the source and the target tokens
        IERC20[] memory reserveTokens = new IERC20[](2);
        reserveTokens[0] = _networkToken;
        reserveTokens[1] = token;

        // make sure to only look up for 50/50 converters
        uint32[] memory standardReserveWeights = new uint32[](2);
        standardReserveWeights[0] = STANDARD_POOL_RESERVE_WEIGHT;
        standardReserveWeights[1] = STANDARD_POOL_RESERVE_WEIGHT;

        // find the standard pool converter between the specified token and the network token
        IConverterAnchor anchor =
            converterRegistry.getLiquidityPoolByConfig(
                STANDARD_POOL_CONVERTER_TYPE,
                reserveTokens,
                standardReserveWeights
            );
        require(address(anchor) != address(0), "ERR_INVALID_RESERVE_TOKEN");

        return anchor;
    }

    /**
     * @dev ensures that the network is able to pull the tokens from this contact
     *
     * @param token the source token
     * @param network the address of the network contract
     * @param amount the token amount to approve
     */
    function ensureAllowance(
        IERC20 token,
        IBancorNetwork network,
        uint256 amount
    ) private {
        address networkAddress = address(network);
        uint256 allowance = token.allowance(address(this), networkAddress);
        if (allowance < amount) {
            if (allowance > 0) {
                token.safeApprove(networkAddress, 0);
            }
            token.safeApprove(networkAddress, amount);
        }
    }

    /**
     * @dev returns the converter registry
     *
     * @return the converter registry
     */
    function converterRegistry() private view returns (IConverterRegistry) {
        return IConverterRegistry(addressOf(CONVERTER_REGISTRY));
    }

    /**
     * @dev returns the network contract
     *
     * @return the network contract
     */
    function bancorNetwork() private view returns (IBancorNetwork) {
        return IBancorNetwork(payable(addressOf(BANCOR_NETWORK)));
    }

    /**
     * @dev returns the network settings contract
     *
     * @return the network settings contract
     */
    function networkSetting() private view returns (INetworkSettings) {
        return INetworkSettings(addressOf(NETWORK_SETTINGS));
    }

    /**
     * @dev returns the network fee wallet
     *
     * @return the network fee wallet
     */
    function networkFeeWallet() private view returns (ITokenHolder) {
        return ITokenHolder(networkSetting().networkFeeWallet());
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"contract IERC20","name":"networkToken","type":"address"},{"internalType":"contract ITokenGovernance","name":"govTokenGovernance","type":"address"},{"internalType":"contract IContractRegistry","name":"registry","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"prevBurnReward","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"newBurnReward","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"prevMaxBurnRewardAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMaxBurnRewardAmount","type":"uint256"}],"name":"BurnRewardUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract IERC20[]","name":"tokens","type":"address[]"},{"indexed":false,"internalType":"uint256","name":"sourceAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"burnedAmount","type":"uint256"}],"name":"Burned","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract IERC20","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"sourceAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"targetAmount","type":"uint256"}],"name":"Converted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_prevOwner","type":"address"},{"indexed":true,"internalType":"address","name":"_newOwner","type":"address"}],"name":"OwnerUpdate","type":"event"},{"inputs":[],"name":"acceptNetworkFeeOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20[]","name":"tokens","type":"address[]"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"burnReward","outputs":[{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"newOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"onlyOwnerCanUpdateRegistry","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"prevRegistry","outputs":[{"internalType":"contract IContractRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registry","outputs":[{"internalType":"contract IContractRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"restoreRegistry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_onlyOwnerCanUpdateRegistry","type":"bool"}],"name":"restrictRegistryUpdate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"newBurnReward","type":"uint32"},{"internalType":"uint256","name":"newMaxBurnRewardAmount","type":"uint256"}],"name":"setBurnReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalBurnedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferNetworkFeeWalletOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateRegistry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

60e060405260016002553480156200001657600080fd5b506040516200231e3803806200231e833981810160405260608110156200003c57600080fd5b5080516020820151604090920151600080546001600160a01b0319163317905590919080806200006c8162000154565b50600380546001600160a01b039092166001600160a01b031992831681179091556004805490921617905582620000a38162000154565b82620000af8162000154565b6001600160601b0319606086811b821660805285901b1660c05260408051637e062a3560e11b815290516001600160a01b0386169163fc0c546a916004808301926020929190829003018186803b1580156200010a57600080fd5b505afa1580156200011f573d6000803e3d6000fd5b505050506040513d60208110156200013657600080fd5b505160601b6001600160601b03191660a05250620001b39350505050565b6001600160a01b038116620001b0576040805162461bcd60e51b815260206004820152601360248201527f4552525f494e56414c49445f4144445245535300000000000000000000000000604482015290519081900360640190fd5b50565b60805160601c60a05160601c60c05160601c6120fe6200022060003980610c4d5250806108405280610b3a528061139a52806115c052806116185250806108055280610a1f5280610cdc528061136b528061140d528061156b528061174c528061195552506120fe6000f3fe6080604052600436106100f75760003560e01c8063769b90b91161008a578063afd25caa11610059578063afd25caa14610321578063b4a176d314610336578063d4ee1d901461034b578063f2fde38b14610360576100fe565b8063769b90b9146102ac57806379ba5097146102e25780637b103999146102f75780638da5cb5b1461030c576100fe565b806349d10b64116100c657806349d10b64146101b65780634aca7fb2146101cb57806361cd756e146101fe5780636c5d61561461022f576100fe565b8063024c7ec71461010357806302a79454146101315780632fe8a6ad1461016657806335ab5f641461018f576100fe565b366100fe57005b600080fd5b34801561010f57600080fd5b5061012f6004803603602081101561012657600080fd5b50351515610393565b005b34801561013d57600080fd5b506101466103b9565b6040805163ffffffff909316835260208301919091528051918290030190f35b34801561017257600080fd5b5061017b6103d0565b604080519115158252519081900360200190f35b34801561019b57600080fd5b506101a46103e0565b60408051918252519081900360200190f35b3480156101c257600080fd5b5061012f6103e6565b3480156101d757600080fd5b5061012f600480360360208110156101ee57600080fd5b50356001600160a01b03166105ee565b34801561020a57600080fd5b50610213610667565b604080516001600160a01b039092168252519081900360200190f35b34801561023b57600080fd5b5061012f6004803603602081101561025257600080fd5b81019060208101813564010000000081111561026d57600080fd5b82018360208201111561027f57600080fd5b803590602001918460208302840111640100000000831117156102a157600080fd5b509092509050610676565b3480156102b857600080fd5b5061012f600480360360408110156102cf57600080fd5b5063ffffffff8135169060200135610dd5565b3480156102ee57600080fd5b5061012f610e6e565b34801561030357600080fd5b50610213610f25565b34801561031857600080fd5b50610213610f34565b34801561032d57600080fd5b5061012f610f43565b34801561034257600080fd5b5061012f610fa7565b34801561035757600080fd5b50610213610fd3565b34801561036c57600080fd5b5061012f6004803603602081101561038357600080fd5b50356001600160a01b0316610fe2565b61039b611060565b60048054911515600160a01b0260ff60a01b19909216919091179055565b600454600554600160a81b90910463ffffffff1691565b600454600160a01b900460ff1681565b60065490565b6000546001600160a01b03163314806104095750600454600160a01b900460ff16155b61044e576040805162461bcd60e51b815260206004820152601160248201527011549497d050d0d154d4d7d11153925151607a1b604482015290519081900360640190fd5b600061046c6f436f6e7472616374526567697374727960801b6110b5565b6003549091506001600160a01b0380831691161480159061049557506001600160a01b03811615155b6104dd576040805162461bcd60e51b81526020600482015260146024820152734552525f494e56414c49445f524547495354525960601b604482015290519081900360640190fd5b60006001600160a01b0316816001600160a01b031663bb34534c6f436f6e7472616374526567697374727960801b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561053f57600080fd5b505afa158015610553573d6000803e3d6000fd5b505050506040513d602081101561056957600080fd5b50516001600160a01b031614156105be576040805162461bcd60e51b81526020600482015260146024820152734552525f494e56414c49445f524547495354525960601b604482015290519081900360640190fd5b60038054600480546001600160a01b038084166001600160a01b0319928316179092559091169216919091179055565b6105f6611060565b6105fe611133565b6001600160a01b031663f2fde38b826040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050600060405180830381600087803b15801561064c57600080fd5b505af1158015610660573d6000803e3d6000fd5b5050505050565b6004546001600160a01b031681565b61067e6111a6565b60028055600061068c611133565b9050610696612000565b6106a18484846111ee565b9050816001600160a01b03166308506df785853085602001516040518563ffffffff1660e01b81526004018080602001846001600160a01b031681526020018060200183810383528787828181526020019250602002808284376000838201819052601f909101601f1916909201858103845286518152865160209182019382890193509102908190849084905b8381101561074757818101518382015260200161072f565b505050509050019650505050505050600060405180830381600087803b15801561077057600080fd5b505af1158015610784573d6000803e3d6000fd5b50505050600061079261166b565b905060005b825151811015610a03576000836020015182815181106107b357fe5b6020026020010151905080600014156107cc57506109fb565b6060846000015183815181106107de57fe5b602002602001015190506000816000815181106107f757fe5b6020026020010151905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316148061087457507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316145b1561088257505050506109fb565b6001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156108ae5750826108b9565b6108b982878661168b565b6000866001600160a01b031663b77d239b8386886001306000806040518863ffffffff1660e01b81526004018080602001878152602001868152602001856001600160a01b03168152602001846001600160a01b03168152602001838152602001828103825288818151815260200191508051906020019060200280838360005b8381101561095257818101518382015260200161093a565b505050509050019750505050505050506020604051808303818588803b15801561097b57600080fd5b505af115801561098f573d6000803e3d6000fd5b50505050506040513d60208110156109a657600080fd5b5051604080516001600160a01b03861681526020810188905280820183905290519192507fe6a45eea08a42f7c3f90f290e8ecf15e16174981943adf509fc9ea49808a64c6919081900360600190a150505050505b600101610797565b50600080610a0f611745565b90925090508115610b3657610a457f0000000000000000000000000000000000000000000000000000000000000000848461168b565b826001600160a01b031663b77d239b8560400151846001306000806040518763ffffffff1660e01b81526004018080602001878152602001868152602001856001600160a01b03168152602001846001600160a01b03168152602001838152602001828103825288818151815260200191508051906020019060200280838360005b83811015610adf578181015183820152602001610ac7565b50505050905001975050505050505050602060405180830381600087803b158015610b0957600080fd5b505af1158015610b1d573d6000803e3d6000fd5b505050506040513d6020811015610b3357600080fd5b50505b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015610ba557600080fd5b505afa158015610bb9573d6000803e3d6000fd5b505050506040513d6020811015610bcf57600080fd5b5051905080610c1c576040805162461bcd60e51b815260206004820152601460248201527311549497d6915493d7d095549397d05353d5539560621b604482015290519081900360640190fd5b600654610c29908261182f565b60065560408051630852cd8d60e31b81526004810183905290516001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916342966c6891602480830192600092919082900301818387803b158015610c9457600080fd5b505af1158015610ca8573d6000803e3d6000fd5b505050506000821115610d51576040805163a9059cbb60e01b81523360048201526024810184905290516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163a9059cbb9160448083019260209291908290030181600087803b158015610d2457600080fd5b505af1158015610d38573d6000803e3d6000fd5b505050506040513d6020811015610d4e57600080fd5b50505b7f8d1a3aa2e14a1c054c9817979380a072bdf25ccff4f74e29d40616a716cb538888888486018460405180806020018481526020018381526020018281038252868682818152602001925060200280828437600083820152604051601f909101601f191690920182900397509095505050505050a150506001600255505050505050565b610ddd611060565b81610de781611892565b6004546005546040805163ffffffff600160a81b9094048416815292861660208401528281019190915260608201849052517f71d9eda78517255f4f5f721d1855a56406b2daf72b2beedc9bcdc3f7fcee17539181900360800190a1506004805463ffffffff909316600160a81b0263ffffffff60a81b1990931692909217909155600555565b6001546001600160a01b03163314610ec1576040805162461bcd60e51b815260206004820152601160248201527011549497d050d0d154d4d7d11153925151607a1b604482015290519081900360640190fd5b600154600080546040516001600160a01b0393841693909116917f343765429aea5a34b3ff6a3785a98a5abb2597aca87bfbb58632c173d585373a91a360018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b6003546001600160a01b031681565b6000546001600160a01b031681565b610f4b611060565b610f53611133565b6001600160a01b03166379ba50976040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610f8d57600080fd5b505af1158015610fa1573d6000803e3d6000fd5b50505050565b610faf611060565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b6001546001600160a01b031681565b610fea611060565b6000546001600160a01b038281169116141561103e576040805162461bcd60e51b815260206004820152600e60248201526d22a9292fa9a0a6a2afa7aba722a960911b604482015290519081900360640190fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031633146110b3576040805162461bcd60e51b815260206004820152601160248201527011549497d050d0d154d4d7d11153925151607a1b604482015290519081900360640190fd5b565b60035460408051632ecd14d360e21b81526004810184905290516000926001600160a01b03169163bb34534c916024808301926020929190829003018186803b15801561110157600080fd5b505afa158015611115573d6000803e3d6000fd5b505050506040513d602081101561112b57600080fd5b505192915050565b600061113d6118e5565b6001600160a01b0316633e4565046040518163ffffffff1660e01b815260040160206040518083038186803b15801561117557600080fd5b505afa158015611189573d6000803e3d6000fd5b505050506040513d602081101561119f57600080fd5b5051905090565b6001600254146110b3576040805162461bcd60e51b815260206004820152600e60248201526d4552525f5245454e5452414e435960901b604482015290519081900360640190fd5b6111f6612000565b6000611200611902565b905061120a612000565b6040805160608101909152808667ffffffffffffffff8111801561122d57600080fd5b5060405190808252806020026020018201604052801561126157816020015b606081526020019060019003908161124c5790505b5081526020018667ffffffffffffffff8111801561127e57600080fd5b506040519080825280602002602001820160405280156112a8578160200160208202803683370190505b5081526040805160038082526080820190925260209283019290919082016060803683375050509052905060005b858110156115685760008787838181106112ec57fe5b905060200201356001600160a01b031690506060600367ffffffffffffffff8111801561131857600080fd5b50604051908082528060200260200182016040528015611342578160200160208202803683370190505b509050818160008151811061135357fe5b6001600160a01b0392831660209182029290920101527f00000000000000000000000000000000000000000000000000000000000000008116908316148015906113cf57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031614155b1561145a576113de828661192d565b816001815181106113eb57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250507f00000000000000000000000000000000000000000000000000000000000000008160028151811061143957fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b808460000151848151811061146b57fe5b60209081029190910101526001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156114c757866001600160a01b031631846020015184815181106114b657fe5b60200260200101818152505061155e565b816001600160a01b03166370a08231886040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561151457600080fd5b505afa158015611528573d6000803e3d6000fd5b505050506040513d602081101561153e57600080fd5b5051602085015180518590811061155157fe5b6020026020010181815250505b50506001016112d6565b507f0000000000000000000000000000000000000000000000000000000000000000816040015160008151811061159b57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250506115e57f00000000000000000000000000000000000000000000000000000000000000008361192d565b81604001516001815181106115f657fe5b60200260200101906001600160a01b031690816001600160a01b0316815250507f0000000000000000000000000000000000000000000000000000000000000000816040015160028151811061164857fe5b6001600160a01b03909216602092830291909101909101529150505b9392505050565b60006116866c42616e636f724e6574776f726b60981b6110b5565b905090565b60408051636eb1769f60e11b81523060048201526001600160a01b038085166024830152915184926000929087169163dd62ed3e91604480820192602092909190829003018186803b1580156116e057600080fd5b505afa1580156116f4573d6000803e3d6000fd5b505050506040513d602081101561170a57600080fd5b5051905082811015610660578015611731576117316001600160a01b038616836000611bab565b6106606001600160a01b0386168385611bab565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156117b757600080fd5b505afa1580156117cb573d6000803e3d6000fd5b505050506040513d60208110156117e157600080fd5b505160045490915060009061182190620f424090611811908590600160a81b900463ffffffff90811690611cc316565b8161181857fe5b04600554611d1c565b918290039350909150509091565b600082820183811015611889576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b90505b92915050565b620f424063ffffffff821611156118e2576040805162461bcd60e51b815260206004820152600f60248201526e4552525f494e56414c49445f46454560881b604482015290519081900360640190fd5b50565b60006116866e4e6574776f726b53657474696e677360881b6110b5565b60006116867f42616e636f72436f6e76657274657252656769737472790000000000000000006110b5565b60408051600280825260608083018452600093909291906020830190803683370190505090507f00000000000000000000000000000000000000000000000000000000000000008160008151811061198157fe5b60200260200101906001600160a01b031690816001600160a01b03168152505083816001815181106119af57fe5b6001600160a01b03929092166020928302919091019091015260408051600280825260608281019093528160200160208202803683370190505090506002620f424004816000815181106119ff57fe5b63ffffffff909216602092830291909101909101526002620f42400481600181518110611a2857fe5b602002602001019063ffffffff16908163ffffffff16815250506000846001600160a01b0316631d3fccd5600385856040518463ffffffff1660e01b8152600401808461ffff1681526020018060200180602001838103835285818151815260200191508051906020019060200280838360005b83811015611ab4578181015183820152602001611a9c565b50505050905001838103825284818151815260200191508051906020019060200280838360005b83811015611af3578181015183820152602001611adb565b505050509050019550505050505060206040518083038186803b158015611b1957600080fd5b505afa158015611b2d573d6000803e3d6000fd5b505050506040513d6020811015611b4357600080fd5b505190506001600160a01b038116611ba2576040805162461bcd60e51b815260206004820152601960248201527f4552525f494e56414c49445f524553455256455f544f4b454e00000000000000604482015290519081900360640190fd5b95945050505050565b801580611c31575060408051636eb1769f60e11b81523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b158015611c0357600080fd5b505afa158015611c17573d6000803e3d6000fd5b505050506040513d6020811015611c2d57600080fd5b5051155b611c6c5760405162461bcd60e51b81526004018080602001828103825260368152602001806120936036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b179052611cbe908490611d32565b505050565b600082611cd25750600061188c565b82820282848281611cdf57fe5b04146118895760405162461bcd60e51b81526004018080602001828103825260218152602001806120486021913960400191505060405180910390fd5b6000818310611d2b5781611889565b5090919050565b6060611d87826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611de39092919063ffffffff16565b805190915015611cbe57808060200190516020811015611da657600080fd5b5051611cbe5760405162461bcd60e51b815260040180806020018281038252602a815260200180612069602a913960400191505060405180910390fd5b6060611df28484600085611dfa565b949350505050565b606082471015611e3b5760405162461bcd60e51b81526004018080602001828103825260268152602001806120226026913960400191505060405180910390fd5b611e4485611f56565b611e95576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b60208310611ed45780518252601f199092019160209182019101611eb5565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114611f36576040519150601f19603f3d011682016040523d82523d6000602084013e611f3b565b606091505b5091509150611f4b828286611f5c565b979650505050505050565b3b151590565b60608315611f6b575081611664565b825115611f7b5782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611fc5578181015183820152602001611fad565b50505050905090810190601f168015611ff25780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b6040518060600160405280606081526020016060815260200160608152509056fe416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a26469706673582212205c93e79cd457517d74738ab237b1eb16214875fc1e4e30f15fbccab69859989464736f6c634300060c00330000000000000000000000001f573d6fb3f13d689ff844b4ce37794d79a7ff1c0000000000000000000000000887ae1251e180d7d453aedebee26e1639f2011300000000000000000000000052ae12abe5d8bd778bd5397f99ca900624cfadd4

Deployed Bytecode

0x6080604052600436106100f75760003560e01c8063769b90b91161008a578063afd25caa11610059578063afd25caa14610321578063b4a176d314610336578063d4ee1d901461034b578063f2fde38b14610360576100fe565b8063769b90b9146102ac57806379ba5097146102e25780637b103999146102f75780638da5cb5b1461030c576100fe565b806349d10b64116100c657806349d10b64146101b65780634aca7fb2146101cb57806361cd756e146101fe5780636c5d61561461022f576100fe565b8063024c7ec71461010357806302a79454146101315780632fe8a6ad1461016657806335ab5f641461018f576100fe565b366100fe57005b600080fd5b34801561010f57600080fd5b5061012f6004803603602081101561012657600080fd5b50351515610393565b005b34801561013d57600080fd5b506101466103b9565b6040805163ffffffff909316835260208301919091528051918290030190f35b34801561017257600080fd5b5061017b6103d0565b604080519115158252519081900360200190f35b34801561019b57600080fd5b506101a46103e0565b60408051918252519081900360200190f35b3480156101c257600080fd5b5061012f6103e6565b3480156101d757600080fd5b5061012f600480360360208110156101ee57600080fd5b50356001600160a01b03166105ee565b34801561020a57600080fd5b50610213610667565b604080516001600160a01b039092168252519081900360200190f35b34801561023b57600080fd5b5061012f6004803603602081101561025257600080fd5b81019060208101813564010000000081111561026d57600080fd5b82018360208201111561027f57600080fd5b803590602001918460208302840111640100000000831117156102a157600080fd5b509092509050610676565b3480156102b857600080fd5b5061012f600480360360408110156102cf57600080fd5b5063ffffffff8135169060200135610dd5565b3480156102ee57600080fd5b5061012f610e6e565b34801561030357600080fd5b50610213610f25565b34801561031857600080fd5b50610213610f34565b34801561032d57600080fd5b5061012f610f43565b34801561034257600080fd5b5061012f610fa7565b34801561035757600080fd5b50610213610fd3565b34801561036c57600080fd5b5061012f6004803603602081101561038357600080fd5b50356001600160a01b0316610fe2565b61039b611060565b60048054911515600160a01b0260ff60a01b19909216919091179055565b600454600554600160a81b90910463ffffffff1691565b600454600160a01b900460ff1681565b60065490565b6000546001600160a01b03163314806104095750600454600160a01b900460ff16155b61044e576040805162461bcd60e51b815260206004820152601160248201527011549497d050d0d154d4d7d11153925151607a1b604482015290519081900360640190fd5b600061046c6f436f6e7472616374526567697374727960801b6110b5565b6003549091506001600160a01b0380831691161480159061049557506001600160a01b03811615155b6104dd576040805162461bcd60e51b81526020600482015260146024820152734552525f494e56414c49445f524547495354525960601b604482015290519081900360640190fd5b60006001600160a01b0316816001600160a01b031663bb34534c6f436f6e7472616374526567697374727960801b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561053f57600080fd5b505afa158015610553573d6000803e3d6000fd5b505050506040513d602081101561056957600080fd5b50516001600160a01b031614156105be576040805162461bcd60e51b81526020600482015260146024820152734552525f494e56414c49445f524547495354525960601b604482015290519081900360640190fd5b60038054600480546001600160a01b038084166001600160a01b0319928316179092559091169216919091179055565b6105f6611060565b6105fe611133565b6001600160a01b031663f2fde38b826040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050600060405180830381600087803b15801561064c57600080fd5b505af1158015610660573d6000803e3d6000fd5b5050505050565b6004546001600160a01b031681565b61067e6111a6565b60028055600061068c611133565b9050610696612000565b6106a18484846111ee565b9050816001600160a01b03166308506df785853085602001516040518563ffffffff1660e01b81526004018080602001846001600160a01b031681526020018060200183810383528787828181526020019250602002808284376000838201819052601f909101601f1916909201858103845286518152865160209182019382890193509102908190849084905b8381101561074757818101518382015260200161072f565b505050509050019650505050505050600060405180830381600087803b15801561077057600080fd5b505af1158015610784573d6000803e3d6000fd5b50505050600061079261166b565b905060005b825151811015610a03576000836020015182815181106107b357fe5b6020026020010151905080600014156107cc57506109fb565b6060846000015183815181106107de57fe5b602002602001015190506000816000815181106107f757fe5b6020026020010151905060007f0000000000000000000000001f573d6fb3f13d689ff844b4ce37794d79a7ff1c6001600160a01b0316826001600160a01b0316148061087457507f00000000000000000000000048fb253446873234f2febbf9bdeaa72d9d387f946001600160a01b0316826001600160a01b0316145b1561088257505050506109fb565b6001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156108ae5750826108b9565b6108b982878661168b565b6000866001600160a01b031663b77d239b8386886001306000806040518863ffffffff1660e01b81526004018080602001878152602001868152602001856001600160a01b03168152602001846001600160a01b03168152602001838152602001828103825288818151815260200191508051906020019060200280838360005b8381101561095257818101518382015260200161093a565b505050509050019750505050505050506020604051808303818588803b15801561097b57600080fd5b505af115801561098f573d6000803e3d6000fd5b50505050506040513d60208110156109a657600080fd5b5051604080516001600160a01b03861681526020810188905280820183905290519192507fe6a45eea08a42f7c3f90f290e8ecf15e16174981943adf509fc9ea49808a64c6919081900360600190a150505050505b600101610797565b50600080610a0f611745565b90925090508115610b3657610a457f0000000000000000000000001f573d6fb3f13d689ff844b4ce37794d79a7ff1c848461168b565b826001600160a01b031663b77d239b8560400151846001306000806040518763ffffffff1660e01b81526004018080602001878152602001868152602001856001600160a01b03168152602001846001600160a01b03168152602001838152602001828103825288818151815260200191508051906020019060200280838360005b83811015610adf578181015183820152602001610ac7565b50505050905001975050505050505050602060405180830381600087803b158015610b0957600080fd5b505af1158015610b1d573d6000803e3d6000fd5b505050506040513d6020811015610b3357600080fd5b50505b60007f00000000000000000000000048fb253446873234f2febbf9bdeaa72d9d387f946001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015610ba557600080fd5b505afa158015610bb9573d6000803e3d6000fd5b505050506040513d6020811015610bcf57600080fd5b5051905080610c1c576040805162461bcd60e51b815260206004820152601460248201527311549497d6915493d7d095549397d05353d5539560621b604482015290519081900360640190fd5b600654610c29908261182f565b60065560408051630852cd8d60e31b81526004810183905290516001600160a01b037f0000000000000000000000000887ae1251e180d7d453aedebee26e1639f2011316916342966c6891602480830192600092919082900301818387803b158015610c9457600080fd5b505af1158015610ca8573d6000803e3d6000fd5b505050506000821115610d51576040805163a9059cbb60e01b81523360048201526024810184905290516001600160a01b037f0000000000000000000000001f573d6fb3f13d689ff844b4ce37794d79a7ff1c169163a9059cbb9160448083019260209291908290030181600087803b158015610d2457600080fd5b505af1158015610d38573d6000803e3d6000fd5b505050506040513d6020811015610d4e57600080fd5b50505b7f8d1a3aa2e14a1c054c9817979380a072bdf25ccff4f74e29d40616a716cb538888888486018460405180806020018481526020018381526020018281038252868682818152602001925060200280828437600083820152604051601f909101601f191690920182900397509095505050505050a150506001600255505050505050565b610ddd611060565b81610de781611892565b6004546005546040805163ffffffff600160a81b9094048416815292861660208401528281019190915260608201849052517f71d9eda78517255f4f5f721d1855a56406b2daf72b2beedc9bcdc3f7fcee17539181900360800190a1506004805463ffffffff909316600160a81b0263ffffffff60a81b1990931692909217909155600555565b6001546001600160a01b03163314610ec1576040805162461bcd60e51b815260206004820152601160248201527011549497d050d0d154d4d7d11153925151607a1b604482015290519081900360640190fd5b600154600080546040516001600160a01b0393841693909116917f343765429aea5a34b3ff6a3785a98a5abb2597aca87bfbb58632c173d585373a91a360018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b6003546001600160a01b031681565b6000546001600160a01b031681565b610f4b611060565b610f53611133565b6001600160a01b03166379ba50976040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610f8d57600080fd5b505af1158015610fa1573d6000803e3d6000fd5b50505050565b610faf611060565b600454600380546001600160a01b0319166001600160a01b03909216919091179055565b6001546001600160a01b031681565b610fea611060565b6000546001600160a01b038281169116141561103e576040805162461bcd60e51b815260206004820152600e60248201526d22a9292fa9a0a6a2afa7aba722a960911b604482015290519081900360640190fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031633146110b3576040805162461bcd60e51b815260206004820152601160248201527011549497d050d0d154d4d7d11153925151607a1b604482015290519081900360640190fd5b565b60035460408051632ecd14d360e21b81526004810184905290516000926001600160a01b03169163bb34534c916024808301926020929190829003018186803b15801561110157600080fd5b505afa158015611115573d6000803e3d6000fd5b505050506040513d602081101561112b57600080fd5b505192915050565b600061113d6118e5565b6001600160a01b0316633e4565046040518163ffffffff1660e01b815260040160206040518083038186803b15801561117557600080fd5b505afa158015611189573d6000803e3d6000fd5b505050506040513d602081101561119f57600080fd5b5051905090565b6001600254146110b3576040805162461bcd60e51b815260206004820152600e60248201526d4552525f5245454e5452414e435960901b604482015290519081900360640190fd5b6111f6612000565b6000611200611902565b905061120a612000565b6040805160608101909152808667ffffffffffffffff8111801561122d57600080fd5b5060405190808252806020026020018201604052801561126157816020015b606081526020019060019003908161124c5790505b5081526020018667ffffffffffffffff8111801561127e57600080fd5b506040519080825280602002602001820160405280156112a8578160200160208202803683370190505b5081526040805160038082526080820190925260209283019290919082016060803683375050509052905060005b858110156115685760008787838181106112ec57fe5b905060200201356001600160a01b031690506060600367ffffffffffffffff8111801561131857600080fd5b50604051908082528060200260200182016040528015611342578160200160208202803683370190505b509050818160008151811061135357fe5b6001600160a01b0392831660209182029290920101527f0000000000000000000000001f573d6fb3f13d689ff844b4ce37794d79a7ff1c8116908316148015906113cf57507f00000000000000000000000048fb253446873234f2febbf9bdeaa72d9d387f946001600160a01b0316826001600160a01b031614155b1561145a576113de828661192d565b816001815181106113eb57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250507f0000000000000000000000001f573d6fb3f13d689ff844b4ce37794d79a7ff1c8160028151811061143957fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b808460000151848151811061146b57fe5b60209081029190910101526001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156114c757866001600160a01b031631846020015184815181106114b657fe5b60200260200101818152505061155e565b816001600160a01b03166370a08231886040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561151457600080fd5b505afa158015611528573d6000803e3d6000fd5b505050506040513d602081101561153e57600080fd5b5051602085015180518590811061155157fe5b6020026020010181815250505b50506001016112d6565b507f0000000000000000000000001f573d6fb3f13d689ff844b4ce37794d79a7ff1c816040015160008151811061159b57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250506115e57f00000000000000000000000048fb253446873234f2febbf9bdeaa72d9d387f948361192d565b81604001516001815181106115f657fe5b60200260200101906001600160a01b031690816001600160a01b0316815250507f00000000000000000000000048fb253446873234f2febbf9bdeaa72d9d387f94816040015160028151811061164857fe5b6001600160a01b03909216602092830291909101909101529150505b9392505050565b60006116866c42616e636f724e6574776f726b60981b6110b5565b905090565b60408051636eb1769f60e11b81523060048201526001600160a01b038085166024830152915184926000929087169163dd62ed3e91604480820192602092909190829003018186803b1580156116e057600080fd5b505afa1580156116f4573d6000803e3d6000fd5b505050506040513d602081101561170a57600080fd5b5051905082811015610660578015611731576117316001600160a01b038616836000611bab565b6106606001600160a01b0386168385611bab565b60008060007f0000000000000000000000001f573d6fb3f13d689ff844b4ce37794d79a7ff1c6001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b1580156117b757600080fd5b505afa1580156117cb573d6000803e3d6000fd5b505050506040513d60208110156117e157600080fd5b505160045490915060009061182190620f424090611811908590600160a81b900463ffffffff90811690611cc316565b8161181857fe5b04600554611d1c565b918290039350909150509091565b600082820183811015611889576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b90505b92915050565b620f424063ffffffff821611156118e2576040805162461bcd60e51b815260206004820152600f60248201526e4552525f494e56414c49445f46454560881b604482015290519081900360640190fd5b50565b60006116866e4e6574776f726b53657474696e677360881b6110b5565b60006116867f42616e636f72436f6e76657274657252656769737472790000000000000000006110b5565b60408051600280825260608083018452600093909291906020830190803683370190505090507f0000000000000000000000001f573d6fb3f13d689ff844b4ce37794d79a7ff1c8160008151811061198157fe5b60200260200101906001600160a01b031690816001600160a01b03168152505083816001815181106119af57fe5b6001600160a01b03929092166020928302919091019091015260408051600280825260608281019093528160200160208202803683370190505090506002620f424004816000815181106119ff57fe5b63ffffffff909216602092830291909101909101526002620f42400481600181518110611a2857fe5b602002602001019063ffffffff16908163ffffffff16815250506000846001600160a01b0316631d3fccd5600385856040518463ffffffff1660e01b8152600401808461ffff1681526020018060200180602001838103835285818151815260200191508051906020019060200280838360005b83811015611ab4578181015183820152602001611a9c565b50505050905001838103825284818151815260200191508051906020019060200280838360005b83811015611af3578181015183820152602001611adb565b505050509050019550505050505060206040518083038186803b158015611b1957600080fd5b505afa158015611b2d573d6000803e3d6000fd5b505050506040513d6020811015611b4357600080fd5b505190506001600160a01b038116611ba2576040805162461bcd60e51b815260206004820152601960248201527f4552525f494e56414c49445f524553455256455f544f4b454e00000000000000604482015290519081900360640190fd5b95945050505050565b801580611c31575060408051636eb1769f60e11b81523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b158015611c0357600080fd5b505afa158015611c17573d6000803e3d6000fd5b505050506040513d6020811015611c2d57600080fd5b5051155b611c6c5760405162461bcd60e51b81526004018080602001828103825260368152602001806120936036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b179052611cbe908490611d32565b505050565b600082611cd25750600061188c565b82820282848281611cdf57fe5b04146118895760405162461bcd60e51b81526004018080602001828103825260218152602001806120486021913960400191505060405180910390fd5b6000818310611d2b5781611889565b5090919050565b6060611d87826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611de39092919063ffffffff16565b805190915015611cbe57808060200190516020811015611da657600080fd5b5051611cbe5760405162461bcd60e51b815260040180806020018281038252602a815260200180612069602a913960400191505060405180910390fd5b6060611df28484600085611dfa565b949350505050565b606082471015611e3b5760405162461bcd60e51b81526004018080602001828103825260268152602001806120226026913960400191505060405180910390fd5b611e4485611f56565b611e95576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b60208310611ed45780518252601f199092019160209182019101611eb5565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114611f36576040519150601f19603f3d011682016040523d82523d6000602084013e611f3b565b606091505b5091509150611f4b828286611f5c565b979650505050505050565b3b151590565b60608315611f6b575081611664565b825115611f7b5782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611fc5578181015183820152602001611fad565b50505050905090810190601f168015611ff25780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b6040518060600160405280606081526020016060815260200160608152509056fe416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a26469706673582212205c93e79cd457517d74738ab237b1eb16214875fc1e4e30f15fbccab69859989464736f6c634300060c0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000001f573d6fb3f13d689ff844b4ce37794d79a7ff1c0000000000000000000000000887ae1251e180d7d453aedebee26e1639f2011300000000000000000000000052ae12abe5d8bd778bd5397f99ca900624cfadd4

-----Decoded View---------------
Arg [0] : networkToken (address): 0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C
Arg [1] : govTokenGovernance (address): 0x0887ae1251E180d7D453aeDEBee26e1639f20113
Arg [2] : registry (address): 0x52Ae12ABe5D8BD778BD5397F99cA900624CfADD4

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000001f573d6fb3f13d689ff844b4ce37794d79a7ff1c
Arg [1] : 0000000000000000000000000887ae1251e180d7d453aedebee26e1639f20113
Arg [2] : 00000000000000000000000052ae12abe5d8bd778bd5397f99ca900624cfadd4


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.