ETH Price: $3,373.22 (-1.25%)
Gas: 9 Gwei

Contract

0xBFd4065A7004B1c8DE08e965969E306Be6bE78D4
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Value
Swap188712302023-12-26 17:02:23183 days ago1703610143IN
Emiswap: ESW-USDT
0 ETH0.003873821.59419872
Swap179641052023-08-21 15:50:59310 days ago1692633059IN
Emiswap: ESW-USDT
0 ETH0.0075754545.34460758
Approve169188032023-03-27 12:45:47457 days ago1679921147IN
Emiswap: ESW-USDT
0 ETH0.0006090325.16880945
Approve160720052022-11-29 0:14:59575 days ago1669680899IN
Emiswap: ESW-USDT
0 ETH0.0005161411.1041355
Approve160719142022-11-28 23:56:35575 days ago1669679795IN
Emiswap: ESW-USDT
0 ETH0.000507910.92683424
Approve160718562022-11-28 23:44:59575 days ago1669679099IN
Emiswap: ESW-USDT
0 ETH0.000574212.35336305
Swap152899152022-08-06 16:56:59690 days ago1659805019IN
Emiswap: ESW-USDT
0 ETH0.001091246.72447068
Approve149954382022-06-20 7:59:14737 days ago1655711954IN
Emiswap: ESW-USDT
0 ETH0.0009350920.11732855
Swap149895332022-06-19 7:15:04738 days ago1655622904IN
Emiswap: ESW-USDT
0 ETH0.0034718420.77851406
Swap147631022022-05-12 20:14:06775 days ago1652386446IN
Emiswap: ESW-USDT
0 ETH0.0152352791.18115873
Swap146049662022-04-17 20:42:45800 days ago1650228165IN
Emiswap: ESW-USDT
0 ETH0.0035875820
Approve143586282022-03-10 10:42:12839 days ago1646908932IN
Emiswap: ESW-USDT
0 ETH0.0010062821.64898889
Swap143385772022-03-07 8:08:25842 days ago1646640505IN
Emiswap: ESW-USDT
0 ETH0.0050122830
Approve142417602022-02-20 8:05:57857 days ago1645344357IN
Emiswap: ESW-USDT
0 ETH0.0025610455.09761268
Approve141652842022-02-08 11:55:43869 days ago1644321343IN
Emiswap: ESW-USDT
0 ETH0.0020979845.13539578
Swap139721232022-01-09 15:23:41899 days ago1641741821IN
Emiswap: ESW-USDT
0 ETH0.01872167112.03873618
Swap139254322022-01-02 10:20:18906 days ago1641118818IN
Emiswap: ESW-USDT
0 ETH0.0116174563.08209965
Swap137647592021-12-08 12:20:38931 days ago1638966038IN
Emiswap: ESW-USDT
0 ETH0.0073410367.85
Swap137298752021-12-02 22:14:49936 days ago1638483289IN
Emiswap: ESW-USDT
0 ETH0.0166943490.64934712
Approve136986142021-11-27 22:03:17941 days ago1638050597IN
Emiswap: ESW-USDT
0 ETH0.00526571113.28510773
Swap136568512021-11-21 7:34:41948 days ago1637480081IN
Emiswap: ESW-USDT
0 ETH0.015600384.70235029
Swap136330862021-11-17 13:08:28952 days ago1637154508IN
Emiswap: ESW-USDT
0 ETH0.01875752104.71632283
Swap136329152021-11-17 12:29:12952 days ago1637152152IN
Emiswap: ESW-USDT
0 ETH0.01943053108.45896297
Swap136324462021-11-17 10:38:45952 days ago1637145525IN
Emiswap: ESW-USDT
0 ETH0.02012467115.44208015
Swap136323862021-11-17 10:23:52952 days ago1637144632IN
Emiswap: ESW-USDT
0 ETH0.0146609984.0947706
View all transactions

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To Value
117297972021-01-26 6:46:291247 days ago1611643589  Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Emiswap

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
Yes with 100000 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

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

// File: @openzeppelin/contracts/GSN/Context.sol

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/*
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with GSN meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address payable) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}

// File: @openzeppelin/contracts/access/Ownable.sol

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor () internal {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(_owner == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
}

// 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/math/SafeMath.sol

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, 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) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * 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);
        uint256 c = a - b;

        return c;
    }

    /**
     * @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) {
        // 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 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts 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) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts with custom message 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, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts 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) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message 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, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

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

pragma solidity >=0.6.0 <0.8.0;




/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin guidelines: functions revert instead
 * of returning `false` on failure. This behavior is nonetheless conventional
 * and does not conflict with the expectations of ERC20 applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20 {
    using SafeMath for uint256;

    mapping (address => uint256) private _balances;

    mapping (address => mapping (address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;
    uint8 private _decimals;

    /**
     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with
     * a default value of 18.
     *
     * To select a different value for {decimals}, use {_setupDecimals}.
     *
     * All three of these values are immutable: they can only be set once during
     * construction.
     */
    constructor (string memory name_, string memory symbol_) public {
        _name = name_;
        _symbol = symbol_;
        _decimals = 18;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5,05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is
     * called.
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view returns (uint8) {
        return _decimals;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * Requirements:
     *
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for ``sender``'s tokens of at least
     * `amount`.
     */
    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
        return true;
    }

    /**
     * @dev Moves tokens `amount` from `sender` to `recipient`.
     *
     * This is internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(address sender, address recipient, uint256 amount) internal virtual {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(sender, recipient, amount);

        _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(sender, recipient, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
        _totalSupply = _totalSupply.sub(amount);
        emit Transfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(address owner, address spender, uint256 amount) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Sets {decimals} to a value other than the default one of 18.
     *
     * WARNING: This function should only be called from the constructor. Most
     * applications that interact with token contracts will not expect
     * {decimals} to ever change, and may work incorrectly if it does.
     */
    function _setupDecimals(uint8 decimals_) internal {
        _decimals = decimals_;
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be to transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
}

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

    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: contracts/libraries/UniERC20.sol

pragma solidity ^0.6.0;




library UniERC20 {
    using SafeMath for uint256;
    using SafeERC20 for IERC20;

    function isETH(IERC20 token) internal pure returns (bool) {
        return (address(token) == address(0));
    }

    function uniBalanceOf(IERC20 token, address account)
        internal
        view
        returns (uint256)
    {
        if (isETH(token)) {
            return account.balance;
        } else {
            return token.balanceOf(account);
        }
    }

    function uniTransfer(
        IERC20 token,
        address payable to,
        uint256 amount
    ) internal {
        if (amount > 0) {
            if (isETH(token)) {
                to.transfer(amount);
            } else {
                token.safeTransfer(to, amount);
            }
        }
    }

    function uniTransferFromSenderToThis(IERC20 token, uint256 amount)
        internal
    {
        if (amount > 0) {
            if (isETH(token)) {
                require(msg.value >= amount, "UniERC20: not enough value");
                if (msg.value > amount) {
                    // Return remainder if exist
                    msg.sender.transfer(msg.value.sub(amount));
                }
            } else {
                token.safeTransferFrom(msg.sender, address(this), amount);
            }
        }
    }

    function uniSymbol(IERC20 token) internal view returns (string memory) {
        if (isETH(token)) {
            return "ETH";
        }

        (bool success, bytes memory data) =
            address(token).staticcall{gas: 20000}(
                abi.encodeWithSignature("symbol()")
            );
        if (!success) {
            (success, data) = address(token).staticcall{gas: 20000}(
                abi.encodeWithSignature("SYMBOL()")
            );
        }

        if (success && data.length >= 96) {
            (uint256 offset, uint256 len) =
                abi.decode(data, (uint256, uint256));
            if (offset == 0x20 && len > 0 && len <= 256) {
                return string(abi.decode(data, (bytes)));
            }
        }

        if (success && data.length == 32) {
            uint256 len = 0;
            while (
                len < data.length && data[len] >= 0x20 && data[len] <= 0x7E
            ) {
                len++;
            }

            if (len > 0) {
                bytes memory result = new bytes(len);
                for (uint256 i = 0; i < len; i++) {
                    result[i] = data[i];
                }
                return string(result);
            }
        }

        return _toHex(address(token));
    }

    function _toHex(address account) private pure returns (string memory) {
        return _toHex(abi.encodePacked(account));
    }

    function _toHex(bytes memory data) private pure returns (string memory) {
        bytes memory str = new bytes(2 + data.length * 2);
        str[0] = "0";
        str[1] = "x";
        uint256 j = 2;
        for (uint256 i = 0; i < data.length; i++) {
            uint256 a = uint8(data[i]) >> 4;
            uint256 b = uint8(data[i]) & 0x0f;
            str[j++] = bytes1(uint8(a + 48 + (a / 10) * 39));
            str[j++] = bytes1(uint8(b + 48 + (b / 10) * 39));
        }

        return string(str);
    }
}

// File: contracts/interfaces/IEmiswap.sol

pragma solidity ^0.6.0;


interface IEmiswapRegistry {
    function pools(IERC20 token1, IERC20 token2)
        external
        view
        returns (IEmiswap);

    function isPool(address addr) external view returns (bool);

    function deploy(IERC20 tokenA, IERC20 tokenB) external returns (IEmiswap);
}

interface IEmiswap {
    function fee() external view returns (uint256);

    function tokens(uint256 i) external view returns (IERC20);

    function deposit(
        uint256[] calldata amounts,
        uint256[] calldata minAmounts,
        address referral
    ) external payable returns (uint256 fairSupply);

    function withdraw(uint256 amount, uint256[] calldata minReturns) external;

    function getBalanceForAddition(IERC20 token)
        external
        view
        returns (uint256);

    function getBalanceForRemoval(IERC20 token) external view returns (uint256);

    function getReturn(
        IERC20 fromToken,
        IERC20 destToken,
        uint256 amount
    ) external view returns (uint256 returnAmount);

    function swap(
        IERC20 fromToken,
        IERC20 destToken,
        uint256 amount,
        uint256 minReturn,
        address to,
        address referral
    ) external payable returns (uint256 returnAmount);

    function initialize(IERC20[] calldata assets) external;
}

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

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor () internal {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

// 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: contracts/libraries/Sqrt.sol

pragma solidity ^0.6.0;

library Sqrt {
    // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method)
    function sqrt(uint256 y) internal pure returns (uint256) {
        if (y > 3) {
            uint256 z = y;
            uint256 x = y / 2 + 1;
            while (x < z) {
                z = x;
                x = (y / x + x) / 2;
            }
            return z;
        } else if (y != 0) {
            return 1;
        } else {
            return 0;
        }
    }
}

// File: contracts/Emiswap.sol

pragma solidity ^0.6.0;








interface IFactory {
    function fee() external view returns (uint256);

    function feeVault() external view returns (uint256);

    function addressVault() external view returns (address);
}

library VirtualBalance {
    using SafeMath for uint256;

    struct Data {
        uint216 balance;
        uint40 time;
    }

    uint256 public constant DECAY_PERIOD = 5 minutes;

    function set(VirtualBalance.Data storage self, uint256 balance) internal {
        self.balance = uint216(balance);
        self.time = uint40(block.timestamp);
    }

    function update(VirtualBalance.Data storage self, uint256 realBalance)
        internal
    {
        set(self, current(self, realBalance));
    }

    function scale(
        VirtualBalance.Data storage self,
        uint256 realBalance,
        uint256 num,
        uint256 denom
    ) internal {
        set(
            self,
            current(self, realBalance).mul(num).add(denom.sub(1)).div(denom)
        );
    }

    function current(VirtualBalance.Data memory self, uint256 realBalance)
        internal
        view
        returns (uint256)
    {
        uint256 timePassed =
            Math.min(DECAY_PERIOD, block.timestamp.sub(self.time));
        uint256 timeRemain = DECAY_PERIOD.sub(timePassed);
        return
            uint256(self.balance)
                .mul(timeRemain)
                .add(realBalance.mul(timePassed))
                .div(DECAY_PERIOD);
    }
}

contract Emiswap is ERC20, ReentrancyGuard, Ownable {
    using Sqrt for uint256;
    using SafeMath for uint256;
    using UniERC20 for IERC20;
    using VirtualBalance for VirtualBalance.Data;

    struct Balances {
        uint256 src;
        uint256 dst;
    }

    struct SwapVolumes {
        uint128 confirmed;
        uint128 result;
    }

    event Deposited(address indexed account, uint256 amount, address referral);

    event Withdrawn(address indexed account, uint256 amount);

    event Swapped(
        address indexed account,
        address indexed src,
        address indexed dst,
        uint256 amount,
        uint256 result,
        uint256 srcBalance,
        uint256 dstBalance,
        uint256 totalSupply,
        address referral
    );

    event Swapped2(
        address indexed account,
        address indexed to,
        uint256 resultVault
    );

    uint256 public constant REFERRAL_SHARE = 20; // 1/share = 5% of LPs revenue
    uint256 public constant BASE_SUPPLY = 1000; // Total supply on first deposit
    uint256 public constant FEE_DENOMINATOR = 1e18;

    IFactory public factory;
    IERC20[] public tokens;
    mapping(IERC20 => bool) public isToken;
    mapping(IERC20 => SwapVolumes) public volumes;
    mapping(IERC20 => VirtualBalance.Data) public virtualBalancesForAddition;
    mapping(IERC20 => VirtualBalance.Data) public virtualBalancesForRemoval;

    constructor() public ERC20("Emiswap LP token", "EMI LP") {
        factory = IFactory(msg.sender);
    }

    // called once by the factory at time of deployment
    function initialize(IERC20[] calldata assets) external {
        require(msg.sender == address(factory), "Emiswap: FORBIDDEN"); // sufficient check
        require(assets.length == 2, "Emiswap: only 2 tokens allowed");

        tokens = assets;
        for (uint256 i = 0; i < assets.length; i++) {
            require(!isToken[assets[i]], "Emiswap: duplicate tokens");
            isToken[assets[i]] = true;
        }
    }

    function fee() public view returns (uint256) {
        return factory.fee();
    }

    function feeVault() public view returns (uint256) {
        return factory.feeVault();
    }

    function addressVault() public view returns (address) {
        return factory.addressVault();
    }

    function getTokens() external view returns (IERC20[] memory) {
        return tokens;
    }

    function decayPeriod() external pure returns (uint256) {
        return VirtualBalance.DECAY_PERIOD;
    }

    function getBalanceForAddition(IERC20 token) public view returns (uint256) {
        uint256 balance = token.uniBalanceOf(address(this));
        return
            Math.max(
                virtualBalancesForAddition[token].current(balance),
                balance
            );
    }

    function getBalanceForRemoval(IERC20 token) public view returns (uint256) {
        uint256 balance = token.uniBalanceOf(address(this));
        return
            Math.min(
                virtualBalancesForRemoval[token].current(balance),
                balance
            );
    }

    function getReturn(
        IERC20 src,
        IERC20 dst,
        uint256 amount
    ) external view returns (uint256, uint256) {
        return
            _getReturn(
                src,
                dst,
                amount,
                getBalanceForAddition(src),
                getBalanceForRemoval(dst)
            );
    }

    function deposit(
        uint256[] calldata amounts,
        uint256[] calldata minAmounts,
        address referral
    ) external nonReentrant returns (uint256 fairSupply) {
        IERC20[] memory _tokens = tokens;
        require(
            (amounts.length > 0) && (amounts.length == _tokens.length),
            "Emiswap: wrong amounts length"
        );
        require(
            (amounts[0] > 0) && (amounts[1] > 0),
            "Emiswap: wrong value usage"
        );

        uint256[] memory realBalances = new uint256[](amounts.length);
        for (uint256 i = 0; i < realBalances.length; i++) {
            realBalances[i] = _tokens[i].uniBalanceOf(address(this));
        }

        uint256 totalSupply = totalSupply();
        if (totalSupply == 0) {
            fairSupply = BASE_SUPPLY.mul(99);
            _mint(address(this), BASE_SUPPLY); // Donate up to 1%

            // Use the greatest token amount but not less than 99k for the initial supply
            for (uint256 i = 0; i < amounts.length; i++) {
                fairSupply = Math.max(fairSupply, amounts[i]);
            }
        } else {
            // Pre-compute fair supply
            fairSupply = type(uint256).max;
            for (uint256 i = 0; i < amounts.length; i++) {
                fairSupply = Math.min(
                    fairSupply,
                    totalSupply.mul(amounts[i]).div(realBalances[i])
                );
            }
        }

        uint256 fairSupplyCached = fairSupply;
        for (uint256 i = 0; i < amounts.length; i++) {
            require(amounts[i] > 0, "Emiswap: amount is zero");
            uint256 amount =
                (totalSupply == 0)
                    ? amounts[i]
                    : realBalances[i]
                        .mul(fairSupplyCached)
                        .add(totalSupply - 1)
                        .div(totalSupply);
            require(amount >= minAmounts[i], "Emiswap: minAmount not reached");

            _tokens[i].uniTransferFromSenderToThis(amount);
            if (totalSupply > 0) {
                uint256 confirmed =
                    _tokens[i].uniBalanceOf(address(this)).sub(realBalances[i]);
                fairSupply = Math.min(
                    fairSupply,
                    totalSupply.mul(confirmed).div(realBalances[i])
                );
            }
        }

        if (totalSupply > 0) {
            for (uint256 i = 0; i < amounts.length; i++) {
                virtualBalancesForRemoval[_tokens[i]].scale(
                    realBalances[i],
                    totalSupply.add(fairSupply),
                    totalSupply
                );
                virtualBalancesForAddition[_tokens[i]].scale(
                    realBalances[i],
                    totalSupply.add(fairSupply),
                    totalSupply
                );
            }
        }

        require(fairSupply > 0, "Emniswap: result is not enough");
        _mint(msg.sender, fairSupply);

        emit Deposited(msg.sender, fairSupply, referral);
    }

    function withdraw(uint256 amount, uint256[] calldata minReturns)
        external
        nonReentrant
    {
        uint256 totalSupply = totalSupply();
        _burn(msg.sender, amount);

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

            uint256 preBalance = token.uniBalanceOf(address(this));
            uint256 value = preBalance.mul(amount).div(totalSupply);
            token.uniTransfer(msg.sender, value);
            require(
                i >= minReturns.length || value >= minReturns[i],
                "Emiswap: result is not enough"
            );

            virtualBalancesForAddition[token].scale(
                preBalance,
                totalSupply.sub(amount),
                totalSupply
            );
            virtualBalancesForRemoval[token].scale(
                preBalance,
                totalSupply.sub(amount),
                totalSupply
            );
        }

        emit Withdrawn(msg.sender, amount);
    }

    function swap(
        IERC20 src,
        IERC20 dst,
        uint256 amount,
        uint256 minReturn,
        address to,
        address referral
    ) external nonReentrant returns (uint256 result) {
        require(address(src) != address(0), "Emiswap: only tokens allowed");

        Balances memory balances =
            Balances({
                src: src.uniBalanceOf(address(this)),
                dst: dst.uniBalanceOf(address(this))
            });

        // catch possible airdrops and external balance changes for deflationary tokens
        uint256 srcAdditionBalance =
            Math.max(
                virtualBalancesForAddition[src].current(balances.src),
                balances.src
            );
        uint256 dstRemovalBalance =
            Math.min(
                virtualBalancesForRemoval[dst].current(balances.dst),
                balances.dst
            );

        src.uniTransferFromSenderToThis(amount);
        uint256 confirmed = src.uniBalanceOf(address(this)).sub(balances.src);

        uint256 resultVault;
        (result, resultVault) = _getReturn(
            src,
            dst,
            confirmed,
            srcAdditionBalance,
            dstRemovalBalance
        );
        require(
            result > 0 && result >= minReturn,
            "Emiswap: return is not enough"
        );
        dst.uniTransfer(payable(to), result);
        if (resultVault > 0) {
            dst.uniTransfer(payable(addressVault()), resultVault);
        }

        // Update virtual balances to the same direction only at imbalanced state
        if (srcAdditionBalance != balances.src) {
            virtualBalancesForAddition[src].set(
                srcAdditionBalance.add(confirmed)
            );
        }
        if (dstRemovalBalance != balances.dst) {
            virtualBalancesForRemoval[dst].set(dstRemovalBalance.sub(result));
        }

        // Update virtual balances to the opposite direction
        virtualBalancesForRemoval[src].update(balances.src);
        virtualBalancesForAddition[dst].update(balances.dst);

        emit Swapped(
            msg.sender,
            address(src),
            address(dst),
            confirmed,
            result,
            balances.src,
            balances.dst,
            totalSupply(),
            referral
        );
        emit Swapped2(msg.sender, to, resultVault);

        // Overflow of uint128 is desired
        volumes[src].confirmed += uint128(confirmed);
        volumes[src].result += uint128(result);
    }

    function rescueFunds(IERC20 token, uint256 amount)
        external
        nonReentrant
        onlyOwner
    {
        uint256[] memory balances = new uint256[](tokens.length);
        for (uint256 i = 0; i < balances.length; i++) {
            balances[i] = tokens[i].uniBalanceOf(address(this));
        }

        token.uniTransfer(msg.sender, amount);

        for (uint256 i = 0; i < balances.length; i++) {
            require(
                tokens[i].uniBalanceOf(address(this)) >= balances[i],
                "Emiswap: access denied"
            );
        }
        require(
            balanceOf(address(this)) >= BASE_SUPPLY,
            "Emiswap: access denied"
        );
    }

    function _getReturn(
        IERC20 src,
        IERC20 dst,
        uint256 amount,
        uint256 srcBalance,
        uint256 dstBalance
    ) internal view returns (uint256, uint256) {
        if (isToken[src] && isToken[dst] && src != dst && amount > 0) {
            uint256 taxedAmount =
                amount.sub(amount.mul(fee()).div(FEE_DENOMINATOR));
            uint256 resWFee =
                taxedAmount.mul(dstBalance).div(srcBalance.add(taxedAmount));
            uint256 resWOFee =
                amount.mul(dstBalance).div(srcBalance.add(amount));
            uint256 resVault =
                (
                    feeVault() == 0
                        ? 0
                        : resWOFee.sub(resWFee).div(fee().div(feeVault()))
                );

            return (resWFee, resVault);
        }
    }
}

// File: contracts/EmiFactory.sol

pragma solidity ^0.6.0;






contract EmiFactory is Ownable {
    using UniERC20 for IERC20;

    mapping(address => bool) private _adminTable;

    modifier onlyAdmin() {
        require(_adminTable[msg.sender], "Admin: caller is not admin");
        _;
    }

    event Deployed(
        address indexed emiswap,
        address indexed token1,
        address indexed token2
    );

    event adminGranted(address indexed admin, bool isGranted);

    uint256 public constant MAX_FEE = 0.003e18; // 0.3%

    uint256 public fee;
    uint256 public feeVault;
    address public addressVault;
    Emiswap[] public allPools;
    mapping(Emiswap => bool) public isPool;
    mapping(IERC20 => mapping(IERC20 => Emiswap)) public pools;

    function getAllPools() external view returns (Emiswap[] memory) {
        return allPools;
    }

    function setFee(uint256 newFee) external onlyAdmin {
        require(newFee <= MAX_FEE, "Factory: fee should be <= 0.3%");
        fee = newFee;
    }

    function setFeeVault(uint256 newFeeVault) external onlyAdmin {
        require(newFeeVault < fee, "Factory: vault fee");
        feeVault = newFeeVault;
    }

    function setaddressVault(address newAddressVault) external onlyAdmin {
        require(newAddressVault != address(0), "Factory: vault");
        addressVault = newAddressVault;
    }

    function setAdminGrant(address newAdmin, bool isGranted)
        external
        onlyOwner
    {
        require(newAdmin != address(0), "Admin address 0");
        _adminTable[newAdmin] = isGranted;
        emit adminGranted(newAdmin, isGranted);
    }

    function deploy(IERC20 tokenA, IERC20 tokenB)
        external
        returns (Emiswap pool)
    {
        require(
            address(tokenA) != address(0) && address(tokenB) != address(0),
            "Factory:no 0x address"
        );
        require(tokenA != tokenB, "Factory:no same tokens");
        require(
            pools[tokenA][tokenB] == Emiswap(0),
            "Factory:pool already exists"
        );

        (IERC20 token1, IERC20 token2) = sortTokens(tokenA, tokenB);
        IERC20[] memory tokens = new IERC20[](2);
        tokens[0] = token1;
        tokens[1] = token2;

        /////////// abi.encodePacked(bytecode, abi.encode(arg1, arg2))
        bytes memory bytecode = abi.encodePacked(type(Emiswap).creationCode);

        bytes32 salt = keccak256(abi.encodePacked(token1, token2));
        assembly {
            pool := create2(0, add(bytecode, 32), mload(bytecode), salt)
        }
        Emiswap(pool).initialize(tokens);

        pool.transferOwnership(owner());
        pools[token1][token2] = pool;
        pools[token2][token1] = pool;
        allPools.push(pool);
        isPool[pool] = true;

        emit Deployed(address(pool), address(token1), address(token2));
    }

    function sortTokens(IERC20 tokenA, IERC20 tokenB)
        public
        pure
        returns (IERC20, IERC20)
    {
        if (tokenA < tokenB) {
            return (tokenA, tokenB);
        }
        return (tokenB, tokenA);
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"referral","type":"address"}],"name":"Deposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"src","type":"address"},{"indexed":true,"internalType":"address","name":"dst","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"result","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"srcBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dstBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalSupply","type":"uint256"},{"indexed":false,"internalType":"address","name":"referral","type":"address"}],"name":"Swapped","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"resultVault","type":"uint256"}],"name":"Swapped2","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[],"name":"BASE_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REFERRAL_SHARE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"addressVault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decayPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"uint256[]","name":"minAmounts","type":"uint256[]"},{"internalType":"address","name":"referral","type":"address"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"fairSupply","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"contract IFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeVault","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"}],"name":"getBalanceForAddition","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"}],"name":"getBalanceForRemoval","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"src","type":"address"},{"internalType":"contract IERC20","name":"dst","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"getReturn","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTokens","outputs":[{"internalType":"contract IERC20[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20[]","name":"assets","type":"address[]"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"name":"isToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"rescueFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"src","type":"address"},{"internalType":"contract IERC20","name":"dst","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minReturn","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"referral","type":"address"}],"name":"swap","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokens","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"name":"virtualBalancesForAddition","outputs":[{"internalType":"uint216","name":"balance","type":"uint216"},{"internalType":"uint40","name":"time","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"name":"virtualBalancesForRemoval","outputs":[{"internalType":"uint216","name":"balance","type":"uint216"},{"internalType":"uint40","name":"time","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"name":"volumes","outputs":[{"internalType":"uint128","name":"confirmed","type":"uint128"},{"internalType":"uint128","name":"result","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256[]","name":"minReturns","type":"uint256[]"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040523480156200001157600080fd5b50604080518082018252601081526f22b6b4b9bbb0b8102628103a37b5b2b760811b6020808301918252835180850190945260068452650454d49204c560d41b908401528151919291620000689160039162000109565b5080516200007e90600490602084019062000109565b50506005805460ff1916601217905550600160065560006200009f62000105565b600780546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350600880546001600160a01b03191633179055620001a5565b3390565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200014c57805160ff19168380011785556200017c565b828001600101855582156200017c579182015b828111156200017c5782518255916020019190600101906200015f565b506200018a9291506200018e565b5090565b5b808211156200018a57600081556001016200018f565b613f7680620001b56000396000f3fe608060405234801561001057600080fd5b506004361061025c5760003560e01c80637dc2038211610145578063b21b5a21116100bd578063d7d3aab51161008c578063ddca3f4311610071578063ddca3f43146109d7578063e7ff42c9146109df578063f2fde38b14610a125761025c565b8063d7d3aab514610969578063dd62ed3e1461099c5761025c565b8063b21b5a2114610949578063baf13a0a14610951578063c45a015514610959578063d73792a9146109615761025c565b8063a224cee711610114578063a9059cbb116100f9578063a9059cbb14610844578063aa6ca8081461087d578063b1ec4c40146108d55761025c565b8063a224cee71461079b578063a457c2d71461080b5761025c565b80637dc203821461065c5780637e067a60146106b35780638da5cb5b1461078b57806395d89b41146107935761025c565b806348d67e1b116101d85780635ed9156d116101a757806370a082311161018c57806370a08231146105e8578063715018a61461061b57806378e3214f146106235761025c565b80635ed9156d146105455780636edc2c09146105b55761025c565b806348d67e1b146104765780634f64b2be1461047e57806356929070146104c45780635915d806146104cc5761025c565b80631e1401f81161022f578063313ce56711610214578063313ce567146104175780633950935114610435578063478222c21461046e5761025c565b80631e1401f81461037857806323b872dd146103d45761025c565b806306fdde0314610261578063095ea7b3146102de57806318160ddd1461032b57806319f3736114610345575b600080fd5b610269610a45565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102a357818101518382015260200161028b565b50505050905090810190601f1680156102d05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610317600480360360408110156102f457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610af9565b604080519115158252519081900360200190f35b610333610b17565b60408051918252519081900360200190f35b6103176004803603602081101561035b57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610b1d565b6103bb6004803603606081101561038e57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135610b32565b6040805192835260208301919091528051918290030190f35b610317600480360360608110156103ea57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135610b5e565b61041f610c00565b6040805160ff9092168252519081900360200190f35b6103176004803603604081101561044b57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610c09565b610333610c64565b610333610d00565b61049b6004803603602081101561049457600080fd5b5035610d06565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b61049b610d3a565b610543600480360360408110156104e257600080fd5b8135919081019060408101602082013564010000000081111561050457600080fd5b82018360208201111561051657600080fd5b8035906020019184602083028401116401000000008311171561053857600080fd5b509092509050610da5565b005b6105786004803603602081101561055b57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611005565b604080517affffffffffffffffffffffffffffffffffffffffffffffffffffff909316835264ffffffffff90911660208301528051918290030190f35b610578600480360360208110156105cb57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661105c565b610333600480360360208110156105fe57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166110b3565b6105436110db565b6105436004803603604081101561063957600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356111db565b610333600480360360c081101561067257600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020810135821691604082013591606081013591608082013581169160a00135166114dc565b610333600480360360608110156106c957600080fd5b8101906020810181356401000000008111156106e457600080fd5b8201836020820111156106f657600080fd5b8035906020019184602083028401116401000000008311171561071857600080fd5b91939092909160208101903564010000000081111561073657600080fd5b82018360208201111561074857600080fd5b8035906020019184602083028401116401000000008311171561076a57600080fd5b91935091503573ffffffffffffffffffffffffffffffffffffffff16611b2d565b61049b61228d565b6102696122a9565b610543600480360360208110156107b157600080fd5b8101906020810181356401000000008111156107cc57600080fd5b8201836020820111156107de57600080fd5b8035906020019184602083028401116401000000008311171561080057600080fd5b509092509050612328565b6103176004803603604081101561082157600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013561255f565b6103176004803603604081101561085a57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356125d4565b6108856125e8565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156108c15781810151838201526020016108a9565b505050509050019250505060405180910390f35b610908600480360360208110156108eb57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612656565b60405180836fffffffffffffffffffffffffffffffff168152602001826fffffffffffffffffffffffffffffffff1681526020019250505060405180910390f35b610333612692565b610333612697565b61049b61269d565b6103336126b9565b6103336004803603602081101561097f57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166126c5565b610333600480360360408110156109b257600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602001351661277b565b6103336127b3565b610333600480360360208110156109f557600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661281e565b61054360048036036020811015610a2857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166128d4565b60038054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610aef5780601f10610ac457610100808354040283529160200191610aef565b820191906000526020600020905b815481529060010190602001808311610ad257829003601f168201915b5050505050905090565b6000610b0d610b06612a5f565b8484612a63565b5060015b92915050565b60025490565b600a6020526000908152604090205460ff1681565b600080610b52858585610b44896126c5565b610b4d8961281e565b612baa565b91509150935093915050565b6000610b6b848484612d01565b610bf584610b77612a5f565b610bf085604051806060016040528060288152602001613e606028913973ffffffffffffffffffffffffffffffffffffffff8a16600090815260016020526040812090610bc2612a5f565b73ffffffffffffffffffffffffffffffffffffffff1681526020810191909152604001600020549190612ed1565b612a63565b5060015b9392505050565b60055460ff1690565b6000610b0d610c16612a5f565b84610bf08560016000610c27612a5f565b73ffffffffffffffffffffffffffffffffffffffff908116825260208083019390935260409182016000908120918c168152925290205490612f82565b600854604080517f478222c2000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163478222c2916004808301926020929190829003018186803b158015610ccf57600080fd5b505afa158015610ce3573d6000803e3d6000fd5b505050506040513d6020811015610cf957600080fd5b5051905090565b61012c90565b60098181548110610d1357fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b600854604080517f56929070000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff16916356929070916004808301926020929190829003018186803b158015610ccf57600080fd5b60026006541415610e1757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026006556000610e26610b17565b9050610e323385612ff6565b60005b600954811015610fc357600060098281548110610e4e57fe5b600091825260208220015473ffffffffffffffffffffffffffffffffffffffff169150610e7b8230613140565b90506000610e9385610e8d848b613208565b9061327b565b9050610eb673ffffffffffffffffffffffffffffffffffffffff841633836132bd565b8584101580610ed75750868685818110610ecc57fe5b905060200201358110155b610f4257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f456d69737761703a20726573756c74206973206e6f7420656e6f756768000000604482015290519081900360640190fd5b610f7d82610f50878b61333b565b73ffffffffffffffffffffffffffffffffffffffff86166000908152600c6020526040902091908861337d565b610fb882610f8b878b61333b565b73ffffffffffffffffffffffffffffffffffffffff86166000908152600d6020526040902091908861337d565b505050600101610e35565b5060408051858152905133917f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d5919081900360200190a2505060016006555050565b600d602052600090815260409020547affffffffffffffffffffffffffffffffffffffffffffffffffffff8116907b01000000000000000000000000000000000000000000000000000000900464ffffffffff1682565b600c602052600090815260409020547affffffffffffffffffffffffffffffffffffffffffffffffffffff8116907b01000000000000000000000000000000000000000000000000000000900464ffffffffff1682565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6110e3612a5f565b60075473ffffffffffffffffffffffffffffffffffffffff90811691161461116c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60075460405160009173ffffffffffffffffffffffffffffffffffffffff16907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600780547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b6002600654141561124d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260065561125a612a5f565b60075473ffffffffffffffffffffffffffffffffffffffff9081169116146112e357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60095460609067ffffffffffffffff811180156112ff57600080fd5b50604051908082528060200260200182016040528015611329578160200160208202803683370190505b50905060005b815181101561139057611371306009838154811061134957fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1690613140565b82828151811061137d57fe5b602090810291909101015260010161132f565b506113b273ffffffffffffffffffffffffffffffffffffffff841633846132bd565b60005b8151811015611458578181815181106113ca57fe5b60200260200101516113e3306009848154811061134957fe5b101561145057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f456d69737761703a206163636573732064656e69656400000000000000000000604482015290519081900360640190fd5b6001016113b5565b506103e8611465306110b3565b10156114d257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f456d69737761703a206163636573732064656e69656400000000000000000000604482015290519081900360640190fd5b5050600160065550565b60006002600654141561155057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260065573ffffffffffffffffffffffffffffffffffffffff87166115d757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f456d69737761703a206f6e6c7920746f6b656e7320616c6c6f77656400000000604482015290519081900360640190fd5b6115df613c8c565b604080518082019091528061160a73ffffffffffffffffffffffffffffffffffffffff8b1630613140565b815260200161162f73ffffffffffffffffffffffffffffffffffffffff8a1630613140565b9052805173ffffffffffffffffffffffffffffffffffffffff8a166000908152600c602090815260408083208151808301909252547affffffffffffffffffffffffffffffffffffffffffffffffffffff811682527b01000000000000000000000000000000000000000000000000000000900464ffffffffff1691810191909152929350916116ca916116c3919061340b565b8351613489565b60208381015173ffffffffffffffffffffffffffffffffffffffff8b166000908152600d835260408082208151808301909252547affffffffffffffffffffffffffffffffffffffffffffffffffffff811682527b01000000000000000000000000000000000000000000000000000000900464ffffffffff16938101939093529293506117659161175b9161340b565b84602001516134a0565b905061178773ffffffffffffffffffffffffffffffffffffffff8b16896134af565b82516000906117b6906117b073ffffffffffffffffffffffffffffffffffffffff8e1630613140565b9061333b565b905060006117c78c8c848787612baa565b909650905085158015906117db5750888610155b61184657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f456d69737761703a2072657475726e206973206e6f7420656e6f756768000000604482015290519081900360640190fd5b61186773ffffffffffffffffffffffffffffffffffffffff8c1689886132bd565b801561189657611896611878610d3a565b73ffffffffffffffffffffffffffffffffffffffff8d1690836132bd565b845184146118d6576118d66118ab8584612f82565b73ffffffffffffffffffffffffffffffffffffffff8e166000908152600c602052604090209061359d565b84602001518314611919576119196118ee848861333b565b73ffffffffffffffffffffffffffffffffffffffff8d166000908152600d602052604090209061359d565b845173ffffffffffffffffffffffffffffffffffffffff8d166000908152600d602052604090206119499161360d565b60208086015173ffffffffffffffffffffffffffffffffffffffff8d166000908152600c909252604090912061197e9161360d565b8a73ffffffffffffffffffffffffffffffffffffffff168c73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f86c49b5d8577da08444947f1427d23ef191cfabf2c0788f93324d79e926a9302858a8a600001518b602001516119f8610b17565b604080519586526020860194909452848401929092526060840152608083015273ffffffffffffffffffffffffffffffffffffffff8d1660a0830152519081900360c00190a460408051828152905173ffffffffffffffffffffffffffffffffffffffff8a169133917f2ff1ad11b6e7211d4d0cc86e3a449ecc036fd7abfe355401bdb6304dbf9b7a2b9181900360200190a35073ffffffffffffffffffffffffffffffffffffffff909a166000908152600b6020526040902080547001000000000000000000000000000000006fffffffffffffffffffffffffffffffff808316909d018d167fffffffffffffffffffffffffffffffff00000000000000000000000000000000909216919091178181048d1687018d169091029b169a909a17909955505060016006559695505050505050565b600060026006541415611ba157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002600655600980546040805160208084028201810190925282815260609390929091830182828015611c0a57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311611bdf575b5093945050508715801592509050611c225750805186145b611c8d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f456d69737761703a2077726f6e6720616d6f756e7473206c656e677468000000604482015290519081900360640190fd5b600087876000818110611c9c57fe5b90506020020135118015611cc35750600087876001818110611cba57fe5b90506020020135115b611d2e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f456d69737761703a2077726f6e672076616c7565207573616765000000000000604482015290519081900360640190fd5b60608667ffffffffffffffff81118015611d4757600080fd5b50604051908082528060200260200182016040528015611d71578160200160208202803683370190505b50905060005b8151811015611ddb57611dbc30848381518110611d9057fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1661314090919063ffffffff16565b828281518110611dc857fe5b6020908102919091010152600101611d77565b506000611de6610b17565b905080611e3f57611dfa6103e86063613208565b9350611e08306103e8613674565b60005b88811015611e3957611e2f858b8b84818110611e2357fe5b90506020020135613489565b9450600101611e0b565b50611ebe565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff935060005b88811015611ebc57611eb285611ead858481518110611e8057fe5b6020026020010151610e8d8e8e87818110611e9757fe5b905060200201358761320890919063ffffffff16565b6134a0565b9450600101611e65565b505b8360005b898110156120ce5760008b8b83818110611ed857fe5b9050602002013511611f4b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f456d69737761703a20616d6f756e74206973207a65726f000000000000000000604482015290519081900360640190fd5b60008315611f8f57611f8a84610e8d60018703611f84878a8881518110611f6e57fe5b602002602001015161320890919063ffffffff16565b90612f82565b611fa3565b8b8b83818110611f9b57fe5b905060200201355b9050898983818110611fb157fe5b9050602002013581101561202657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f456d69737761703a206d696e416d6f756e74206e6f7420726561636865640000604482015290519081900360640190fd5b6120628187848151811061203657fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff166134af90919063ffffffff16565b83156120c557600061209186848151811061207957fe5b60200260200101516117b0308a8781518110611d9057fe5b90506120c188611ead8886815181106120a657fe5b6020026020010151610e8d858a61320890919063ffffffff16565b9750505b50600101611ec2565b5081156121b25760005b898110156121b05761216d8482815181106120ef57fe5b602002602001015161210a8886612f8290919063ffffffff16565b85600d60008a878151811061211b57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002061337d909392919063ffffffff16565b6121a884828151811061217c57fe5b60200260200101516121978886612f8290919063ffffffff16565b85600c60008a878151811061211b57fe5b6001016120d8565b505b6000851161222157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f456d6e69737761703a20726573756c74206973206e6f7420656e6f7567680000604482015290519081900360640190fd5b61222b3386613674565b6040805186815273ffffffffffffffffffffffffffffffffffffffff88166020820152815133927fb4e1304f97b5093610f51b33ddab6622388422e2dac138b0d32f93dcfbd39edf928290030190a25050600160065550909695505050505050565b60075473ffffffffffffffffffffffffffffffffffffffff1690565b60048054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610aef5780601f10610ac457610100808354040283529160200191610aef565b60085473ffffffffffffffffffffffffffffffffffffffff1633146123ae57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f456d69737761703a20464f5242494444454e0000000000000000000000000000604482015290519081900360640190fd5b6002811461241d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f456d69737761703a206f6e6c79203220746f6b656e7320616c6c6f7765640000604482015290519081900360640190fd5b61242960098383613ca6565b5060005b8181101561255a57600a600084848481811061244557fe5b6020908102929092013573ffffffffffffffffffffffffffffffffffffffff168352508101919091526040016000205460ff16156124e457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f456d69737761703a206475706c696361746520746f6b656e7300000000000000604482015290519081900360640190fd5b6001600a60008585858181106124f657fe5b6020908102929092013573ffffffffffffffffffffffffffffffffffffffff1683525081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905560010161242d565b505050565b6000610b0d61256c612a5f565b84610bf085604051806060016040528060258152602001613f1c6025913960016000612596612a5f565b73ffffffffffffffffffffffffffffffffffffffff908116825260208083019390935260409182016000908120918d16815292529020549190612ed1565b6000610b0d6125e1612a5f565b8484612d01565b60606009805480602002602001604051908101604052809291908181526020018280548015610aef57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311612622575050505050905090565b600b602052600090815260409020546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041682565b601481565b6103e881565b60085473ffffffffffffffffffffffffffffffffffffffff1681565b670de0b6b3a764000081565b6000806126e873ffffffffffffffffffffffffffffffffffffffff841630613140565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600c60209081526040918290208251808401909352547affffffffffffffffffffffffffffffffffffffffffffffffffffff811683527b01000000000000000000000000000000000000000000000000000000900464ffffffffff1690820152909150610bf990612775908361340b565b82613489565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b600854604080517fddca3f43000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163ddca3f43916004808301926020929190829003018186803b158015610ccf57600080fd5b60008061284173ffffffffffffffffffffffffffffffffffffffff841630613140565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600d60209081526040918290208251808401909352547affffffffffffffffffffffffffffffffffffffffffffffffffffff811683527b01000000000000000000000000000000000000000000000000000000900464ffffffffff1690820152909150610bf9906128ce908361340b565b826134a0565b6128dc612a5f565b60075473ffffffffffffffffffffffffffffffffffffffff90811691161461296557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff81166129d1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180613dab6026913960400191505060405180910390fd5b60075460405173ffffffffffffffffffffffffffffffffffffffff8084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b3390565b73ffffffffffffffffffffffffffffffffffffffff8316612acf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180613ece6024913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216612b3b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180613dd16022913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600a6020526040812054819060ff168015612c06575073ffffffffffffffffffffffffffffffffffffffff86166000908152600a602052604090205460ff165b8015612c3e57508573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1614155b8015612c4a5750600085115b15612cf7576000612c79612c72670de0b6b3a7640000610e8d612c6b6127b3565b8a90613208565b879061333b565b90506000612c94612c8a8784612f82565b610e8d8488613208565b90506000612caf612ca5888a612f82565b610e8d8a89613208565b90506000612cbb610c64565b15612ce557612ce0612cd6612cce610c64565b610e8d6127b3565b610e8d848661333b565b612ce8565b60005b929550919350612cf792505050565b9550959350505050565b73ffffffffffffffffffffffffffffffffffffffff8316612d6d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180613ea96025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216612dd9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180613d666023913960400191505060405180910390fd5b612de483838361255a565b612e2e81604051806060016040528060268152602001613df36026913973ffffffffffffffffffffffffffffffffffffffff86166000908152602081905260409020549190612ed1565b73ffffffffffffffffffffffffffffffffffffffff8085166000908152602081905260408082209390935590841681522054612e6a9082612f82565b73ffffffffffffffffffffffffffffffffffffffff8084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115612f7a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612f3f578181015183820152602001612f27565b50505050905090810190601f168015612f6c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600082820183811015610bf957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8216613062576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180613e886021913960400191505060405180910390fd5b61306e8260008361255a565b6130b881604051806060016040528060228152602001613d896022913973ffffffffffffffffffffffffffffffffffffffff85166000908152602081905260409020549190612ed1565b73ffffffffffffffffffffffffffffffffffffffff83166000908152602081905260409020556002546130eb908261333b565b60025560408051828152905160009173ffffffffffffffffffffffffffffffffffffffff8516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b600061314b836137a5565b1561316e575073ffffffffffffffffffffffffffffffffffffffff811631610b11565b8273ffffffffffffffffffffffffffffffffffffffff166370a08231836040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156131d557600080fd5b505afa1580156131e9573d6000803e3d6000fd5b505050506040513d60208110156131ff57600080fd5b50519050610b11565b60008261321757506000610b11565b8282028284828161322457fe5b0414610bf9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180613e3f6021913960400191505060405180910390fd5b6000610bf983836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506137bf565b801561255a576132cc836137a5565b1561331a5760405173ffffffffffffffffffffffffffffffffffffffff83169082156108fc029083906000818181858888f19350505050158015613314573d6000803e3d6000fd5b5061255a565b61255a73ffffffffffffffffffffffffffffffffffffffff8416838361383e565b6000610bf983836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612ed1565b6134058461340083610e8d61339382600161333b565b604080518082019091528a547affffffffffffffffffffffffffffffffffffffffffffffffffffff811682527b01000000000000000000000000000000000000000000000000000000900464ffffffffff166020820152611f849089906133fa908c61340b565b90613208565b61359d565b50505050565b60008061343261012c611ead866020015164ffffffffff164261333b90919063ffffffff16565b9050600061344261012c8361333b565b905061348061012c610e8d6134578786613208565b8851611f84907affffffffffffffffffffffffffffffffffffffffffffffffffffff1686613208565b95945050505050565b6000818310156134995781610bf9565b5090919050565b60008183106134995781610bf9565b8015613599576134be826137a5565b15613577578034101561353257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f556e6945524332303a206e6f7420656e6f7567682076616c7565000000000000604482015290519081900360640190fd5b8034111561357257336108fc613548348461333b565b6040518115909202916000818181858888f19350505050158015613570573d6000803e3d6000fd5b505b613599565b61359973ffffffffffffffffffffffffffffffffffffffff83163330846138cb565b5050565b81547fffffffffff000000000000000000000000000000000000000000000000000000167affffffffffffffffffffffffffffffffffffffffffffffffffffff91821617167b010000000000000000000000000000000000000000000000000000004264ffffffffff1602179055565b6040805180820190915282547affffffffffffffffffffffffffffffffffffffffffffffffffffff811682527b01000000000000000000000000000000000000000000000000000000900464ffffffffff166020820152613599908390613400908461340b565b73ffffffffffffffffffffffffffffffffffffffff82166136f657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b6137026000838361255a565b60025461370f9082612f82565b60025573ffffffffffffffffffffffffffffffffffffffff82166000908152602081905260409020546137429082612f82565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b73ffffffffffffffffffffffffffffffffffffffff161590565b60008183613828576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201818152835160248401528351909283926044909101919085019080838360008315612f3f578181015183820152602001612f27565b50600083858161383457fe5b0495945050505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261255a90849061395c565b6040805173ffffffffffffffffffffffffffffffffffffffff80861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790526134059085905b60606139be826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16613a349092919063ffffffff16565b80519091501561255a578080602001905160208110156139dd57600080fd5b505161255a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180613ef2602a913960400191505060405180910390fd5b6060613a438484600085613a4b565b949350505050565b606082471015613aa6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180613e196026913960400191505060405180910390fd5b613aaf85613c06565b613b1a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b60208310613b8457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613b47565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114613be6576040519150601f19603f3d011682016040523d82523d6000602084013e613beb565b606091505b5091509150613bfb828286613c0c565b979650505050505050565b3b151590565b60608315613c1b575081610bf9565b825115613c2b5782518084602001fd5b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201818152845160248401528451859391928392604401919085019080838360008315612f3f578181015183820152602001612f27565b604051806040016040528060008152602001600081525090565b828054828255906000526020600020908101928215613d1e579160200282015b82811115613d1e5781547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff843516178255602090920191600190910190613cc6565b50613d2a929150613d2e565b5090565b5b80821115613d2a5780547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155600101613d2f56fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e63654f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7745524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f20616464726573735361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122036d32bf2b7644348aa43131dd58567690193bc79edcad61fb173e9588885feb164736f6c634300060c0033

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061025c5760003560e01c80637dc2038211610145578063b21b5a21116100bd578063d7d3aab51161008c578063ddca3f4311610071578063ddca3f43146109d7578063e7ff42c9146109df578063f2fde38b14610a125761025c565b8063d7d3aab514610969578063dd62ed3e1461099c5761025c565b8063b21b5a2114610949578063baf13a0a14610951578063c45a015514610959578063d73792a9146109615761025c565b8063a224cee711610114578063a9059cbb116100f9578063a9059cbb14610844578063aa6ca8081461087d578063b1ec4c40146108d55761025c565b8063a224cee71461079b578063a457c2d71461080b5761025c565b80637dc203821461065c5780637e067a60146106b35780638da5cb5b1461078b57806395d89b41146107935761025c565b806348d67e1b116101d85780635ed9156d116101a757806370a082311161018c57806370a08231146105e8578063715018a61461061b57806378e3214f146106235761025c565b80635ed9156d146105455780636edc2c09146105b55761025c565b806348d67e1b146104765780634f64b2be1461047e57806356929070146104c45780635915d806146104cc5761025c565b80631e1401f81161022f578063313ce56711610214578063313ce567146104175780633950935114610435578063478222c21461046e5761025c565b80631e1401f81461037857806323b872dd146103d45761025c565b806306fdde0314610261578063095ea7b3146102de57806318160ddd1461032b57806319f3736114610345575b600080fd5b610269610a45565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102a357818101518382015260200161028b565b50505050905090810190601f1680156102d05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610317600480360360408110156102f457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610af9565b604080519115158252519081900360200190f35b610333610b17565b60408051918252519081900360200190f35b6103176004803603602081101561035b57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610b1d565b6103bb6004803603606081101561038e57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135610b32565b6040805192835260208301919091528051918290030190f35b610317600480360360608110156103ea57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135610b5e565b61041f610c00565b6040805160ff9092168252519081900360200190f35b6103176004803603604081101561044b57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610c09565b610333610c64565b610333610d00565b61049b6004803603602081101561049457600080fd5b5035610d06565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b61049b610d3a565b610543600480360360408110156104e257600080fd5b8135919081019060408101602082013564010000000081111561050457600080fd5b82018360208201111561051657600080fd5b8035906020019184602083028401116401000000008311171561053857600080fd5b509092509050610da5565b005b6105786004803603602081101561055b57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611005565b604080517affffffffffffffffffffffffffffffffffffffffffffffffffffff909316835264ffffffffff90911660208301528051918290030190f35b610578600480360360208110156105cb57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661105c565b610333600480360360208110156105fe57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166110b3565b6105436110db565b6105436004803603604081101561063957600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356111db565b610333600480360360c081101561067257600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020810135821691604082013591606081013591608082013581169160a00135166114dc565b610333600480360360608110156106c957600080fd5b8101906020810181356401000000008111156106e457600080fd5b8201836020820111156106f657600080fd5b8035906020019184602083028401116401000000008311171561071857600080fd5b91939092909160208101903564010000000081111561073657600080fd5b82018360208201111561074857600080fd5b8035906020019184602083028401116401000000008311171561076a57600080fd5b91935091503573ffffffffffffffffffffffffffffffffffffffff16611b2d565b61049b61228d565b6102696122a9565b610543600480360360208110156107b157600080fd5b8101906020810181356401000000008111156107cc57600080fd5b8201836020820111156107de57600080fd5b8035906020019184602083028401116401000000008311171561080057600080fd5b509092509050612328565b6103176004803603604081101561082157600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013561255f565b6103176004803603604081101561085a57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356125d4565b6108856125e8565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156108c15781810151838201526020016108a9565b505050509050019250505060405180910390f35b610908600480360360208110156108eb57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612656565b60405180836fffffffffffffffffffffffffffffffff168152602001826fffffffffffffffffffffffffffffffff1681526020019250505060405180910390f35b610333612692565b610333612697565b61049b61269d565b6103336126b9565b6103336004803603602081101561097f57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166126c5565b610333600480360360408110156109b257600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602001351661277b565b6103336127b3565b610333600480360360208110156109f557600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661281e565b61054360048036036020811015610a2857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166128d4565b60038054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610aef5780601f10610ac457610100808354040283529160200191610aef565b820191906000526020600020905b815481529060010190602001808311610ad257829003601f168201915b5050505050905090565b6000610b0d610b06612a5f565b8484612a63565b5060015b92915050565b60025490565b600a6020526000908152604090205460ff1681565b600080610b52858585610b44896126c5565b610b4d8961281e565b612baa565b91509150935093915050565b6000610b6b848484612d01565b610bf584610b77612a5f565b610bf085604051806060016040528060288152602001613e606028913973ffffffffffffffffffffffffffffffffffffffff8a16600090815260016020526040812090610bc2612a5f565b73ffffffffffffffffffffffffffffffffffffffff1681526020810191909152604001600020549190612ed1565b612a63565b5060015b9392505050565b60055460ff1690565b6000610b0d610c16612a5f565b84610bf08560016000610c27612a5f565b73ffffffffffffffffffffffffffffffffffffffff908116825260208083019390935260409182016000908120918c168152925290205490612f82565b600854604080517f478222c2000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163478222c2916004808301926020929190829003018186803b158015610ccf57600080fd5b505afa158015610ce3573d6000803e3d6000fd5b505050506040513d6020811015610cf957600080fd5b5051905090565b61012c90565b60098181548110610d1357fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b600854604080517f56929070000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff16916356929070916004808301926020929190829003018186803b158015610ccf57600080fd5b60026006541415610e1757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026006556000610e26610b17565b9050610e323385612ff6565b60005b600954811015610fc357600060098281548110610e4e57fe5b600091825260208220015473ffffffffffffffffffffffffffffffffffffffff169150610e7b8230613140565b90506000610e9385610e8d848b613208565b9061327b565b9050610eb673ffffffffffffffffffffffffffffffffffffffff841633836132bd565b8584101580610ed75750868685818110610ecc57fe5b905060200201358110155b610f4257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f456d69737761703a20726573756c74206973206e6f7420656e6f756768000000604482015290519081900360640190fd5b610f7d82610f50878b61333b565b73ffffffffffffffffffffffffffffffffffffffff86166000908152600c6020526040902091908861337d565b610fb882610f8b878b61333b565b73ffffffffffffffffffffffffffffffffffffffff86166000908152600d6020526040902091908861337d565b505050600101610e35565b5060408051858152905133917f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d5919081900360200190a2505060016006555050565b600d602052600090815260409020547affffffffffffffffffffffffffffffffffffffffffffffffffffff8116907b01000000000000000000000000000000000000000000000000000000900464ffffffffff1682565b600c602052600090815260409020547affffffffffffffffffffffffffffffffffffffffffffffffffffff8116907b01000000000000000000000000000000000000000000000000000000900464ffffffffff1682565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6110e3612a5f565b60075473ffffffffffffffffffffffffffffffffffffffff90811691161461116c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60075460405160009173ffffffffffffffffffffffffffffffffffffffff16907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600780547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b6002600654141561124d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260065561125a612a5f565b60075473ffffffffffffffffffffffffffffffffffffffff9081169116146112e357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60095460609067ffffffffffffffff811180156112ff57600080fd5b50604051908082528060200260200182016040528015611329578160200160208202803683370190505b50905060005b815181101561139057611371306009838154811061134957fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1690613140565b82828151811061137d57fe5b602090810291909101015260010161132f565b506113b273ffffffffffffffffffffffffffffffffffffffff841633846132bd565b60005b8151811015611458578181815181106113ca57fe5b60200260200101516113e3306009848154811061134957fe5b101561145057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f456d69737761703a206163636573732064656e69656400000000000000000000604482015290519081900360640190fd5b6001016113b5565b506103e8611465306110b3565b10156114d257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f456d69737761703a206163636573732064656e69656400000000000000000000604482015290519081900360640190fd5b5050600160065550565b60006002600654141561155057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260065573ffffffffffffffffffffffffffffffffffffffff87166115d757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f456d69737761703a206f6e6c7920746f6b656e7320616c6c6f77656400000000604482015290519081900360640190fd5b6115df613c8c565b604080518082019091528061160a73ffffffffffffffffffffffffffffffffffffffff8b1630613140565b815260200161162f73ffffffffffffffffffffffffffffffffffffffff8a1630613140565b9052805173ffffffffffffffffffffffffffffffffffffffff8a166000908152600c602090815260408083208151808301909252547affffffffffffffffffffffffffffffffffffffffffffffffffffff811682527b01000000000000000000000000000000000000000000000000000000900464ffffffffff1691810191909152929350916116ca916116c3919061340b565b8351613489565b60208381015173ffffffffffffffffffffffffffffffffffffffff8b166000908152600d835260408082208151808301909252547affffffffffffffffffffffffffffffffffffffffffffffffffffff811682527b01000000000000000000000000000000000000000000000000000000900464ffffffffff16938101939093529293506117659161175b9161340b565b84602001516134a0565b905061178773ffffffffffffffffffffffffffffffffffffffff8b16896134af565b82516000906117b6906117b073ffffffffffffffffffffffffffffffffffffffff8e1630613140565b9061333b565b905060006117c78c8c848787612baa565b909650905085158015906117db5750888610155b61184657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f456d69737761703a2072657475726e206973206e6f7420656e6f756768000000604482015290519081900360640190fd5b61186773ffffffffffffffffffffffffffffffffffffffff8c1689886132bd565b801561189657611896611878610d3a565b73ffffffffffffffffffffffffffffffffffffffff8d1690836132bd565b845184146118d6576118d66118ab8584612f82565b73ffffffffffffffffffffffffffffffffffffffff8e166000908152600c602052604090209061359d565b84602001518314611919576119196118ee848861333b565b73ffffffffffffffffffffffffffffffffffffffff8d166000908152600d602052604090209061359d565b845173ffffffffffffffffffffffffffffffffffffffff8d166000908152600d602052604090206119499161360d565b60208086015173ffffffffffffffffffffffffffffffffffffffff8d166000908152600c909252604090912061197e9161360d565b8a73ffffffffffffffffffffffffffffffffffffffff168c73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f86c49b5d8577da08444947f1427d23ef191cfabf2c0788f93324d79e926a9302858a8a600001518b602001516119f8610b17565b604080519586526020860194909452848401929092526060840152608083015273ffffffffffffffffffffffffffffffffffffffff8d1660a0830152519081900360c00190a460408051828152905173ffffffffffffffffffffffffffffffffffffffff8a169133917f2ff1ad11b6e7211d4d0cc86e3a449ecc036fd7abfe355401bdb6304dbf9b7a2b9181900360200190a35073ffffffffffffffffffffffffffffffffffffffff909a166000908152600b6020526040902080547001000000000000000000000000000000006fffffffffffffffffffffffffffffffff808316909d018d167fffffffffffffffffffffffffffffffff00000000000000000000000000000000909216919091178181048d1687018d169091029b169a909a17909955505060016006559695505050505050565b600060026006541415611ba157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002600655600980546040805160208084028201810190925282815260609390929091830182828015611c0a57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311611bdf575b5093945050508715801592509050611c225750805186145b611c8d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f456d69737761703a2077726f6e6720616d6f756e7473206c656e677468000000604482015290519081900360640190fd5b600087876000818110611c9c57fe5b90506020020135118015611cc35750600087876001818110611cba57fe5b90506020020135115b611d2e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f456d69737761703a2077726f6e672076616c7565207573616765000000000000604482015290519081900360640190fd5b60608667ffffffffffffffff81118015611d4757600080fd5b50604051908082528060200260200182016040528015611d71578160200160208202803683370190505b50905060005b8151811015611ddb57611dbc30848381518110611d9057fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1661314090919063ffffffff16565b828281518110611dc857fe5b6020908102919091010152600101611d77565b506000611de6610b17565b905080611e3f57611dfa6103e86063613208565b9350611e08306103e8613674565b60005b88811015611e3957611e2f858b8b84818110611e2357fe5b90506020020135613489565b9450600101611e0b565b50611ebe565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff935060005b88811015611ebc57611eb285611ead858481518110611e8057fe5b6020026020010151610e8d8e8e87818110611e9757fe5b905060200201358761320890919063ffffffff16565b6134a0565b9450600101611e65565b505b8360005b898110156120ce5760008b8b83818110611ed857fe5b9050602002013511611f4b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f456d69737761703a20616d6f756e74206973207a65726f000000000000000000604482015290519081900360640190fd5b60008315611f8f57611f8a84610e8d60018703611f84878a8881518110611f6e57fe5b602002602001015161320890919063ffffffff16565b90612f82565b611fa3565b8b8b83818110611f9b57fe5b905060200201355b9050898983818110611fb157fe5b9050602002013581101561202657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f456d69737761703a206d696e416d6f756e74206e6f7420726561636865640000604482015290519081900360640190fd5b6120628187848151811061203657fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff166134af90919063ffffffff16565b83156120c557600061209186848151811061207957fe5b60200260200101516117b0308a8781518110611d9057fe5b90506120c188611ead8886815181106120a657fe5b6020026020010151610e8d858a61320890919063ffffffff16565b9750505b50600101611ec2565b5081156121b25760005b898110156121b05761216d8482815181106120ef57fe5b602002602001015161210a8886612f8290919063ffffffff16565b85600d60008a878151811061211b57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002061337d909392919063ffffffff16565b6121a884828151811061217c57fe5b60200260200101516121978886612f8290919063ffffffff16565b85600c60008a878151811061211b57fe5b6001016120d8565b505b6000851161222157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f456d6e69737761703a20726573756c74206973206e6f7420656e6f7567680000604482015290519081900360640190fd5b61222b3386613674565b6040805186815273ffffffffffffffffffffffffffffffffffffffff88166020820152815133927fb4e1304f97b5093610f51b33ddab6622388422e2dac138b0d32f93dcfbd39edf928290030190a25050600160065550909695505050505050565b60075473ffffffffffffffffffffffffffffffffffffffff1690565b60048054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610aef5780601f10610ac457610100808354040283529160200191610aef565b60085473ffffffffffffffffffffffffffffffffffffffff1633146123ae57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f456d69737761703a20464f5242494444454e0000000000000000000000000000604482015290519081900360640190fd5b6002811461241d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f456d69737761703a206f6e6c79203220746f6b656e7320616c6c6f7765640000604482015290519081900360640190fd5b61242960098383613ca6565b5060005b8181101561255a57600a600084848481811061244557fe5b6020908102929092013573ffffffffffffffffffffffffffffffffffffffff168352508101919091526040016000205460ff16156124e457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f456d69737761703a206475706c696361746520746f6b656e7300000000000000604482015290519081900360640190fd5b6001600a60008585858181106124f657fe5b6020908102929092013573ffffffffffffffffffffffffffffffffffffffff1683525081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905560010161242d565b505050565b6000610b0d61256c612a5f565b84610bf085604051806060016040528060258152602001613f1c6025913960016000612596612a5f565b73ffffffffffffffffffffffffffffffffffffffff908116825260208083019390935260409182016000908120918d16815292529020549190612ed1565b6000610b0d6125e1612a5f565b8484612d01565b60606009805480602002602001604051908101604052809291908181526020018280548015610aef57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311612622575050505050905090565b600b602052600090815260409020546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041682565b601481565b6103e881565b60085473ffffffffffffffffffffffffffffffffffffffff1681565b670de0b6b3a764000081565b6000806126e873ffffffffffffffffffffffffffffffffffffffff841630613140565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600c60209081526040918290208251808401909352547affffffffffffffffffffffffffffffffffffffffffffffffffffff811683527b01000000000000000000000000000000000000000000000000000000900464ffffffffff1690820152909150610bf990612775908361340b565b82613489565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b600854604080517fddca3f43000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163ddca3f43916004808301926020929190829003018186803b158015610ccf57600080fd5b60008061284173ffffffffffffffffffffffffffffffffffffffff841630613140565b73ffffffffffffffffffffffffffffffffffffffff84166000908152600d60209081526040918290208251808401909352547affffffffffffffffffffffffffffffffffffffffffffffffffffff811683527b01000000000000000000000000000000000000000000000000000000900464ffffffffff1690820152909150610bf9906128ce908361340b565b826134a0565b6128dc612a5f565b60075473ffffffffffffffffffffffffffffffffffffffff90811691161461296557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff81166129d1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180613dab6026913960400191505060405180910390fd5b60075460405173ffffffffffffffffffffffffffffffffffffffff8084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b3390565b73ffffffffffffffffffffffffffffffffffffffff8316612acf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180613ece6024913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216612b3b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180613dd16022913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b73ffffffffffffffffffffffffffffffffffffffff85166000908152600a6020526040812054819060ff168015612c06575073ffffffffffffffffffffffffffffffffffffffff86166000908152600a602052604090205460ff165b8015612c3e57508573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1614155b8015612c4a5750600085115b15612cf7576000612c79612c72670de0b6b3a7640000610e8d612c6b6127b3565b8a90613208565b879061333b565b90506000612c94612c8a8784612f82565b610e8d8488613208565b90506000612caf612ca5888a612f82565b610e8d8a89613208565b90506000612cbb610c64565b15612ce557612ce0612cd6612cce610c64565b610e8d6127b3565b610e8d848661333b565b612ce8565b60005b929550919350612cf792505050565b9550959350505050565b73ffffffffffffffffffffffffffffffffffffffff8316612d6d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180613ea96025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216612dd9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180613d666023913960400191505060405180910390fd5b612de483838361255a565b612e2e81604051806060016040528060268152602001613df36026913973ffffffffffffffffffffffffffffffffffffffff86166000908152602081905260409020549190612ed1565b73ffffffffffffffffffffffffffffffffffffffff8085166000908152602081905260408082209390935590841681522054612e6a9082612f82565b73ffffffffffffffffffffffffffffffffffffffff8084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115612f7a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612f3f578181015183820152602001612f27565b50505050905090810190601f168015612f6c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600082820183811015610bf957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8216613062576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180613e886021913960400191505060405180910390fd5b61306e8260008361255a565b6130b881604051806060016040528060228152602001613d896022913973ffffffffffffffffffffffffffffffffffffffff85166000908152602081905260409020549190612ed1565b73ffffffffffffffffffffffffffffffffffffffff83166000908152602081905260409020556002546130eb908261333b565b60025560408051828152905160009173ffffffffffffffffffffffffffffffffffffffff8516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b600061314b836137a5565b1561316e575073ffffffffffffffffffffffffffffffffffffffff811631610b11565b8273ffffffffffffffffffffffffffffffffffffffff166370a08231836040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156131d557600080fd5b505afa1580156131e9573d6000803e3d6000fd5b505050506040513d60208110156131ff57600080fd5b50519050610b11565b60008261321757506000610b11565b8282028284828161322457fe5b0414610bf9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180613e3f6021913960400191505060405180910390fd5b6000610bf983836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506137bf565b801561255a576132cc836137a5565b1561331a5760405173ffffffffffffffffffffffffffffffffffffffff83169082156108fc029083906000818181858888f19350505050158015613314573d6000803e3d6000fd5b5061255a565b61255a73ffffffffffffffffffffffffffffffffffffffff8416838361383e565b6000610bf983836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612ed1565b6134058461340083610e8d61339382600161333b565b604080518082019091528a547affffffffffffffffffffffffffffffffffffffffffffffffffffff811682527b01000000000000000000000000000000000000000000000000000000900464ffffffffff166020820152611f849089906133fa908c61340b565b90613208565b61359d565b50505050565b60008061343261012c611ead866020015164ffffffffff164261333b90919063ffffffff16565b9050600061344261012c8361333b565b905061348061012c610e8d6134578786613208565b8851611f84907affffffffffffffffffffffffffffffffffffffffffffffffffffff1686613208565b95945050505050565b6000818310156134995781610bf9565b5090919050565b60008183106134995781610bf9565b8015613599576134be826137a5565b15613577578034101561353257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f556e6945524332303a206e6f7420656e6f7567682076616c7565000000000000604482015290519081900360640190fd5b8034111561357257336108fc613548348461333b565b6040518115909202916000818181858888f19350505050158015613570573d6000803e3d6000fd5b505b613599565b61359973ffffffffffffffffffffffffffffffffffffffff83163330846138cb565b5050565b81547fffffffffff000000000000000000000000000000000000000000000000000000167affffffffffffffffffffffffffffffffffffffffffffffffffffff91821617167b010000000000000000000000000000000000000000000000000000004264ffffffffff1602179055565b6040805180820190915282547affffffffffffffffffffffffffffffffffffffffffffffffffffff811682527b01000000000000000000000000000000000000000000000000000000900464ffffffffff166020820152613599908390613400908461340b565b73ffffffffffffffffffffffffffffffffffffffff82166136f657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b6137026000838361255a565b60025461370f9082612f82565b60025573ffffffffffffffffffffffffffffffffffffffff82166000908152602081905260409020546137429082612f82565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b73ffffffffffffffffffffffffffffffffffffffff161590565b60008183613828576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201818152835160248401528351909283926044909101919085019080838360008315612f3f578181015183820152602001612f27565b50600083858161383457fe5b0495945050505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261255a90849061395c565b6040805173ffffffffffffffffffffffffffffffffffffffff80861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790526134059085905b60606139be826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16613a349092919063ffffffff16565b80519091501561255a578080602001905160208110156139dd57600080fd5b505161255a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180613ef2602a913960400191505060405180910390fd5b6060613a438484600085613a4b565b949350505050565b606082471015613aa6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180613e196026913960400191505060405180910390fd5b613aaf85613c06565b613b1a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b60208310613b8457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613b47565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114613be6576040519150601f19603f3d011682016040523d82523d6000602084013e613beb565b606091505b5091509150613bfb828286613c0c565b979650505050505050565b3b151590565b60608315613c1b575081610bf9565b825115613c2b5782518084602001fd5b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201818152845160248401528451859391928392604401919085019080838360008315612f3f578181015183820152602001612f27565b604051806040016040528060008152602001600081525090565b828054828255906000526020600020908101928215613d1e579160200282015b82811115613d1e5781547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff843516178255602090920191600190910190613cc6565b50613d2a929150613d2e565b5090565b5b80821115613d2a5780547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155600101613d2f56fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e63654f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7745524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f20616464726573735361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122036d32bf2b7644348aa43131dd58567690193bc79edcad61fb173e9588885feb164736f6c634300060c0033

Deployed Bytecode Sourcemap

43860:11960:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13682:83;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15788:169;;;;;;;;;;;;;;;;-1:-1:-1;15788:169:0;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;14757:100;;;:::i;:::-;;;;;;;;;;;;;;;;45066:38;;;;;;;;;;;;;;;;-1:-1:-1;45066:38:0;;;;:::i;47057:356::-;;;;;;;;;;;;;;;;-1:-1:-1;47057:356:0;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;16439:321;;;;;;;;;;;;;;;;-1:-1:-1;16439:321:0;;;;;;;;;;;;;;;;;;:::i;14609:83::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;17169:218;;;;;;;;;;;;;;;;-1:-1:-1;17169:218:0;;;;;;;;;:::i;46026:94::-;;;:::i;46339:108::-;;;:::i;45037:22::-;;;;;;;;;;;;;;;;-1:-1:-1;45037:22:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;46128:102;;;:::i;50560:1041::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;50560:1041:0;;-1:-1:-1;50560:1041:0;-1:-1:-1;50560:1041:0;:::i;:::-;;45242:71;;;;;;;;;;;;;;;;-1:-1:-1;45242:71:0;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;45163:72;;;;;;;;;;;;;;;;-1:-1:-1;45163:72:0;;;;:::i;14920:119::-;;;;;;;;;;;;;;;;-1:-1:-1;14920:119:0;;;;:::i;2768:148::-;;;:::i;54236:717::-;;;;;;;;;;;;;;;;-1:-1:-1;54236:717:0;;;;;;;;;:::i;51609:2619::-;;;;;;;;;;;;;;;;-1:-1:-1;51609:2619:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;47421:3131::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;47421:3131:0;-1:-1:-1;47421:3131:0;;;;:::i;2126:79::-;;;:::i;13884:87::-;;;:::i;45493:433::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;45493:433:0;;-1:-1:-1;45493:433:0;-1:-1:-1;45493:433:0;:::i;17890:269::-;;;;;;;;;;;;;;;;-1:-1:-1;17890:269:0;;;;;;;;;:::i;15252:175::-;;;;;;;;;;;;;;;;-1:-1:-1;15252:175:0;;;;;;;;;:::i;46238:93::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45111:45;;;;;;;;;;;;;;;;-1:-1:-1;45111:45:0;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;44789:43;;;:::i;44870:42::-;;;:::i;45007:23::-;;;:::i;44952:46::-;;;:::i;46455:294::-;;;;;;;;;;;;;;;;-1:-1:-1;46455:294:0;;;;:::i;15490:151::-;;;;;;;;;;;;;;;;-1:-1:-1;15490:151:0;;;;;;;;;;;:::i;45934:84::-;;;:::i;46757:292::-;;;;;;;;;;;;;;;;-1:-1:-1;46757:292:0;;;;:::i;3071:244::-;;;;;;;;;;;;;;;;-1:-1:-1;3071:244:0;;;;:::i;13682:83::-;13752:5;13745:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13719:13;;13745:12;;13752:5;;13745:12;;13752:5;13745:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13682:83;:::o;15788:169::-;15871:4;15888:39;15897:12;:10;:12::i;:::-;15911:7;15920:6;15888:8;:39::i;:::-;-1:-1:-1;15945:4:0;15788:169;;;;;:::o;14757:100::-;14837:12;;14757:100;:::o;45066:38::-;;;;;;;;;;;;;;;:::o;47057:356::-;47173:7;47182;47222:183;47251:3;47273;47295:6;47320:26;47342:3;47320:21;:26::i;:::-;47365:25;47386:3;47365:20;:25::i;:::-;47222:10;:183::i;:::-;47202:203;;;;47057:356;;;;;;:::o;16439:321::-;16545:4;16562:36;16572:6;16580:9;16591:6;16562:9;:36::i;:::-;16609:121;16618:6;16626:12;:10;:12::i;:::-;16640:89;16678:6;16640:89;;;;;;;;;;;;;;;;;:19;;;;;;;:11;:19;;;;;;16660:12;:10;:12::i;:::-;16640:33;;;;;;;;;;;;;-1:-1:-1;16640:33:0;;;:89;:37;:89::i;:::-;16609:8;:121::i;:::-;-1:-1:-1;16748:4:0;16439:321;;;;;;:::o;14609:83::-;14675:9;;;;14609:83;:::o;17169:218::-;17257:4;17274:83;17283:12;:10;:12::i;:::-;17297:7;17306:50;17345:10;17306:11;:25;17318:12;:10;:12::i;:::-;17306:25;;;;;;;;;;;;;;;;;;-1:-1:-1;17306:25:0;;;:34;;;;;;;;;;;:38;:50::i;46026:94::-;46094:7;;:18;;;;;;;;46067:7;;46094;;;:16;;:18;;;;;;;;;;;;;;:7;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;46094:18:0;;-1:-1:-1;46026:94:0;:::o;46339:108::-;42736:9;46339:108;:::o;45037:22::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;45037:22:0;:::o;46128:102::-;46200:7;;:22;;;;;;;;46173:7;;46200;;;:20;;:22;;;;;;;;;;;;;;:7;:22;;;;;;;;;;50560:1041;39875:1;40481:7;;:19;;40473:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39875:1;40614:7;:18;50681:19:::1;50703:13;:11;:13::i;:::-;50681:35;;50727:25;50733:10;50745:6;50727:5;:25::i;:::-;50770:9;50765:782;50789:6;:13:::0;50785:17;::::1;50765:782;;;50824:12;50839:6;50846:1;50839:9;;;;;;;;;::::0;;;::::1;::::0;;::::1;::::0;::::1;;::::0;-1:-1:-1;50886:33:0::1;50839:9:::0;50913:4:::1;50886:18;:33::i;:::-;50865:54:::0;-1:-1:-1;50934:13:0::1;50950:39;50977:11:::0;50950:22:::1;50865:54:::0;50965:6;50950:14:::1;:22::i;:::-;:26:::0;::::1;:39::i;:::-;50934:55:::0;-1:-1:-1;51004:36:0::1;:17;::::0;::::1;51022:10;50934:55:::0;51004:17:::1;:36::i;:::-;51081:22:::0;;::::1;;::::0;:48:::1;;;51116:10;;51127:1;51116:13;;;;;;;;;;;;;51107:5;:22;;51081:48;51055:139;;;::::0;;::::1;::::0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;51211:155;51269:10:::0;51298:23:::1;:11:::0;51314:6;51298:15:::1;:23::i;:::-;51211:33;::::0;::::1;;::::0;;;:26:::1;:33;::::0;;;;;:155;51340:11;51211:39:::1;:155::i;:::-;51381:154;51438:10:::0;51467:23:::1;:11:::0;51483:6;51467:15:::1;:23::i;:::-;51381:32;::::0;::::1;;::::0;;;:25:::1;:32;::::0;;;;;:154;51509:11;51381:38:::1;:154::i;:::-;-1:-1:-1::0;;;50804:3:0::1;;50765:782;;;-1:-1:-1::0;51564:29:0::1;::::0;;;;;;;51574:10:::1;::::0;51564:29:::1;::::0;;;;;::::1;::::0;;::::1;-1:-1:-1::0;;39831:1:0;40793:7;:22;-1:-1:-1;;50560:1041:0:o;45242:71::-;;;;;;;;;;;;;;;;;;;;;;:::o;45163:72::-;;;;;;;;;;;;;;;;;;;;;;:::o;14920:119::-;15013:18;;14986:7;15013:18;;;;;;;;;;;;14920:119::o;2768:148::-;2348:12;:10;:12::i;:::-;2338:6;;:22;:6;;;:22;;;2330:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2859:6:::1;::::0;2838:40:::1;::::0;2875:1:::1;::::0;2838:40:::1;2859:6;::::0;2838:40:::1;::::0;2875:1;;2838:40:::1;2889:6;:19:::0;;;::::1;::::0;;2768:148::o;54236:717::-;39875:1;40481:7;;:19;;40473:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39875:1;40614:7;:18;2348:12:::1;:10;:12::i;:::-;2338:6;::::0;:22:::1;:6:::0;;::::1;:22:::0;::::1;;2330:67;;;::::0;;::::1;::::0;;::::1;;::::0;::::1;::::0;;;;;;;::::1;::::0;;;;;;;;;;;;;::::1;;54404:6:::2;:13:::0;54362:25:::2;::::0;54390:28:::2;::::0;::::2;::::0;::::2;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;54390:28:0::2;;54362:56;;54434:9;54429:124;54453:8;:15;54449:1;:19;54429:124;;;54504:37;54535:4;54504:6;54511:1;54504:9;;;;;;;;;::::0;;;::::2;::::0;;;::::2;::::0;::::2;;::::0;:22:::2;:37::i;:::-;54490:8;54499:1;54490:11;;;;;;;;;::::0;;::::2;::::0;;;;;:51;54470:3:::2;;54429:124;;;-1:-1:-1::0;54565:37:0::2;:17;::::0;::::2;54583:10;54595:6:::0;54565:17:::2;:37::i;:::-;54620:9;54615:209;54639:8;:15;54635:1;:19;54615:209;;;54743:8;54752:1;54743:11;;;;;;;;;;;;;;54702:37;54733:4;54702:6;54709:1;54702:9;;;;;;;:37;:52;;54676:136;;;::::0;;::::2;::::0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;::::2;::::0;;;;;;;;;;;;;::::2;;54656:3;;54615:209;;;;44908:4;54856:24;54874:4;54856:9;:24::i;:::-;:39;;54834:111;;;::::0;;::::2;::::0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;::::2;::::0;;;;;;;;;;;;;::::2;;-1:-1:-1::0;;39831:1:0;40793:7;:22;-1:-1:-1;54236:717:0:o;51609:2619::-;51804:14;39875:1;40481:7;;:19;;40473:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39875:1;40614:7;:18;51839:26:::1;::::0;::::1;51831:67;;;::::0;;::::1;::::0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;51911:24;;:::i;:::-;51951:135;::::0;;;;::::1;::::0;;;;51984:31:::1;:16;::::0;::::1;52009:4;51984:16;:31::i;:::-;51951:135:::0;;::::1;;52039:31;:16;::::0;::::1;52064:4;52039:16;:31::i;:::-;51951:135:::0;;52297:12;;52257:31:::1;::::0;::::1;52188:26;52257:31:::0;;;:26:::1;:31;::::0;;;;;;;:39;;;;::::1;::::0;;;;::::1;::::0;::::1;::::0;;;;::::1;;;::::0;;::::1;::::0;;;;52297:12;;-1:-1:-1;52188:26:0;52230:126:::1;::::0;52257:53:::1;::::0;:39;::::1;:53::i;:::-;52329:12:::0;;52230:8:::1;:126::i;:::-;52474:12;::::0;;::::1;::::0;52435:30:::1;::::0;::::1;52367:25;52435:30:::0;;;:25:::1;:30:::0;;;;;;:38;;;;::::1;::::0;;;;::::1;::::0;::::1;::::0;;;;::::1;;;::::0;;::::1;::::0;;;;52188:168;;-1:-1:-1;52408:125:0::1;::::0;52435:52:::1;::::0;:38:::1;:52::i;:::-;52506:8;:12;;;52408:8;:125::i;:::-;52367:166:::0;-1:-1:-1;52546:39:0::1;:31;::::0;::::1;52578:6:::0;52546:31:::1;:39::i;:::-;52652:12:::0;;52596:17:::1;::::0;52616:49:::1;::::0;:31:::1;:16;::::0;::::1;52641:4;52616:16;:31::i;:::-;:35:::0;::::1;:49::i;:::-;52596:69;;52678:19;52732:146;52757:3;52775;52793:9;52817:18;52850:17;52732:10;:146::i;:::-;52708:170:::0;;-1:-1:-1;52708:170:0;-1:-1:-1;52911:10:0;;;;;:33:::1;;;52935:9;52925:6;:19;;52911:33;52889:112;;;::::0;;::::1;::::0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;53012:36;:15;::::0;::::1;53036:2:::0;53041:6;53012:15:::1;:36::i;:::-;53063:15:::0;;53059:101:::1;;53095:53;53119:14;:12;:14::i;:::-;53095:15;::::0;::::1;::::0;53136:11;53095:15:::1;:53::i;:::-;53281:12:::0;;53259:34;::::1;53255:169;;53310:102;53364:33;:18:::0;53387:9;53364:22:::1;:33::i;:::-;53310:31;::::0;::::1;;::::0;;;:26:::1;:31;::::0;;;;;:35:::1;:102::i;:::-;53459:8;:12;;;53438:17;:33;53434:131;;53488:65;53523:29;:17:::0;53545:6;53523:21:::1;:29::i;:::-;53488:30;::::0;::::1;;::::0;;;:25:::1;:30;::::0;;;;;:34:::1;:65::i;:::-;53677:12:::0;;53639:30:::1;::::0;::::1;53677:12;53639:30:::0;;;:25:::1;:30;::::0;;;;:51:::1;::::0;:37:::1;:51::i;:::-;53740:12;::::0;;::::1;::::0;53701:31:::1;::::0;::::1;;::::0;;;:26:::1;:31:::0;;;;;;;:52:::1;::::0;:38:::1;:52::i;:::-;53853:3;53771:247;;53826:3;53771:247;;53793:10;53771:247;;;53872:9;53896:6;53917:8;:12;;;53944:8;:12;;;53971:13;:11;:13::i;:::-;53771:247;::::0;;;;;::::1;::::0;::::1;::::0;;;;;;;;;;;;;;;;;;;::::1;::::0;::::1;::::0;;;;;;;;;;;;::::1;54034:37;::::0;;;;;;;::::1;::::0;::::1;::::0;54043:10:::1;::::0;54034:37:::1;::::0;;;;::::1;::::0;;::::1;-1:-1:-1::0;54127:12:0::1;::::0;;::::1;;::::0;;;:7:::1;:12;::::0;;;;:44;;54182:38;54127:44:::1;::::0;;::::1;::::0;;::::1;::::0;::::1;::::0;;;::::1;::::0;;;::::1;54182:38:::0;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;;::::1;::::0;;;-1:-1:-1;;54127:44:0;40793:7;:22;54213:6;51609:2619;-1:-1:-1;;;;;;51609:2619:0:o;47421:3131::-;47580:18;39875:1;40481:7;;:19;;40473:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39875:1;40614:7;:18;47637:6:::1;47611:32:::0;;::::1;::::0;;::::1;::::0;;::::1;::::0;;;;;;;;;;:23:::1;::::0;:32;;47637:6;;47611:32;::::1;47637:6:::0;47611:32;;::::1;;;;;;;;;;;;;;;;::::0;;::::1;;::::0;;;;;::::1;::::0;::::1;;::::0;;::::1;;;;-1:-1:-1::0;47611:32:0;;-1:-1:-1;;;47677:18:0;;;;;-1:-1:-1;47677:18:0;-1:-1:-1;47676:58:0::1;;-1:-1:-1::0;47719:14:0;;47701:32;::::1;47676:58;47654:137;;;::::0;;::::1;::::0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;47838:1;47825:7;;47833:1;47825:10;;;;;;;;;;;;;:14;47824:36;;;;;47858:1;47845:7;;47853:1;47845:10;;;;;;;;;;;;;:14;47824:36;47802:112;;;::::0;;::::1;::::0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;47927:29;47973:7:::0;47959:29:::1;::::0;::::1;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;47959:29:0::1;;47927:61;;48004:9;47999:133;48023:12;:19;48019:1;:23;47999:133;;;48082:38;48114:4;48082:7;48090:1;48082:10;;;;;;;;;;;;;;:23;;;;:38;;;;:::i;:::-;48064:12;48077:1;48064:15;;;;;;;;;::::0;;::::1;::::0;;;;;:56;48044:3:::1;;47999:133;;;;48144:19;48166:13;:11;:13::i;:::-;48144:35:::0;-1:-1:-1;48194:16:0;48190:721:::1;;48240:19;44908:4;48256:2;48240:15;:19::i;:::-;48227:32;;48274:33;48288:4;44908;48274:5;:33::i;:::-;48439:9;48434:125;48454:18:::0;;::::1;48434:125;;;48511:32;48520:10;48532:7;;48540:1;48532:10;;;;;;;;;;;;;48511:8;:32::i;:::-;48498:45:::0;-1:-1:-1;48474:3:0::1;;48434:125;;;;48190:721;;;48644:17;48631:30;;48681:9;48676:224;48696:18:::0;;::::1;48676:224;;;48753:131;48784:10;48817:48;48849:12;48862:1;48849:15;;;;;;;;;;;;;;48817:27;48833:7;;48841:1;48833:10;;;;;;;;;;;;;48817:11;:15;;:27;;;;:::i;:48::-;48753:8;:131::i;:::-;48740:144:::0;-1:-1:-1;48716:3:0::1;;48676:224;;;;48190:721;48950:10:::0;48923:24:::1;48971:876;48991:18:::0;;::::1;48971:876;;;49052:1;49039:7;;49047:1;49039:10;;;;;;;;;;;;;:14;49031:50;;;::::0;;::::1;::::0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;49096:14;49131:16:::0;;49130:229:::1;;49206:153;49347:11;49206:110;49314:1;49300:11;:15;49206:63;49252:16;49206:12;49219:1;49206:15;;;;;;;;;;;;;;:45;;:63;;;;:::i;:::-;:93:::0;::::1;:110::i;:153::-;49130:229;;;49172:7;;49180:1;49172:10;;;;;;;;;;;;;49130:229;49096:263;;49392:10;;49403:1;49392:13;;;;;;;;;;;;;49382:6;:23;;49374:66;;;::::0;;::::1;::::0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;49457:46;49496:6;49457:7;49465:1;49457:10;;;;;;;;;;;;;;:38;;;;:46;;;;:::i;:::-;49522:15:::0;;49518:318:::1;;49558:17;49599:59;49642:12;49655:1;49642:15;;;;;;;;;;;;;;49599:38;49631:4;49599:7;49607:1;49599:10;;;;;;;:59;49558:100;;49690:130;49721:10;49754:47;49785:12;49798:1;49785:15;;;;;;;;;;;;;;49754:26;49770:9;49754:11;:15;;:26;;;;:::i;49690:130::-;49677:143;;49518:318;;-1:-1:-1::0;49011:3:0::1;;48971:876;;;-1:-1:-1::0;49863:15:0;;49859:515:::1;;49900:9;49895:468;49915:18:::0;;::::1;49895:468;;;49959:184;50025:12;50038:1;50025:15;;;;;;;;;;;;;;50063:27;50079:10;50063:11;:15;;:27;;;;:::i;:::-;50113:11;49959:25;:37;49985:7;49993:1;49985:10;;;;;;;;;;;;;;49959:37;;;;;;;;;;;;;;;:43;;:184;;;;;;:::i;:::-;50162:185;50229:12;50242:1;50229:15;;;;;;;;;;;;;;50267:27;50283:10;50267:11;:15;;:27;;;;:::i;:::-;50317:11;50162:26;:38;50189:7;50197:1;50189:10;;;;;;;50162:185;49935:3;;49895:468;;;;49859:515;50407:1;50394:10;:14;50386:57;;;::::0;;::::1;::::0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;50454:29;50460:10;50472;50454:5;:29::i;:::-;50501:43;::::0;;;;;::::1;::::0;::::1;;::::0;::::1;::::0;;;50511:10:::1;::::0;50501:43:::1;::::0;;;;;;::::1;-1:-1:-1::0;;39831:1:0;40793:7;:22;-1:-1:-1;47421:3131:0;;;-1:-1:-1;;;;;;47421:3131:0:o;2126:79::-;2191:6;;;;2126:79;:::o;13884:87::-;13956:7;13949:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13923:13;;13949:14;;13956:7;;13949:14;;13956:7;13949:14;;;;;;;;;;;;;;;;;;;;;;;;45493:433;45589:7;;;;45567:10;:30;45559:61;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45676:1;45659:18;;45651:61;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45725:15;:6;45734;;45725:15;:::i;:::-;;45756:9;45751:168;45771:17;;;45751:168;;;45819:7;:18;45827:6;;45834:1;45827:9;;;;;;;;;;;;;;;;;;45819:18;;-1:-1:-1;45819:18:0;;;;;;;;-1:-1:-1;45819:18:0;;;;45818:19;45810:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45903:4;45882:7;:18;45890:6;;45897:1;45890:9;;;;;;;;;;;;;;;;;;45882:18;;-1:-1:-1;45882:18:0;;;;;;;;-1:-1:-1;45882:18:0;:25;;;;;;;;;;;;;-1:-1:-1;45790:3:0;45751:168;;;;45493:433;;:::o;17890:269::-;17983:4;18000:129;18009:12;:10;:12::i;:::-;18023:7;18032:96;18071:15;18032:96;;;;;;;;;;;;;;;;;:11;:25;18044:12;:10;:12::i;:::-;18032:25;;;;;;;;;;;;;;;;;;-1:-1:-1;18032:25:0;;;:34;;;;;;;;;;;:96;:38;:96::i;15252:175::-;15338:4;15355:42;15365:12;:10;:12::i;:::-;15379:9;15390:6;15355:9;:42::i;46238:93::-;46282:15;46317:6;46310:13;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;46238:93;:::o;45111:45::-;;;;;;;;;;;;;;;;;;;;;;:::o;44789:43::-;44830:2;44789:43;:::o;44870:42::-;44908:4;44870:42;:::o;45007:23::-;;;;;;:::o;44952:46::-;44994:4;44952:46;:::o;46455:294::-;46521:7;;46559:33;:18;;;46586:4;46559:18;:33::i;:::-;46650;;;;;;;:26;:33;;;;;;;;;:41;;;;;;;;;;;;;;;;;;;;;;;46541:51;;-1:-1:-1;46623:118:0;;46650:50;;46541:51;46650:41;:50::i;:::-;46719:7;46623:8;:118::i;15490:151::-;15606:18;;;;15579:7;15606:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;15490:151::o;45934:84::-;45997:7;;:13;;;;;;;;45970:7;;45997;;;:11;;:13;;;;;;;;;;;;;;:7;:13;;;;;;;;;;46757:292;46822:7;;46860:33;:18;;;46887:4;46860:18;:33::i;:::-;46951:32;;;;;;;:25;:32;;;;;;;;;:40;;;;;;;;;;;;;;;;;;;;;;;46842:51;;-1:-1:-1;46924:117:0;;46951:49;;46842:51;46951:40;:49::i;:::-;47019:7;46924:8;:117::i;3071:244::-;2348:12;:10;:12::i;:::-;2338:6;;:22;:6;;;:22;;;2330:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3160:22:::1;::::0;::::1;3152:73;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3262:6;::::0;3241:38:::1;::::0;::::1;::::0;;::::1;::::0;3262:6:::1;::::0;3241:38:::1;::::0;3262:6:::1;::::0;3241:38:::1;3290:6;:17:::0;;;::::1;;::::0;;;::::1;::::0;;;::::1;::::0;;3071:244::o;665:106::-;753:10;665:106;:::o;21037:346::-;21139:19;;;21131:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21218:21;;;21210:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21291:18;;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;21343:32;;;;;;;;;;;;;;;;;21037:346;;;:::o;54961:856::-;55169:12;;;55136:7;55169:12;;;:7;:12;;;;;;55136:7;;55169:12;;:28;;;;-1:-1:-1;55185:12:0;;;;;;;:7;:12;;;;;;;;55169:28;:42;;;;;55208:3;55201:10;;:3;:10;;;;55169:42;:56;;;;;55224:1;55215:6;:10;55169:56;55165:645;;;55242:19;55281:50;55292:38;44994:4;55292:17;55303:5;:3;:5::i;:::-;55292:6;;:10;:17::i;:38::-;55281:6;;:10;:50::i;:::-;55242:89;-1:-1:-1;55346:15:0;55381:60;55413:27;:10;55242:89;55413:14;:27::i;:::-;55381;:11;55397:10;55381:15;:27::i;:60::-;55346:95;-1:-1:-1;55456:16:0;55492:50;55519:22;:10;55534:6;55519:14;:22::i;:::-;55492;:6;55503:10;55492;:22::i;:50::-;55456:86;;55557:16;55616:10;:8;:10::i;:::-;:15;:120;;55688:48;55714:21;55724:10;:8;:10::i;:::-;55714:5;:3;:5::i;:21::-;55688;:8;55701:7;55688:12;:21::i;:48::-;55616:120;;;55659:1;55616:120;55780:7;;-1:-1:-1;55557:198:0;;-1:-1:-1;55772:26:0;;-1:-1:-1;;;55772:26:0;55165:645;54961:856;;;;;;;;:::o;18649:539::-;18755:20;;;18747:70;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18836:23;;;18828:71;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18912:47;18933:6;18941:9;18952:6;18912:20;:47::i;:::-;18992:71;19014:6;18992:71;;;;;;;;;;;;;;;;;:17;;;:9;:17;;;;;;;;;;;;:71;:21;:71::i;:::-;18972:17;;;;:9;:17;;;;;;;;;;;:91;;;;19097:20;;;;;;;:32;;19122:6;19097:24;:32::i;:::-;19074:20;;;;:9;:20;;;;;;;;;;;;:55;;;;19145:35;;;;;;;19074:20;;19145:35;;;;;;;;;;;;;18649:539;;;:::o;7961:192::-;8047:7;8083:12;8075:6;;;;8067:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;8119:5:0;;;7961:192::o;7058:181::-;7116:7;7148:5;;;7172:6;;;;7164:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20181:418;20265:21;;;20257:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20337:49;20358:7;20375:1;20379:6;20337:20;:49::i;:::-;20420:68;20443:6;20420:68;;;;;;;;;;;;;;;;;:18;;;:9;:18;;;;;;;;;;;;:68;:22;:68::i;:::-;20399:18;;;:9;:18;;;;;;;;;;:89;20514:12;;:24;;20531:6;20514:16;:24::i;:::-;20499:12;:39;20554:37;;;;;;;;20580:1;;20554:37;;;;;;;;;;;;;20181:418;;:::o;33559:266::-;33662:7;33691:12;33697:5;33691;:12::i;:::-;33687:131;;;-1:-1:-1;33727:15:0;;;;33720:22;;33687:131;33782:5;:15;;;33798:7;33782:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;33782:24:0;;-1:-1:-1;33775:31:0;;8412:471;8470:7;8715:6;8711:47;;-1:-1:-1;8745:1:0;8738:8;;8711:47;8782:5;;;8786:1;8782;:5;:1;8806:5;;;;;:10;8798:56;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9359:132;9417:7;9444:39;9448:1;9451;9444:39;;;;;;;;;;;;;;;;;:3;:39::i;33833:317::-;33962:10;;33958:185;;33993:12;33999:5;33993;:12::i;:::-;33989:143;;;34026:19;;:11;;;;:19;;;;;34038:6;;34026:19;;;;34038:6;34026:11;:19;;;;;;;;;;;;;;;;;;;;;33989:143;;;34086:30;:18;;;34105:2;34109:6;34086:18;:30::i;7522:136::-;7580:7;7607:43;7611:1;7614;7607:43;;;;;;;;;;;;;;;;;:3;:43::i;43089:281::-;43250:112;43268:4;43287:64;43345:5;43287:53;43327:12;43345:5;43337:1;43327:9;:12::i;:::-;43287:26;;;;;;;;;;;;;;;;;;;;;;;;;:35;;43318:3;;43287:26;;43301:11;43287:7;:26::i;:::-;:30;;:35::i;:64::-;43250:3;:112::i;:::-;43089:281;;;;:::o;43378:475::-;43499:7;43524:18;43558:54;42736:9;43581:30;43601:4;:9;;;43581:30;;:15;:19;;:30;;;;:::i;43558:54::-;43524:88;-1:-1:-1;43623:18:0;43644:28;42736:9;43524:88;43644:16;:28::i;:::-;43623:49;-1:-1:-1;43703:142:0;42736:9;43703:106;43781:27;:11;43797:10;43781:15;:27::i;:::-;43711:12;;43703:55;;:21;;43747:10;43703:43;:55::i;:142::-;43683:162;43378:475;-1:-1:-1;;;;;43378:475:0:o;41079:107::-;41137:7;41169:1;41164;:6;;:14;;41177:1;41164:14;;;-1:-1:-1;41173:1:0;;41079:107;-1:-1:-1;41079:107:0:o;41262:106::-;41320:7;41351:1;41347;:5;:13;;41359:1;41347:13;;34158:536;34263:10;;34259:428;;34294:12;34300:5;34294;:12::i;:::-;34290:386;;;34348:6;34335:9;:19;;34327:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34420:6;34408:9;:18;34404:159;;;34501:10;:42;34521:21;:9;34535:6;34521:13;:21::i;:::-;34501:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34404:159;34290:386;;;34603:57;:22;;;34626:10;34646:4;34653:6;34603:22;:57::i;:::-;34158:536;;:::o;42754:169::-;42838:31;;;;;;;;;42880:35;;42899:15;42880:35;;;;;;42754:169::o;42931:150::-;43046:26;;;;;;;;;;;;;;;;;;;;;;;;;43036:37;;43046:26;;;;43060:11;43046:7;:26::i;19470:378::-;19554:21;;;19546:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19624:49;19653:1;19657:7;19666:6;19624:20;:49::i;:::-;19701:12;;:24;;19718:6;19701:16;:24::i;:::-;19686:12;:39;19757:18;;;:9;:18;;;;;;;;;;;:30;;19780:6;19757:22;:30::i;:::-;19736:18;;;:9;:18;;;;;;;;;;;:51;;;;19803:37;;;;;;;19736:18;;:9;;19803:37;;;;;;;;;;19470:378;;:::o;33437:114::-;33514:28;;;;33437:114::o;9987:278::-;10073:7;10108:12;10101:5;10093:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10132:9;10148:1;10144;:5;;;;;;;9987:278;-1:-1:-1;;;;;9987:278:0:o;30194:177::-;30304:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30327:23;30304:58;;;30277:86;;30297:5;;30277:19;:86::i;30379:205::-;30507:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30530:27;30507:68;;;30480:96;;30500:5;;32499:761;32923:23;32949:69;32977:4;32949:69;;;;;;;;;;;;;;;;;32957:5;32949:27;;;;:69;;;;;:::i;:::-;33033:17;;32923:95;;-1:-1:-1;33033:21:0;33029:224;;33175:10;33164:30;;;;;;;;;;;;;;;-1:-1:-1;33164:30:0;33156:85;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26195:195;26298:12;26330:52;26352:6;26360:4;26366:1;26369:12;26330:21;:52::i;:::-;26323:59;26195:195;-1:-1:-1;;;;26195:195:0:o;27247:530::-;27374:12;27432:5;27407:21;:30;;27399:81;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27499:18;27510:6;27499:10;:18::i;:::-;27491:60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27625:12;27639:23;27666:6;:11;;27686:5;27694:4;27666:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27624:75;;;;27717:52;27735:7;27744:10;27756:12;27717:17;:52::i;:::-;27710:59;27247:530;-1:-1:-1;;;;;;;27247:530:0:o;23277:422::-;23644:20;23683:8;;;23277:422::o;28783:742::-;28898:12;28927:7;28923:595;;;-1:-1:-1;28958:10:0;28951:17;;28923:595;29072:17;;:21;29068:439;;29335:10;29329:17;29396:15;29383:10;29379:2;29375:19;29368:44;29283:148;29471:20;;;;;;;;;;;;;;;;;;;;29478:12;;29471:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;

Swarm Source

ipfs://36d32bf2b7644348aa43131dd58567690193bc79edcad61fb173e9588885feb1

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

OVERVIEW

This is ESW-USDT pair swap smartcontract from Emiswap project.

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.