Contract Address Details

0xe0C38b2a8D09aAD53f1C67734B9A95E43d5981c0

Creator
0xd2bba3–70b399 at 0x5cc915–b54f8a
Balance
0 Doge
Tokens
Fetching tokens...
Transactions
3,058 Transactions
Transfers
0 Transfers
Gas Used
1,027,537,329
Last Balance Update
26540904
Contract name:
FireBirdRouter




Optimization enabled
true
Compiler version
v0.7.6+commit.7338295f




Optimization runs
999999
EVM Version
default




Verified at
2022-08-18T07:29:05.488054Z

Constructor Arguments

000000000000000000000000c7a50fe12c864963ea5a5e0858a0e7abe5b875c4000000000000000000000000ba926938022aed393436635fed939cadf5afe4d5000000000000000000000000b7ddc6414bf4f5515b52d8bdd69973ae205ff101

Arg [0] (address) : 0xc7a50fe12c864963ea5a5e0858a0e7abe5b875c4
Arg [1] (address) : 0xba926938022aed393436635fed939cadf5afe4d5
Arg [2] (address) : 0xb7ddc6414bf4f5515b52d8bdd69973ae205ff101

              

Contract source code

// SPDX-License-Identifier: MIT

pragma solidity >=0.7.6;
pragma abicoder v2;

interface IFireBirdFactory {
  event PairCreated(address indexed token0, address indexed token1, address pair, uint32 tokenWeight0, uint32 swapFee, uint256);

  function feeTo() external view returns (address);

  function formula() external view returns (address);

  function protocolFee() external view returns (uint256);

  function feeToSetter() external view returns (address);

  function getPair(
    address tokenA,
    address tokenB,
    uint32 tokenWeightA,
    uint32 swapFee
  ) external view returns (address pair);

  function allPairs(uint256) external view returns (address pair);

  function isPair(address) external view returns (bool);

  function allPairsLength() external view returns (uint256);

  function createPair(
    address tokenA,
    address tokenB,
    uint32 tokenWeightA,
    uint32 swapFee
  ) external returns (address pair);

  function getWeightsAndSwapFee(address pair)
    external
    view
    returns (
      uint32 tokenWeight0,
      uint32 tokenWeight1,
      uint32 swapFee
    );

  function setFeeTo(address) external;

  function setFeeToSetter(address) external;

  function setProtocolFee(uint256) external;
}

/*
    Bancor Formula interface
*/
interface IFireBirdFormula {
  function getFactoryReserveAndWeights(
    address factory,
    address pair,
    address tokenA,
    uint8 dexId
  )
    external
    view
    returns (
      address tokenB,
      uint256 reserveA,
      uint256 reserveB,
      uint32 tokenWeightA,
      uint32 tokenWeightB,
      uint32 swapFee
    );

  function getFactoryWeightsAndSwapFee(
    address factory,
    address pair,
    uint8 dexId
  )
    external
    view
    returns (
      uint32 tokenWeight0,
      uint32 tokenWeight1,
      uint32 swapFee
    );

  function getAmountIn(
    uint256 amountOut,
    uint256 reserveIn,
    uint256 reserveOut,
    uint32 tokenWeightIn,
    uint32 tokenWeightOut,
    uint32 swapFee
  ) external view returns (uint256 amountIn);

  function getAmountOut(
    uint256 amountIn,
    uint256 reserveIn,
    uint256 reserveOut,
    uint32 tokenWeightIn,
    uint32 tokenWeightOut,
    uint32 swapFee
  ) external view returns (uint256 amountOut);

  function getFactoryAmountsIn(
    address factory,
    address tokenIn,
    address tokenOut,
    uint256 amountOut,
    address[] calldata path,
    uint8[] calldata dexIds
  ) external view returns (uint256[] memory amounts);

  function getFactoryAmountsOut(
    address factory,
    address tokenIn,
    address tokenOut,
    uint256 amountIn,
    address[] calldata path,
    uint8[] calldata dexIds
  ) external view returns (uint256[] memory amounts);

  function ensureConstantValue(
    uint256 reserve0,
    uint256 reserve1,
    uint256 balance0Adjusted,
    uint256 balance1Adjusted,
    uint32 tokenWeight0
  ) external view returns (bool);

  function getReserves(
    address pair,
    address tokenA,
    address tokenB
  ) external view returns (uint256 reserveA, uint256 reserveB);

  function getOtherToken(address pair, address tokenA) external view returns (address tokenB);

  function quote(
    uint256 amountA,
    uint256 reserveA,
    uint256 reserveB
  ) external pure returns (uint256 amountB);

  function sortTokens(address tokenA, address tokenB) external pure returns (address token0, address token1);

  function mintLiquidityFee(
    uint256 totalLiquidity,
    uint112 reserve0,
    uint112 reserve1,
    uint32 tokenWeight0,
    uint32 tokenWeight1,
    uint112 collectedFee0,
    uint112 collectedFee1
  ) external view returns (uint256 amount);
}

interface IFireBirdPair {
  event Approval(address indexed owner, address indexed spender, uint256 value);
  event Transfer(address indexed from, address indexed to, uint256 value);

  function name() external view returns (string memory);

  function symbol() external view returns (string memory);

  function decimals() external pure returns (uint8);

  function totalSupply() external view returns (uint256);

  function balanceOf(address owner) external view returns (uint256);

  function allowance(address owner, address spender) external view returns (uint256);

  function approve(address spender, uint256 value) external returns (bool);

  function transfer(address to, uint256 value) external returns (bool);

  function transferFrom(
    address from,
    address to,
    uint256 value
  ) external returns (bool);

  function DOMAIN_SEPARATOR() external view returns (bytes32);

  function PERMIT_TYPEHASH() external pure returns (bytes32);

  function nonces(address owner) external view returns (uint256);

  function permit(
    address owner,
    address spender,
    uint256 value,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
  ) external;

  event PaidProtocolFee(uint112 collectedFee0, uint112 collectedFee1);
  event Mint(address indexed sender, uint256 amount0, uint256 amount1);
  event Burn(address indexed sender, uint256 amount0, uint256 amount1, address indexed to);
  event Swap(address indexed sender, uint256 amount0In, uint256 amount1In, uint256 amount0Out, uint256 amount1Out, address indexed to);
  event Sync(uint112 reserve0, uint112 reserve1);

  function MINIMUM_LIQUIDITY() external pure returns (uint256);

  function factory() external view returns (address);

  function token0() external view returns (address);

  function token1() external view returns (address);

  function getReserves()
    external
    view
    returns (
      uint112 reserve0,
      uint112 reserve1,
      uint32 blockTimestampLast
    );

  function getCollectedFees() external view returns (uint112 _collectedFee0, uint112 _collectedFee1);

  function getTokenWeights() external view returns (uint32 tokenWeight0, uint32 tokenWeight1);

  function getSwapFee() external view returns (uint32);

  function price0CumulativeLast() external view returns (uint256);

  function price1CumulativeLast() external view returns (uint256);

  function mint(address to) external returns (uint256 liquidity);

  function burn(address to) external returns (uint256 amount0, uint256 amount1);

  function swap(
    uint256 amount0Out,
    uint256 amount1Out,
    address to,
    bytes calldata data
  ) external;

  function skim(address to) external;

  function sync() external;

  function initialize(
    address,
    address,
    uint32,
    uint32
  ) external;
}

// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false
library TransferHelper {
  function safeApprove(
    address token,
    address to,
    uint256 value
  ) internal {
    // bytes4(keccak256(bytes('approve(address,uint256)')));
    (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
    require(success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper: APPROVE_FAILED");
  }

  function safeTransfer(
    address token,
    address to,
    uint256 value
  ) internal {
    // bytes4(keccak256(bytes('transfer(address,uint256)')));
    (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
    require(success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper: TRANSFER_FAILED");
  }

  function safeTransferFrom(
    address token,
    address from,
    address to,
    uint256 value
  ) internal {
    // bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
    (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
    require(success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper: TRANSFER_FROM_FAILED");
  }

  function safeTransferETH(address to, uint256 value) internal {
    (bool success, ) = to.call{value: value}(new bytes(0));
    require(success, "TransferHelper: ETH_TRANSFER_FAILED");
  }
}

interface IERC20 {
  event Approval(address indexed owner, address indexed spender, uint256 value);
  event Transfer(address indexed from, address indexed to, uint256 value);

  function name() external view returns (string memory);

  function symbol() external view returns (string memory);

  function decimals() external view returns (uint8);

  function totalSupply() external view returns (uint256);

  function balanceOf(address owner) external view returns (uint256);

  function allowance(address owner, address spender) external view returns (uint256);

  function approve(address spender, uint256 value) external returns (bool);

  function transfer(address to, uint256 value) external returns (bool);

  function transferFrom(
    address from,
    address to,
    uint256 value
  ) external returns (bool);
}

interface IFireBirdRouter {
  event Exchange(address pair, uint256 amountOut, address output);

  function factory() external view returns (address);

  function formula() external view returns (address);

  function WETH() external view returns (address);

  function swapFeeReward() external view returns (address);

  function addLiquidity(
    address pair,
    address tokenA,
    address tokenB,
    uint256 amountADesired,
    uint256 amountBDesired,
    uint256 amountAMin,
    uint256 amountBMin,
    address to,
    uint256 deadline
  )
    external
    returns (
      uint256 amountA,
      uint256 amountB,
      uint256 liquidity
    );

  function addLiquidityETH(
    address pair,
    address token,
    uint256 amountTokenDesired,
    uint256 amountTokenMin,
    uint256 amountETHMin,
    address to,
    uint256 deadline
  )
    external
    payable
    returns (
      uint256 amountToken,
      uint256 amountETH,
      uint256 liquidity
    );

  function swapExactTokensForTokens(
    address tokenIn,
    address tokenOut,
    uint256 amountIn,
    uint256 amountOutMin,
    address[] calldata path,
    uint8[] calldata dexIds,
    address to,
    uint256 deadline
  ) external returns (uint256[] memory amounts);

  function swapTokensForExactTokens(
    address tokenIn,
    address tokenOut,
    uint256 amountOut,
    uint256 amountInMax,
    address[] calldata path,
    uint8[] calldata dexIds,
    address to,
    uint256 deadline
  ) external returns (uint256[] memory amounts);

  function swapExactETHForTokens(
    address tokenOut,
    uint256 amountOutMin,
    address[] calldata path,
    uint8[] calldata dexIds,
    address to,
    uint256 deadline
  ) external payable returns (uint256[] memory amounts);

  function swapTokensForExactETH(
    address tokenIn,
    uint256 amountOut,
    uint256 amountInMax,
    address[] calldata path,
    uint8[] calldata dexIds,
    address to,
    uint256 deadline
  ) external returns (uint256[] memory amounts);

  function swapExactTokensForETH(
    address tokenIn,
    uint256 amountIn,
    uint256 amountOutMin,
    address[] calldata path,
    uint8[] calldata dexIds,
    address to,
    uint256 deadline
  ) external returns (uint256[] memory amounts);

  function swapETHForExactTokens(
    address tokenOut,
    uint256 amountOut,
    address[] calldata path,
    uint8[] calldata dexIds,
    address to,
    uint256 deadline
  ) external payable returns (uint256[] memory amounts);

  function swapExactTokensForTokensSupportingFeeOnTransferTokens(
    address tokenIn,
    address tokenOut,
    uint256 amountIn,
    uint256 amountOutMin,
    address[] calldata path,
    uint8[] calldata dexIds,
    address to,
    uint256 deadline
  ) external;

  function swapExactETHForTokensSupportingFeeOnTransferTokens(
    address tokenOut,
    uint256 amountOutMin,
    address[] calldata path,
    uint8[] calldata dexIds,
    address to,
    uint256 deadline
  ) external payable;

  function swapExactTokensForETHSupportingFeeOnTransferTokens(
    address tokenIn,
    uint256 amountIn,
    uint256 amountOutMin,
    address[] calldata path,
    uint8[] calldata dexIds,
    address to,
    uint256 deadline
  ) external;

  function createPair(
    address tokenA,
    address tokenB,
    uint256 amountA,
    uint256 amountB,
    uint32 tokenWeightA,
    uint32 swapFee,
    address to
  ) external returns (uint256 liquidity);

  function createPairETH(
    address token,
    uint256 amountToken,
    uint32 tokenWeight,
    uint32 swapFee,
    address to
  ) external payable returns (uint256 liquidity);

  function removeLiquidity(
    address pair,
    address tokenA,
    address tokenB,
    uint256 liquidity,
    uint256 amountAMin,
    uint256 amountBMin,
    address to,
    uint256 deadline
  ) external returns (uint256 amountA, uint256 amountB);

  function removeLiquidityETH(
    address pair,
    address token,
    uint256 liquidity,
    uint256 amountTokenMin,
    uint256 amountETHMin,
    address to,
    uint256 deadline
  ) external returns (uint256 amountToken, uint256 amountETH);

  function removeLiquidityWithPermit(
    address pair,
    address tokenA,
    address tokenB,
    uint256 liquidity,
    uint256 amountAMin,
    uint256 amountBMin,
    address to,
    uint256 deadline,
    bool approveMax,
    uint8 v,
    bytes32 r,
    bytes32 s
  ) external returns (uint256 amountA, uint256 amountB);

  function removeLiquidityETHWithPermit(
    address pair,
    address token,
    uint256 liquidity,
    uint256 amountTokenMin,
    uint256 amountETHMin,
    address to,
    uint256 deadline,
    bool approveMax,
    uint8 v,
    bytes32 r,
    bytes32 s
  ) external returns (uint256 amountToken, uint256 amountETH);

  function removeLiquidityETHSupportingFeeOnTransferTokens(
    address pair,
    address token,
    uint256 liquidity,
    uint256 amountTokenMin,
    uint256 amountETHMin,
    address to,
    uint256 deadline
  ) external returns (uint256 amountETH);

  function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
    address pair,
    address token,
    uint256 liquidity,
    uint256 amountTokenMin,
    uint256 amountETHMin,
    address to,
    uint256 deadline,
    bool approveMax,
    uint8 v,
    bytes32 r,
    bytes32 s
  ) external returns (uint256 amountETH);
}

// a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math)
library SafeMath {
  function add(uint256 x, uint256 y) internal pure returns (uint256 z) {
    require((z = x + y) >= x, "ds-math-add-overflow");
  }

  function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {
    require((z = x - y) <= x, "ds-math-sub-underflow");
  }

  function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {
    require(y == 0 || (z = x * y) / y == x, "ds-math-mul-overflow");
  }

  function div(uint256 a, uint256 b) internal pure returns (uint256 c) {
    require(b > 0, "ds-math-division-by-zero");
    c = a / b;
  }
}

interface IWETH {
  function deposit() external payable;

  function transfer(address to, uint256 value) external returns (bool);

  function withdraw(uint256) external;

  function balanceOf(address account) external view returns (uint256);
}

interface IAggregationExecutor {
  function callBytes(bytes calldata data, address srcSpender) external payable; // 0xd9c45357
}

interface ISwapFeeReward {
  function swap(
    address account,
    address input,
    address output,
    uint256 amount,
    address pair
  ) external returns (bool);

  function pairsListLength() external view returns (uint256);

  function pairsList(uint256 index)
    external
    view
    returns (
      address,
      uint256,
      bool
    );
}

interface IERC20Permit {
  function permit(
    address owner,
    address spender,
    uint256 amount,
    uint256 deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
  ) external;
}

library RevertReasonParser {
  function parse(bytes memory data, string memory prefix) internal pure returns (string memory) {
    // https://solidity.readthedocs.io/en/latest/control-structures.html#revert
    // We assume that revert reason is abi-encoded as Error(string)

    // 68 = 4-byte selector 0x08c379a0 + 32 bytes offset + 32 bytes length
    if (data.length >= 68 && data[0] == "\x08" && data[1] == "\xc3" && data[2] == "\x79" && data[3] == "\xa0") {
      string memory reason;
      // solhint-disable no-inline-assembly
      assembly {
        // 68 = 32 bytes data length + 4-byte selector + 32 bytes offset
        reason := add(data, 68)
      }
      /*
                revert reason is padded up to 32 bytes with ABI encoder: Error(string)
                also sometimes there is extra 32 bytes of zeros padded in the end:
                https://github.com/ethereum/solidity/issues/10170
                because of that we can't check for equality and instead check
                that string length + extra 68 bytes is less than overall data length
            */
      require(data.length >= 68 + bytes(reason).length, "Invalid revert reason");
      return string(abi.encodePacked(prefix, "Error(", reason, ")"));
    }
    // 36 = 4-byte selector 0x4e487b71 + 32 bytes integer
    else if (data.length == 36 && data[0] == "\x4e" && data[1] == "\x48" && data[2] == "\x7b" && data[3] == "\x71") {
      uint256 code;
      // solhint-disable no-inline-assembly
      assembly {
        // 36 = 32 bytes data length + 4-byte selector
        code := mload(add(data, 36))
      }
      return string(abi.encodePacked(prefix, "Panic(", _toHex(code), ")"));
    }

    return string(abi.encodePacked(prefix, "Unknown(", _toHex(data), ")"));
  }

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

  function _toHex(bytes memory data) private pure returns (string memory) {
    bytes16 alphabet = 0x30313233343536373839616263646566;
    bytes memory str = new bytes(2 + data.length * 2);
    str[0] = "0";
    str[1] = "x";
    for (uint256 i = 0; i < data.length; i++) {
      str[2 * i + 2] = alphabet[uint8(data[i] >> 4)];
      str[2 * i + 3] = alphabet[uint8(data[i] & 0x0f)];
    }
    return string(str);
  }
}

contract Permitable {
  event Error(string reason);

  function _permit(
    IERC20 token,
    uint256 amount,
    bytes calldata permit
  ) internal {
    if (permit.length == 32 * 7) {
      // solhint-disable-next-line avoid-low-level-calls
      (bool success, bytes memory result) = address(token).call(abi.encodePacked(IERC20Permit.permit.selector, permit));
      if (!success) {
        string memory reason = RevertReasonParser.parse(result, "Permit call failed: ");
        if (token.allowance(msg.sender, address(this)) < amount) {
          revert(reason);
        } else {
          emit Error(reason);
        }
      }
    }
  }
}

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

/**
 * @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 virtual 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;
  }
}

contract FireBirdRouter is IFireBirdRouter, Ownable, Permitable {
  using SafeMath for uint256;
  address public immutable override factory;
  address public immutable override formula;
  address public immutable override WETH;
  address public override swapFeeReward;
  address private constant ETH_ADDRESS = address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);

  uint256 private constant _PARTIAL_FILL = 0x01;
  uint256 private constant _REQUIRES_EXTRA_ETH = 0x02;
  uint256 private constant _SHOULD_CLAIM = 0x04;
  uint256 private constant _BURN_FROM_MSG_SENDER = 0x08;
  uint256 private constant _BURN_FROM_TX_ORIGIN = 0x10;

  struct SwapDescription {
    IERC20 srcToken;
    IERC20 dstToken;
    address srcReceiver;
    address dstReceiver;
    uint256 amount;
    uint256 minReturnAmount;
    uint256 flags;
    bytes permit;
  }

  event Swapped(address sender, IERC20 srcToken, IERC20 dstToken, address dstReceiver, uint256 spentAmount, uint256 returnAmount);

  modifier ensure(uint256 deadline) {
    require(deadline >= block.timestamp, "Router: EXPIRED");
    _;
  }

  constructor(
    address _factory,
    address _formula,
    address _WETH
  ) public {
    factory = _factory;
    formula = _formula;
    WETH = _WETH;
  }

  receive() external payable {
    assert(msg.sender == WETH);
    // only accept ETH via fallback from the WETH contract
  }

  function setSwapFeeReward(address _swapFeeReward) public onlyOwner {
    swapFeeReward = _swapFeeReward;
  }

  // **** ADD LIQUIDITY ****
  function _addLiquidity(
    address pair,
    address tokenA,
    address tokenB,
    uint256 amountADesired,
    uint256 amountBDesired,
    uint256 amountAMin,
    uint256 amountBMin
  ) internal virtual returns (uint256 amountA, uint256 amountB) {
    (uint256 reserveA, uint256 reserveB) = IFireBirdFormula(formula).getReserves(pair, tokenA, tokenB);
    if (reserveA == 0 && reserveB == 0) {
      (amountA, amountB) = (amountADesired, amountBDesired);
    } else {
      uint256 amountBOptimal = IFireBirdFormula(formula).quote(amountADesired, reserveA, reserveB);
      if (amountBOptimal <= amountBDesired) {
        require(amountBOptimal >= amountBMin, "Router: INSUFFICIENT_B_AMOUNT");
        (amountA, amountB) = (amountADesired, amountBOptimal);
      } else {
        uint256 amountAOptimal = IFireBirdFormula(formula).quote(amountBDesired, reserveB, reserveA);
        assert(amountAOptimal <= amountADesired);
        require(amountAOptimal >= amountAMin, "Router: INSUFFICIENT_A_AMOUNT");
        (amountA, amountB) = (amountAOptimal, amountBDesired);
      }
    }
  }

  function _addLiquidityToken(
    address pair,
    address tokenA,
    address tokenB,
    uint256 amountADesired,
    uint256 amountBDesired,
    uint256 amountAMin,
    uint256 amountBMin
  ) internal returns (uint256 amountA, uint256 amountB) {
    (amountA, amountB) = _addLiquidity(pair, tokenA, tokenB, amountADesired, amountBDesired, amountAMin, amountBMin);
    TransferHelper.safeTransferFrom(tokenA, msg.sender, pair, amountA);
    TransferHelper.safeTransferFrom(tokenB, msg.sender, pair, amountB);
  }

  function createPair(
    address tokenA,
    address tokenB,
    uint256 amountA,
    uint256 amountB,
    uint32 tokenWeightA,
    uint32 swapFee,
    address to
  ) public virtual override returns (uint256 liquidity) {
    address pair = IFireBirdFactory(factory).createPair(tokenA, tokenB, tokenWeightA, swapFee);
    _addLiquidityToken(pair, tokenA, tokenB, amountA, amountB, 0, 0);
    liquidity = IFireBirdPair(pair).mint(to);
  }

  function addLiquidity(
    address pair,
    address tokenA,
    address tokenB,
    uint256 amountADesired,
    uint256 amountBDesired,
    uint256 amountAMin,
    uint256 amountBMin,
    address to,
    uint256 deadline
  )
    external
    virtual
    override
    ensure(deadline)
    returns (
      uint256 amountA,
      uint256 amountB,
      uint256 liquidity
    )
  {
    (amountA, amountB) = _addLiquidityToken(pair, tokenA, tokenB, amountADesired, amountBDesired, amountAMin, amountBMin);
    liquidity = IFireBirdPair(pair).mint(to);
  }

  function _addLiquidityETH(
    address pair,
    address token,
    uint256 amountTokenDesired,
    uint256 amountTokenMin,
    uint256 amountETHMin,
    address to
  )
    internal
    returns (
      uint256 amountToken,
      uint256 amountETH,
      uint256 liquidity
    )
  {
    (amountToken, amountETH) = _addLiquidity(pair, token, WETH, amountTokenDesired, msg.value, amountTokenMin, amountETHMin);
    TransferHelper.safeTransferFrom(token, msg.sender, pair, amountToken);
    transferETHTo(amountETH, pair);
    liquidity = IFireBirdPair(pair).mint(to);
    // refund dust eth, if any
    if (msg.value > amountETH) TransferHelper.safeTransferETH(msg.sender, msg.value - amountETH);
  }

  function createPairETH(
    address token,
    uint256 amountToken,
    uint32 tokenWeight,
    uint32 swapFee,
    address to
  ) public payable virtual override returns (uint256 liquidity) {
    address pair = IFireBirdFactory(factory).createPair(token, WETH, tokenWeight, swapFee);
    (, , liquidity) = _addLiquidityETH(pair, token, amountToken, 0, 0, to);
  }

  function addLiquidityETH(
    address pair,
    address token,
    uint256 amountTokenDesired,
    uint256 amountTokenMin,
    uint256 amountETHMin,
    address to,
    uint256 deadline
  )
    public
    payable
    virtual
    override
    ensure(deadline)
    returns (
      uint256 amountToken,
      uint256 amountETH,
      uint256 liquidity
    )
  {
    (amountToken, amountETH, liquidity) = _addLiquidityETH(pair, token, amountTokenDesired, amountTokenMin, amountETHMin, to);
  }

  // **** SWAP ****
  // requires the initial amount to have already been sent to the first pair
  function _swap(
    address tokenIn,
    uint256[] memory amounts,
    address[] memory path,
    address _to
  ) internal virtual {
    address input = tokenIn;
    for (uint256 i = 0; i < path.length; i++) {
      IFireBirdPair pairV2 = IFireBirdPair(path[i]);
      address token0 = pairV2.token0();
      uint256 amountOut = amounts[i + 1];
      (uint256 amount0Out, uint256 amount1Out, address output) = input == token0 ? (uint256(0), amountOut, pairV2.token1()) : (amountOut, uint256(0), token0);
      if (swapFeeReward != address(0)) {
        ISwapFeeReward(swapFeeReward).swap(msg.sender, input, output, amountOut, path[i]);
      }
      address to = i < path.length - 1 ? path[i + 1] : _to;
      pairV2.swap(amount0Out, amount1Out, to, new bytes(0));
      emit Exchange(address(pairV2), amountOut, output);
      input = output;
    }
  }

  function swapExactTokensForTokens(
    address tokenIn,
    address tokenOut,
    uint256 amountIn,
    uint256 amountOutMin,
    address[] memory path,
    uint8[] memory dexIds,
    address to,
    uint256 deadline
  ) public virtual override ensure(deadline) returns (uint256[] memory amounts) {
    amounts = _validateAmountOut(tokenIn, tokenOut, amountIn, amountOutMin, path, dexIds);

    TransferHelper.safeTransferFrom(tokenIn, msg.sender, path[0], amounts[0]);
    _swap(tokenIn, amounts, path, to);
  }

  function swapTokensForExactTokens(
    address tokenIn,
    address tokenOut,
    uint256 amountOut,
    uint256 amountInMax,
    address[] calldata path,
    uint8[] calldata dexIds,
    address to,
    uint256 deadline
  ) external virtual override ensure(deadline) returns (uint256[] memory amounts) {
    amounts = _validateAmountIn(tokenIn, tokenOut, amountOut, amountInMax, path, dexIds);

    TransferHelper.safeTransferFrom(tokenIn, msg.sender, path[0], amounts[0]);
    _swap(tokenIn, amounts, path, to);
  }

  function swapExactETHForTokens(
    address tokenOut,
    uint256 amountOutMin,
    address[] calldata path,
    uint8[] calldata dexIds,
    address to,
    uint256 deadline
  ) external payable virtual override ensure(deadline) returns (uint256[] memory amounts) {
    amounts = _validateAmountOut(WETH, tokenOut, msg.value, amountOutMin, path, dexIds);

    transferETHTo(amounts[0], path[0]);
    _swap(WETH, amounts, path, to);
  }

  function swapTokensForExactETH(
    address tokenIn,
    uint256 amountOut,
    uint256 amountInMax,
    address[] calldata path,
    uint8[] calldata dexIds,
    address to,
    uint256 deadline
  ) external virtual override ensure(deadline) returns (uint256[] memory amounts) {
    amounts = _validateAmountIn(tokenIn, WETH, amountOut, amountInMax, path, dexIds);

    TransferHelper.safeTransferFrom(tokenIn, msg.sender, path[0], amounts[0]);
    _swap(tokenIn, amounts, path, address(this));
    transferAll(ETH_ADDRESS, to, amounts[amounts.length - 1]);
  }

  function swapExactTokensForETH(
    address tokenIn,
    uint256 amountIn,
    uint256 amountOutMin,
    address[] calldata path,
    uint8[] calldata dexIds,
    address to,
    uint256 deadline
  ) external virtual override ensure(deadline) returns (uint256[] memory amounts) {
    amounts = _validateAmountOut(tokenIn, WETH, amountIn, amountOutMin, path, dexIds);

    TransferHelper.safeTransferFrom(tokenIn, msg.sender, path[0], amounts[0]);
    _swap(tokenIn, amounts, path, address(this));
    transferAll(ETH_ADDRESS, to, amounts[amounts.length - 1]);
  }

  function swapETHForExactTokens(
    address tokenOut,
    uint256 amountOut,
    address[] calldata path,
    uint8[] calldata dexIds,
    address to,
    uint256 deadline
  ) external payable virtual override ensure(deadline) returns (uint256[] memory amounts) {
    amounts = _validateAmountIn(WETH, tokenOut, amountOut, msg.value, path, dexIds);

    transferETHTo(amounts[0], path[0]);
    _swap(WETH, amounts, path, to);
    // refund dust eth, if any
    if (msg.value > amounts[0]) TransferHelper.safeTransferETH(msg.sender, msg.value - amounts[0]);
  }

  // **** SWAP (supporting fee-on-transfer tokens) ****
  // requires the initial amount to have already been sent to the first pair
  function _swapSupportingFeeOnTransferTokens(
    address tokenIn,
    address[] memory path,
    uint8[] memory dexIds,
    address _to
  ) internal virtual {
    for (uint256 i; i < path.length; i++) {
      uint256 amountOutput;
      address currentOutput;
      {
        (address output, uint256 reserveInput, uint256 reserveOutput, uint32 tokenWeightInput, , uint32 swapFee) = IFireBirdFormula(formula).getFactoryReserveAndWeights(
          factory,
          path[i],
          tokenIn,
          dexIds[i]
        );
        uint256 amountInput = IERC20(tokenIn).balanceOf(path[i]).sub(reserveInput);
        amountOutput = IFireBirdFormula(formula).getAmountOut(amountInput, reserveInput, reserveOutput, tokenWeightInput, 100 - tokenWeightInput, swapFee);
        currentOutput = output;
      }

      IFireBirdPair pair = IFireBirdPair(path[i]);
      (uint256 amount0Out, uint256 amount1Out) = tokenIn == pair.token0() ? (uint256(0), amountOutput) : (amountOutput, uint256(0));
      if (swapFeeReward != address(0)) {
        ISwapFeeReward(swapFeeReward).swap(msg.sender, tokenIn, currentOutput, amountOutput, path[i]);
      }
      address to = i < path.length - 1 ? path[i + 1] : _to;
      pair.swap(amount0Out, amount1Out, to, new bytes(0));
      emit Exchange(path[i], amountOutput, currentOutput);
      tokenIn = currentOutput;
    }
  }

  function swapExactTokensForTokensSupportingFeeOnTransferTokens(
    address tokenIn,
    address tokenOut,
    uint256 amountIn,
    uint256 amountOutMin,
    address[] calldata path,
    uint8[] calldata dexIds,
    address to,
    uint256 deadline
  ) external virtual override ensure(deadline) {
    TransferHelper.safeTransferFrom(tokenIn, msg.sender, path[0], amountIn);
    uint256 balanceBefore = IERC20(tokenOut).balanceOf(to);
    _swapSupportingFeeOnTransferTokens(tokenIn, path, dexIds, to);
    require(IERC20(tokenOut).balanceOf(to).sub(balanceBefore) >= amountOutMin, "Router: INSUFFICIENT_OUTPUT_AMOUNT");
  }

  function swapExactETHForTokensSupportingFeeOnTransferTokens(
    address tokenOut,
    uint256 amountOutMin,
    address[] calldata path,
    uint8[] calldata dexIds,
    address to,
    uint256 deadline
  ) external payable virtual override ensure(deadline) {
    //            require(path[0] == WETH, 'Router: INVALID_PATH');
    uint256 amountIn = msg.value;
    transferETHTo(amountIn, path[0]);
    uint256 balanceBefore = IERC20(tokenOut).balanceOf(to);
    _swapSupportingFeeOnTransferTokens(WETH, path, dexIds, to);
    require(IERC20(tokenOut).balanceOf(to).sub(balanceBefore) >= amountOutMin, "Router: INSUFFICIENT_OUTPUT_AMOUNT");
  }

  function swapExactTokensForETHSupportingFeeOnTransferTokens(
    address tokenIn,
    uint256 amountIn,
    uint256 amountOutMin,
    address[] calldata path,
    uint8[] calldata dexIds,
    address to,
    uint256 deadline
  ) external virtual override ensure(deadline) {
    TransferHelper.safeTransferFrom(tokenIn, msg.sender, path[0], amountIn);
    _swapSupportingFeeOnTransferTokens(tokenIn, path, dexIds, address(this));
    uint256 amountOut = IERC20(WETH).balanceOf(address(this));
    require(amountOut >= amountOutMin, "Router: INSUFFICIENT_OUTPUT_AMOUNT");
    transferAll(ETH_ADDRESS, to, amountOut);
  }

  function swap(
    IAggregationExecutor caller,
    SwapDescription calldata desc,
    bytes calldata data
  ) external payable returns (uint256 returnAmount) {
    require(desc.minReturnAmount > 0, "Min return should not be 0");
    require(data.length > 0, "data should be not zero");

    uint256 flags = desc.flags;
    uint256 amount = desc.amount;
    IERC20 srcToken = desc.srcToken;
    IERC20 dstToken = desc.dstToken;

    if (flags & _REQUIRES_EXTRA_ETH != 0) {
      require(msg.value > (isETH(srcToken) ? amount : 0), "Invalid msg.value");
    } else {
      require(msg.value == (isETH(srcToken) ? amount : 0), "Invalid msg.value");
    }

    if (flags & _SHOULD_CLAIM != 0) {
      require(!isETH(srcToken), "Claim token is ETH");
      _permit(srcToken, amount, desc.permit);
      TransferHelper.safeTransferFrom(address(srcToken), msg.sender, desc.srcReceiver, amount);
    }

    address dstReceiver = (desc.dstReceiver == address(0)) ? msg.sender : desc.dstReceiver;
    uint256 initialSrcBalance = (flags & _PARTIAL_FILL != 0) ? getBalance(srcToken, msg.sender) : 0;
    uint256 initialDstBalance = getBalance(dstToken, dstReceiver);

    {
      // solhint-disable-next-line avoid-low-level-calls
      (bool success, bytes memory result) = address(caller).call{value: msg.value}(abi.encodeWithSelector(caller.callBytes.selector, data, msg.sender));
      if (!success) {
        revert(RevertReasonParser.parse(result, "callBytes failed: "));
      }
    }

    uint256 spentAmount = amount;
    returnAmount = getBalance(dstToken, dstReceiver).sub(initialDstBalance);

    if (flags & _PARTIAL_FILL != 0) {
      spentAmount = initialSrcBalance.add(amount).sub(getBalance(srcToken, msg.sender));
      require(returnAmount.mul(amount) >= desc.minReturnAmount.mul(spentAmount), "Return amount is not enough");
    } else {
      require(returnAmount >= desc.minReturnAmount, "Return amount is not enough");
    }

    emit Swapped(msg.sender, srcToken, dstToken, dstReceiver, spentAmount, returnAmount);
    emit Exchange(address(caller), returnAmount, isETH(dstToken) ? WETH : address(dstToken));
  }

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

  function _validateAmountOut(
    address tokenIn,
    address tokenOut,
    uint256 amountIn,
    uint256 amountOutMin,
    address[] memory path,
    uint8[] memory dexIds
  ) internal view returns (uint256[] memory amounts) {
    amounts = IFireBirdFormula(formula).getFactoryAmountsOut(factory, tokenIn, tokenOut, amountIn, path, dexIds);
    require(amounts[amounts.length - 1] >= amountOutMin, "Router: INSUFFICIENT_OUTPUT_AMOUNT");
  }

  function _validateAmountIn(
    address tokenIn,
    address tokenOut,
    uint256 amountOut,
    uint256 amountInMax,
    address[] calldata path,
    uint8[] calldata dexIds
  ) internal view returns (uint256[] memory amounts) {
    amounts = IFireBirdFormula(formula).getFactoryAmountsIn(factory, tokenIn, tokenOut, amountOut, path, dexIds);
    require(amounts[0] <= amountInMax, "Router: EXCESSIVE_INPUT_AMOUNT");
  }

  function transferETHTo(uint256 amount, address to) internal {
    IWETH(WETH).deposit{value: amount}();
    assert(IWETH(WETH).transfer(to, amount));
  }

  function transferAll(
    address token,
    address to,
    uint256 amount
  ) internal returns (bool) {
    if (amount == 0) {
      return true;
    }

    if (isETH(IERC20(token))) {
      IWETH(WETH).withdraw(amount);
      TransferHelper.safeTransferETH(to, amount);
    } else {
      TransferHelper.safeTransfer(token, to, amount);
    }
    return true;
  }

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

  // **** REMOVE LIQUIDITY ****
  function _removeLiquidity(
    address pair,
    address tokenA,
    address tokenB,
    uint256 liquidity,
    uint256 amountAMin,
    uint256 amountBMin,
    address to
  ) internal returns (uint256 amountA, uint256 amountB) {
    require(IFireBirdFactory(factory).isPair(pair), "Router: Invalid pair");
    IFireBirdPair(pair).transferFrom(msg.sender, pair, liquidity);
    // send liquidity to pair
    (uint256 amount0, uint256 amount1) = IFireBirdPair(pair).burn(to);
    (address token0, ) = IFireBirdFormula(formula).sortTokens(tokenA, tokenB);
    (amountA, amountB) = tokenA == token0 ? (amount0, amount1) : (amount1, amount0);
    require(amountA >= amountAMin, "Router: INSUFFICIENT_A_AMOUNT");
    require(amountB >= amountBMin, "Router: INSUFFICIENT_B_AMOUNT");
  }

  function removeLiquidity(
    address pair,
    address tokenA,
    address tokenB,
    uint256 liquidity,
    uint256 amountAMin,
    uint256 amountBMin,
    address to,
    uint256 deadline
  ) public virtual override ensure(deadline) returns (uint256 amountA, uint256 amountB) {
    (amountA, amountB) = _removeLiquidity(pair, tokenA, tokenB, liquidity, amountAMin, amountBMin, to);
  }

  function removeLiquidityETH(
    address pair,
    address token,
    uint256 liquidity,
    uint256 amountTokenMin,
    uint256 amountETHMin,
    address to,
    uint256 deadline
  ) public virtual override ensure(deadline) returns (uint256 amountToken, uint256 amountETH) {
    (amountToken, amountETH) = _removeLiquidity(pair, token, WETH, liquidity, amountTokenMin, amountETHMin, address(this));
    TransferHelper.safeTransfer(token, to, amountToken);
    transferAll(ETH_ADDRESS, to, amountETH);
  }

  function removeLiquidityWithPermit(
    address pair,
    address tokenA,
    address tokenB,
    uint256 liquidity,
    uint256 amountAMin,
    uint256 amountBMin,
    address to,
    uint256 deadline,
    bool approveMax,
    uint8 v,
    bytes32 r,
    bytes32 s
  ) external virtual override ensure(deadline) returns (uint256 amountA, uint256 amountB) {
    {
      uint256 value = approveMax ? uint256(-1) : liquidity;
      IFireBirdPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);
    }
    (amountA, amountB) = _removeLiquidity(pair, tokenA, tokenB, liquidity, amountAMin, amountBMin, to);
  }

  function removeLiquidityETHWithPermit(
    address pair,
    address token,
    uint256 liquidity,
    uint256 amountTokenMin,
    uint256 amountETHMin,
    address to,
    uint256 deadline,
    bool approveMax,
    uint8 v,
    bytes32 r,
    bytes32 s
  ) external virtual override returns (uint256 amountToken, uint256 amountETH) {
    uint256 value = approveMax ? uint256(-1) : liquidity;
    IFireBirdPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);
    (amountToken, amountETH) = removeLiquidityETH(pair, token, liquidity, amountTokenMin, amountETHMin, to, deadline);
  }

  // **** REMOVE LIQUIDITY (supporting fee-on-transfer tokens) ****
  function removeLiquidityETHSupportingFeeOnTransferTokens(
    address pair,
    address token,
    uint256 liquidity,
    uint256 amountTokenMin,
    uint256 amountETHMin,
    address to,
    uint256 deadline
  ) public virtual override ensure(deadline) returns (uint256 amountETH) {
    (, amountETH) = removeLiquidity(pair, token, WETH, liquidity, amountTokenMin, amountETHMin, address(this), deadline);
    TransferHelper.safeTransfer(token, to, IERC20(token).balanceOf(address(this)));
    transferAll(ETH_ADDRESS, to, amountETH);
  }

  function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
    address pair,
    address token,
    uint256 liquidity,
    uint256 amountTokenMin,
    uint256 amountETHMin,
    address to,
    uint256 deadline,
    bool approveMax,
    uint8 v,
    bytes32 r,
    bytes32 s
  ) external virtual override returns (uint256 amountETH) {
    uint256 value = approveMax ? uint256(-1) : liquidity;
    IFireBirdPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);
    amountETH = removeLiquidityETHSupportingFeeOnTransferTokens(pair, token, liquidity, amountTokenMin, amountETHMin, to, deadline);
  }

  function rescueFunds(address token, uint256 amount) external onlyOwner {
    if (isETH(IERC20(token))) {
      TransferHelper.safeTransferETH(msg.sender, amount);
    } else {
      TransferHelper.safeTransfer(token, msg.sender, amount);
    }
  }
}
        

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_factory","internalType":"address"},{"type":"address","name":"_formula","internalType":"address"},{"type":"address","name":"_WETH","internalType":"address"}]},{"type":"event","name":"Error","inputs":[{"type":"string","name":"reason","internalType":"string","indexed":false}],"anonymous":false},{"type":"event","name":"Exchange","inputs":[{"type":"address","name":"pair","internalType":"address","indexed":false},{"type":"uint256","name":"amountOut","internalType":"uint256","indexed":false},{"type":"address","name":"output","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Swapped","inputs":[{"type":"address","name":"sender","internalType":"address","indexed":false},{"type":"address","name":"srcToken","internalType":"contract IERC20","indexed":false},{"type":"address","name":"dstToken","internalType":"contract IERC20","indexed":false},{"type":"address","name":"dstReceiver","internalType":"address","indexed":false},{"type":"uint256","name":"spentAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"returnAmount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"WETH","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"amountA","internalType":"uint256"},{"type":"uint256","name":"amountB","internalType":"uint256"},{"type":"uint256","name":"liquidity","internalType":"uint256"}],"name":"addLiquidity","inputs":[{"type":"address","name":"pair","internalType":"address"},{"type":"address","name":"tokenA","internalType":"address"},{"type":"address","name":"tokenB","internalType":"address"},{"type":"uint256","name":"amountADesired","internalType":"uint256"},{"type":"uint256","name":"amountBDesired","internalType":"uint256"},{"type":"uint256","name":"amountAMin","internalType":"uint256"},{"type":"uint256","name":"amountBMin","internalType":"uint256"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"payable","outputs":[{"type":"uint256","name":"amountToken","internalType":"uint256"},{"type":"uint256","name":"amountETH","internalType":"uint256"},{"type":"uint256","name":"liquidity","internalType":"uint256"}],"name":"addLiquidityETH","inputs":[{"type":"address","name":"pair","internalType":"address"},{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"amountTokenDesired","internalType":"uint256"},{"type":"uint256","name":"amountTokenMin","internalType":"uint256"},{"type":"uint256","name":"amountETHMin","internalType":"uint256"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"liquidity","internalType":"uint256"}],"name":"createPair","inputs":[{"type":"address","name":"tokenA","internalType":"address"},{"type":"address","name":"tokenB","internalType":"address"},{"type":"uint256","name":"amountA","internalType":"uint256"},{"type":"uint256","name":"amountB","internalType":"uint256"},{"type":"uint32","name":"tokenWeightA","internalType":"uint32"},{"type":"uint32","name":"swapFee","internalType":"uint32"},{"type":"address","name":"to","internalType":"address"}]},{"type":"function","stateMutability":"payable","outputs":[{"type":"uint256","name":"liquidity","internalType":"uint256"}],"name":"createPairETH","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"amountToken","internalType":"uint256"},{"type":"uint32","name":"tokenWeight","internalType":"uint32"},{"type":"uint32","name":"swapFee","internalType":"uint32"},{"type":"address","name":"to","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"factory","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"formula","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"amountA","internalType":"uint256"},{"type":"uint256","name":"amountB","internalType":"uint256"}],"name":"removeLiquidity","inputs":[{"type":"address","name":"pair","internalType":"address"},{"type":"address","name":"tokenA","internalType":"address"},{"type":"address","name":"tokenB","internalType":"address"},{"type":"uint256","name":"liquidity","internalType":"uint256"},{"type":"uint256","name":"amountAMin","internalType":"uint256"},{"type":"uint256","name":"amountBMin","internalType":"uint256"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"amountToken","internalType":"uint256"},{"type":"uint256","name":"amountETH","internalType":"uint256"}],"name":"removeLiquidityETH","inputs":[{"type":"address","name":"pair","internalType":"address"},{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"liquidity","internalType":"uint256"},{"type":"uint256","name":"amountTokenMin","internalType":"uint256"},{"type":"uint256","name":"amountETHMin","internalType":"uint256"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"amountETH","internalType":"uint256"}],"name":"removeLiquidityETHSupportingFeeOnTransferTokens","inputs":[{"type":"address","name":"pair","internalType":"address"},{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"liquidity","internalType":"uint256"},{"type":"uint256","name":"amountTokenMin","internalType":"uint256"},{"type":"uint256","name":"amountETHMin","internalType":"uint256"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"amountToken","internalType":"uint256"},{"type":"uint256","name":"amountETH","internalType":"uint256"}],"name":"removeLiquidityETHWithPermit","inputs":[{"type":"address","name":"pair","internalType":"address"},{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"liquidity","internalType":"uint256"},{"type":"uint256","name":"amountTokenMin","internalType":"uint256"},{"type":"uint256","name":"amountETHMin","internalType":"uint256"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"},{"type":"bool","name":"approveMax","internalType":"bool"},{"type":"uint8","name":"v","internalType":"uint8"},{"type":"bytes32","name":"r","internalType":"bytes32"},{"type":"bytes32","name":"s","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"amountETH","internalType":"uint256"}],"name":"removeLiquidityETHWithPermitSupportingFeeOnTransferTokens","inputs":[{"type":"address","name":"pair","internalType":"address"},{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"liquidity","internalType":"uint256"},{"type":"uint256","name":"amountTokenMin","internalType":"uint256"},{"type":"uint256","name":"amountETHMin","internalType":"uint256"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"},{"type":"bool","name":"approveMax","internalType":"bool"},{"type":"uint8","name":"v","internalType":"uint8"},{"type":"bytes32","name":"r","internalType":"bytes32"},{"type":"bytes32","name":"s","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"amountA","internalType":"uint256"},{"type":"uint256","name":"amountB","internalType":"uint256"}],"name":"removeLiquidityWithPermit","inputs":[{"type":"address","name":"pair","internalType":"address"},{"type":"address","name":"tokenA","internalType":"address"},{"type":"address","name":"tokenB","internalType":"address"},{"type":"uint256","name":"liquidity","internalType":"uint256"},{"type":"uint256","name":"amountAMin","internalType":"uint256"},{"type":"uint256","name":"amountBMin","internalType":"uint256"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"},{"type":"bool","name":"approveMax","internalType":"bool"},{"type":"uint8","name":"v","internalType":"uint8"},{"type":"bytes32","name":"r","internalType":"bytes32"},{"type":"bytes32","name":"s","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"rescueFunds","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setSwapFeeReward","inputs":[{"type":"address","name":"_swapFeeReward","internalType":"address"}]},{"type":"function","stateMutability":"payable","outputs":[{"type":"uint256","name":"returnAmount","internalType":"uint256"}],"name":"swap","inputs":[{"type":"address","name":"caller","internalType":"contract IAggregationExecutor"},{"type":"tuple","name":"desc","internalType":"struct FireBirdRouter.SwapDescription","components":[{"type":"address","name":"srcToken","internalType":"contract IERC20"},{"type":"address","name":"dstToken","internalType":"contract IERC20"},{"type":"address","name":"srcReceiver","internalType":"address"},{"type":"address","name":"dstReceiver","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"minReturnAmount","internalType":"uint256"},{"type":"uint256","name":"flags","internalType":"uint256"},{"type":"bytes","name":"permit","internalType":"bytes"}]},{"type":"bytes","name":"data","internalType":"bytes"}]},{"type":"function","stateMutability":"payable","outputs":[{"type":"uint256[]","name":"amounts","internalType":"uint256[]"}],"name":"swapETHForExactTokens","inputs":[{"type":"address","name":"tokenOut","internalType":"address"},{"type":"uint256","name":"amountOut","internalType":"uint256"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"uint8[]","name":"dexIds","internalType":"uint8[]"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"payable","outputs":[{"type":"uint256[]","name":"amounts","internalType":"uint256[]"}],"name":"swapExactETHForTokens","inputs":[{"type":"address","name":"tokenOut","internalType":"address"},{"type":"uint256","name":"amountOutMin","internalType":"uint256"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"uint8[]","name":"dexIds","internalType":"uint8[]"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"swapExactETHForTokensSupportingFeeOnTransferTokens","inputs":[{"type":"address","name":"tokenOut","internalType":"address"},{"type":"uint256","name":"amountOutMin","internalType":"uint256"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"uint8[]","name":"dexIds","internalType":"uint8[]"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256[]","name":"amounts","internalType":"uint256[]"}],"name":"swapExactTokensForETH","inputs":[{"type":"address","name":"tokenIn","internalType":"address"},{"type":"uint256","name":"amountIn","internalType":"uint256"},{"type":"uint256","name":"amountOutMin","internalType":"uint256"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"uint8[]","name":"dexIds","internalType":"uint8[]"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"swapExactTokensForETHSupportingFeeOnTransferTokens","inputs":[{"type":"address","name":"tokenIn","internalType":"address"},{"type":"uint256","name":"amountIn","internalType":"uint256"},{"type":"uint256","name":"amountOutMin","internalType":"uint256"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"uint8[]","name":"dexIds","internalType":"uint8[]"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256[]","name":"amounts","internalType":"uint256[]"}],"name":"swapExactTokensForTokens","inputs":[{"type":"address","name":"tokenIn","internalType":"address"},{"type":"address","name":"tokenOut","internalType":"address"},{"type":"uint256","name":"amountIn","internalType":"uint256"},{"type":"uint256","name":"amountOutMin","internalType":"uint256"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"uint8[]","name":"dexIds","internalType":"uint8[]"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"swapExactTokensForTokensSupportingFeeOnTransferTokens","inputs":[{"type":"address","name":"tokenIn","internalType":"address"},{"type":"address","name":"tokenOut","internalType":"address"},{"type":"uint256","name":"amountIn","internalType":"uint256"},{"type":"uint256","name":"amountOutMin","internalType":"uint256"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"uint8[]","name":"dexIds","internalType":"uint8[]"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"swapFeeReward","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256[]","name":"amounts","internalType":"uint256[]"}],"name":"swapTokensForExactETH","inputs":[{"type":"address","name":"tokenIn","internalType":"address"},{"type":"uint256","name":"amountOut","internalType":"uint256"},{"type":"uint256","name":"amountInMax","internalType":"uint256"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"uint8[]","name":"dexIds","internalType":"uint8[]"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256[]","name":"amounts","internalType":"uint256[]"}],"name":"swapTokensForExactTokens","inputs":[{"type":"address","name":"tokenIn","internalType":"address"},{"type":"address","name":"tokenOut","internalType":"address"},{"type":"uint256","name":"amountOut","internalType":"uint256"},{"type":"uint256","name":"amountInMax","internalType":"uint256"},{"type":"address[]","name":"path","internalType":"address[]"},{"type":"uint8[]","name":"dexIds","internalType":"uint8[]"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"receive","stateMutability":"payable"}]
            

Contract Creation Code

0x60e06040523480156200001157600080fd5b5060405162006091380380620060918339810160408190526200003491620000d3565b600062000040620000b2565b600080546001600160a01b0319166001600160a01b0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3506001600160601b0319606093841b811660805291831b821660a05290911b1660c0526200011c565b3390565b80516001600160a01b0381168114620000ce57600080fd5b919050565b600080600060608486031215620000e8578283fd5b620000f384620000b6565b92506200010360208501620000b6565b91506200011360408501620000b6565b90509250925092565b60805160601c60a05160601c60c05160601c615ea4620001ed600039806101e352806107725280610a395280610b6d5280610e1052806115c052806116f252806117bb528061191d52806119825280611a635280611ed5528061201f52806120615280612aad5280612b4552806134dd52806135965250806108c4528061254e52806126a25280612e6e528061301e5280613ffd528061416e528061427a5280614391525080610b305280611aca5280611af1528061258a5280612c53528061304b528061402a5250615ea46000f3fe6080604052600436106101c65760003560e01c8063991bffc7116100f7578063d0f2c82a11610095578063f0c62e2b11610064578063f0c62e2b146104fb578063f2fde38b1461050e578063fbbeedf11461052e578063fbf451351461054e5761020c565b8063d0f2c82a1461047b578063dc9f70291461049b578063e1f4a784146104bb578063ebb5d2e9146104db5761020c565b8063ad5c4648116100d1578063ad5c464814610411578063af7e6aec14610426578063b56b681d14610446578063c45a0155146104665761020c565b8063991bffc7146103c9578063a3ddb30b146103dc578063a4aabb08146103f15761020c565b8063715018a6116101645780637a286fa21161013e5780637a286fa2146103615780637c0252001461038157806389df37af146103945780638da5cb5b146103b45761020c565b8063715018a614610319578063752ebb7c1461032e57806378e3214f146103415761020c565b80634b75f54f116101a05780634b75f54f146102895780634c17fd7c146102ab578063674f19f8146102d95780636cb49428146103065761020c565b80630e2f024c14610211578063242e3b9f146102475780633990ba54146102675761020c565b3661020c573373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461020a57fe5b005b600080fd5b34801561021d57600080fd5b5061023161022c366004614c39565b61056e565b60405161023e919061537b565b60405180910390f35b34801561025357600080fd5b5061020a610262366004614e36565b610651565b61027a610275366004614bc8565b610860565b60405161023e93929190615d0e565b34801561029557600080fd5b5061029e6108c2565b60405161023e9190615384565b3480156102b757600080fd5b506102cb6102c63660046148a1565b6108e6565b60405161023e929190615cc5565b3480156102e557600080fd5b506102f96102f4366004614e36565b6109f6565b60405161023e9190615720565b610231610314366004614f58565b610b2b565b34801561032557600080fd5b5061020a610c1d565b61020a61033c366004614d90565b610cff565b34801561034d57600080fd5b5061020a61035c366004614d65565b610f74565b34801561036d57600080fd5b506102f961037c3660046149ea565b611013565b61023161038f36600461506b565b6110c3565b3480156103a057600080fd5b506102f96103af366004614aad565b611607565b3480156103c057600080fd5b5061029e611694565b6102f96103d7366004614d90565b6116b0565b3480156103e857600080fd5b5061029e611816565b3480156103fd57600080fd5b506102cb61040c366004614c39565b611832565b34801561041d57600080fd5b5061029e61191b565b34801561043257600080fd5b506102f9610441366004614e36565b61193f565b34801561045257600080fd5b506102cb610461366004614bc8565b611a1e565b34801561047257600080fd5b5061029e611ac8565b34801561048757600080fd5b50610231610496366004614ce2565b611aec565b3480156104a757600080fd5b5061020a6104b63660046149ea565b611c58565b3480156104c757600080fd5b506102cb6104d636600461481d565b611e32565b3480156104e757600080fd5b506102316104f6366004614bc8565b611e91565b6102f9610509366004614d90565b611fdd565b34801561051a57600080fd5b5061020a6105293660046147ac565b6120f8565b34801561053a57600080fd5b5061020a6105493660046147ac565b612245565b34801561055a57600080fd5b5061027a61056936600461495c565b6122ff565b6000808561057c578a61059e565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b6040517fd505accf00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff8e169063d505accf906105ff903390309086908d908c908c908c906004016153cc565b600060405180830381600087803b15801561061957600080fd5b505af115801561062d573d6000803e3d6000fd5b505050506106408d8d8d8d8d8d8d611e91565b9d9c50505050505050505050505050565b8042811015610695576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615ad2565b60405180910390fd5b6106c28a33898960008181106106a757fe5b90506020020160208101906106bc91906147ac565b8c612409565b6107328a88888080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808c0282810182019093528b82529093508b92508a918291850190849080828437600092019190915250309250612535915050565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a08231906107a7903090600401615384565b60206040518083038186803b1580156107bf57600080fd5b505afa1580156107d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107f79190615111565b905088811015610833576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615b77565b61085273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8583612a53565b505050505050505050505050565b600080600083428110156108a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615ad2565b6108ae8b8b8b8b8b8b612b39565b919d909c50909a5098505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000808642811015610924576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615ad2565b600087610931578c610953565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b90508f73ffffffffffffffffffffffffffffffffffffffff1663d505accf3330848d8c8c8c6040518863ffffffff1660e01b815260040161099a97969594939291906153cc565b600060405180830381600087803b1580156109b457600080fd5b505af11580156109c8573d6000803e3d6000fd5b50505050506109dc8f8f8f8f8f8f8f612c4e565b8093508194505050509c509c9a5050505050505050505050565b60608142811015610a33576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615ad2565b610a638b7f00000000000000000000000000000000000000000000000000000000000000008c8c8c8c8c8c612fde565b9150610aa68b338a8a6000818110610a7757fe5b9050602002016020810190610a8c91906147ac565b85600081518110610a9957fe5b6020026020010151612409565b610ae68b838a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525030925061314f915050565b610b1c73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8584600186510381518110610b0f57fe5b6020026020010151612a53565b50509998505050505050505050565b6000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166314572adb887f000000000000000000000000000000000000000000000000000000000000000088886040518563ffffffff1660e01b8152600401610bad949392919061568c565b602060405180830381600087803b158015610bc757600080fd5b505af1158015610bdb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bff91906147c8565b9050610c1081888860008088612b39565b9998505050505050505050565b610c256134d7565b73ffffffffffffffffffffffffffffffffffffffff16610c43611694565b73ffffffffffffffffffffffffffffffffffffffff1614610c90576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615a9d565b6000805460405173ffffffffffffffffffffffffffffffffffffffff909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b8042811015610d3a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615ad2565b34610d64818989600081610d4a57fe5b9050602002016020810190610d5f91906147ac565b6134db565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff8c16906370a0823190610db9908890600401615384565b60206040518083038186803b158015610dd157600080fd5b505afa158015610de5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e099190615111565b9050610e9b7f00000000000000000000000000000000000000000000000000000000000000008a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250612535915050565b89610f2f828d73ffffffffffffffffffffffffffffffffffffffff166370a08231896040518263ffffffff1660e01b8152600401610ed99190615384565b60206040518083038186803b158015610ef157600080fd5b505afa158015610f05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f299190615111565b90613628565b1015610f67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615b77565b5050505050505050505050565b610f7c6134d7565b73ffffffffffffffffffffffffffffffffffffffff16610f9a611694565b73ffffffffffffffffffffffffffffffffffffffff1614610fe7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615a9d565b610ff08261366b565b1561100457610fff338261369e565b61100f565b61100f823383613757565b5050565b60608142811015611050576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615ad2565b6110608c8c8c8c8c8c8c8c612fde565b91506110748c338a8a6000818110610a7757fe5b6110b48c838a8a808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508a925061314f915050565b509a9950505050505050505050565b6000808460a0013511611102576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615a66565b81611139576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615b09565b60c08401356080850135600061115260208801886147ac565b905060006111666040890160208a016147ac565b905060028416156111c45761117a8261366b565b611185576000611187565b825b34116111bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c906159c1565b611212565b6111cd8261366b565b6111d85760006111da565b825b3414611212576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c906159c1565b600484161561128d576112248261366b565b1561125b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615851565b611272828461126d60e08c018c615d58565b613879565b61128d823361128760608c0160408d016147ac565b86612409565b6000806112a060808b0160608c016147ac565b73ffffffffffffffffffffffffffffffffffffffff16146112d0576112cb60808a0160608b016147ac565b6112d2565b335b90506000600186166112e55760006112ef565b6112ef8433613a86565b905060006112fd8484613a86565b90506000808d73ffffffffffffffffffffffffffffffffffffffff1634635697e45360e01b8e8e3360405160240161133793929190615764565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516113c0919061520f565b60006040518083038185875af1925050503d80600081146113fd576040519150601f19603f3d011682016040523d82523d6000602084013e611402565b606091505b50915091508161147e5761144b816040518060400160405280601281526020017f63616c6c4279746573206661696c65643a200000000000000000000000000000815250613b5d565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c91906157d0565b5086905061149082610f298787613a86565b98506001881615611509576114b26114a88733613a86565b610f29858a613f2f565b90506114c260a08d013582613f6c565b6114cc8a89613f6c565b1015611504576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615a2f565b611547565b8b60a00135891015611547576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615a2f565b7fd6d4f5681c246c9f42c203e287975af1601f8df8035a9251f79aab5c8f09e2f833878787858e60405161158096959493929190615488565b60405180910390a17fddac40937f35385a34f721af292e5a83fc5b840f722bff57c2fc71adba708c488d8a6115b48861366b565b6115be57876115e0565b7f00000000000000000000000000000000000000000000000000000000000000005b6040516115ef939291906156f0565b60405180910390a15050505050505050949350505050565b60608142811015611644576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615ad2565b6116528a8a8a8a8a8a613fbd565b915061167b8a338860008151811061166657fe5b602002602001015185600081518110610a9957fe5b6116878a83888761314f565b5098975050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1690565b606081428110156116ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615ad2565b61178f7f00000000000000000000000000000000000000000000000000000000000000008b348c8c8c80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508b8b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250613fbd92505050565b91506117b6826000815181106117a157fe5b602002602001015189896000818110610d4a57fe5b6116877f0000000000000000000000000000000000000000000000000000000000000000838a8a808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508a925061314f915050565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b600080600086611842578b611864565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b6040517fd505accf00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff8f169063d505accf906118c5903390309086908e908d908d908d906004016153cc565b600060405180830381600087803b1580156118df57600080fd5b505af11580156118f3573d6000803e3d6000fd5b505050506119068e8e8e8e8e8e8e611a1e565b909f909e509c50505050505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6060814281101561197c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615ad2565b610a638b7f00000000000000000000000000000000000000000000000000000000000000008c8c8c8c80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508b8b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250613fbd92505050565b6000808242811015611a5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615ad2565b611a8b8a8a7f00000000000000000000000000000000000000000000000000000000000000008b8b8b30612c4e565b9093509150611a9b898685613757565b611aba73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8684612a53565b505097509795505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166314572adb8a8a88886040518563ffffffff1660e01b8152600401611b4e949392919061568c565b602060405180830381600087803b158015611b6857600080fd5b505af1158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba091906147c8565b9050611bb2818a8a8a8a60008061412b565b50506040517f6a62784200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821690636a62784290611c06908690600401615384565b602060405180830381600087803b158015611c2057600080fd5b505af1158015611c34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c109190615111565b8042811015611c93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615ad2565b611ca58b33898960008181106106a757fe5b6040517f70a0823100000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff8c16906370a0823190611cfa908790600401615384565b60206040518083038186803b158015611d1257600080fd5b505afa158015611d26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d4a9190615111565b9050611dbc8c89898080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808d0282810182019093528c82529093508c92508b9182918501908490808284376000920191909152508a9250612535915050565b88611dfa828d73ffffffffffffffffffffffffffffffffffffffff166370a08231886040518263ffffffff1660e01b8152600401610ed99190615384565b1015610852576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615b77565b6000808242811015611e70576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615ad2565b611e7f8b8b8b8b8b8b8b612c4e565b909c909b509950505050505050505050565b60008142811015611ece576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615ad2565b611efe89897f00000000000000000000000000000000000000000000000000000000000000008a8a8a308a611e32565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152909350611fb191508990869073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190611f5c903090600401615384565b60206040518083038186803b158015611f7457600080fd5b505afa158015611f88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fac9190615111565b613757565b611fd073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8584612a53565b5050979650505050505050565b6060814281101561201a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615ad2565b61204a7f00000000000000000000000000000000000000000000000000000000000000008b8b348c8c8c8c612fde565b915061205c826000815181106117a157fe5b6120bc7f0000000000000000000000000000000000000000000000000000000000000000838a8a808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508a925061314f915050565b816000815181106120c957fe5b60200260200101513411156116875761168733836000815181106120e957fe5b6020026020010151340361369e565b6121006134d7565b73ffffffffffffffffffffffffffffffffffffffff1661211e611694565b73ffffffffffffffffffffffffffffffffffffffff161461216b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615a9d565b73ffffffffffffffffffffffffffffffffffffffff81166121b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615888565b6000805460405173ffffffffffffffffffffffffffffffffffffffff808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b61224d6134d7565b73ffffffffffffffffffffffffffffffffffffffff1661226b611694565b73ffffffffffffffffffffffffffffffffffffffff16146122b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615a9d565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6000806000834281101561233f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615ad2565b61234e8d8d8d8d8d8d8d61412b565b6040517f6a627842000000000000000000000000000000000000000000000000000000008152919550935073ffffffffffffffffffffffffffffffffffffffff8e1690636a627842906123a5908990600401615384565b602060405180830381600087803b1580156123bf57600080fd5b505af11580156123d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123f79190615111565b91505099509950999650505050505050565b6000808573ffffffffffffffffffffffffffffffffffffffff166323b872dd86868660405160240161243d93929190615457565b6040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161248b919061520f565b6000604051808303816000865af19150503d80600081146124c8576040519150601f19603f3d011682016040523d82523d6000602084013e6124cd565b606091505b50915091508180156124f75750805115806124f75750808060200190518101906124f7919061504f565b61252d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615c31565b505050505050565b60005b8351811015612a4c5760008060008060008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663eb22d54f7f00000000000000000000000000000000000000000000000000000000000000008d8b815181106125b557fe5b60200260200101518f8e8d815181106125ca57fe5b60200260200101516040518563ffffffff1660e01b81526004016125f19493929190615653565b60c06040518083038186803b15801561260957600080fd5b505afa15801561261d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126419190614ee5565b9550509450945094509450600061269e858e73ffffffffffffffffffffffffffffffffffffffff166370a082318f8d8151811061267a57fe5b60200260200101516040518263ffffffff1660e01b8152600401610ed99190615384565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663671a11b58287878788606403886040518763ffffffff1660e01b815260040161270696959493929190615d24565b60206040518083038186803b15801561271e57600080fd5b505afa158015612732573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127569190615111565b9750859650505050505050600086848151811061276f57fe5b602002602001015190506000808273ffffffffffffffffffffffffffffffffffffffff16630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b1580156127c257600080fd5b505afa1580156127d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127fa91906147c8565b73ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff161461283457846000612838565b6000855b600154919350915073ffffffffffffffffffffffffffffffffffffffff161561292557600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663677fdac8338c87898e8c815181106128a957fe5b60200260200101516040518663ffffffff1660e01b81526004016128d195949392919061541a565b602060405180830381600087803b1580156128eb57600080fd5b505af11580156128ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612923919061504f565b505b600060018a510387106129385787612950565b89876001018151811061294757fe5b60200260200101515b604080516000815260208101918290527f022c0d9f0000000000000000000000000000000000000000000000000000000090915290915073ffffffffffffffffffffffffffffffffffffffff85169063022c0d9f906129b89086908690869060248101615cd3565b600060405180830381600087803b1580156129d257600080fd5b505af11580156129e6573d6000803e3d6000fd5b505050507fddac40937f35385a34f721af292e5a83fc5b840f722bff57c2fc71adba708c488a8881518110612a1757fe5b60200260200101518787604051612a30939291906156f0565b60405180910390a1509298505060019093019250612538915050565b5050505050565b600081612a6257506001612b32565b612a6b8461366b565b15612b23576040517f2e1a7d4d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690632e1a7d4d90612ae290859060040161537b565b600060405180830381600087803b158015612afc57600080fd5b505af1158015612b10573d6000803e3d6000fd5b50505050612b1e838361369e565b612b2e565b612b2e848484613757565b5060015b9392505050565b6000806000612b6d89897f00000000000000000000000000000000000000000000000000000000000000008a348b8b614166565b9093509150612b7e88338b86612409565b612b88828a6134db565b6040517f6a62784200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a1690636a62784290612bda908790600401615384565b602060405180830381600087803b158015612bf457600080fd5b505af1158015612c08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c2c9190615111565b905081341115612c4257612c423383340361369e565b96509650969350505050565b6000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663e5e31b138a6040518263ffffffff1660e01b8152600401612caa9190615384565b60206040518083038186803b158015612cc257600080fd5b505afa158015612cd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cfa919061504f565b612d30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615c8e565b6040517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a16906323b872dd90612d869033908d908b90600401615457565b602060405180830381600087803b158015612da057600080fd5b505af1158015612db4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dd8919061504f565b506000808a73ffffffffffffffffffffffffffffffffffffffff166389afcb44866040518263ffffffff1660e01b8152600401612e159190615384565b6040805180830381600087803b158015612e2e57600080fd5b505af1158015612e42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e669190615129565b9150915060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663544caa568c8c6040518363ffffffff1660e01b8152600401612ec79291906153a5565b604080518083038186803b158015612ede57600080fd5b505afa158015612ef2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f1691906147e4565b5090508073ffffffffffffffffffffffffffffffffffffffff168b73ffffffffffffffffffffffffffffffffffffffff1614612f53578183612f56565b82825b909550935087851015612f95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c906159f8565b86841015612fcf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615953565b50505097509795505050505050565b6040517f30994f7100000000000000000000000000000000000000000000000000000000815260609073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906330994f7190613081907f0000000000000000000000000000000000000000000000000000000000000000908d908d908d908c908c908c908c906004016154ff565b60006040518083038186803b15801561309957600080fd5b505afa1580156130ad573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526130f39190810190614fbf565b9050858160008151811061310357fe5b60200260200101511115613143576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c9061591c565b98975050505050505050565b8360005b835181101561252d57600084828151811061316a57fe5b6020026020010151905060008173ffffffffffffffffffffffffffffffffffffffff16630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b1580156131bc57600080fd5b505afa1580156131d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131f491906147c8565b9050600087846001018151811061320757fe5b6020026020010151905060008060008473ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161461325257836000866132d3565b6000848773ffffffffffffffffffffffffffffffffffffffff1663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b15801561329b57600080fd5b505afa1580156132af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132d391906147c8565b600154929550909350915073ffffffffffffffffffffffffffffffffffffffff16156133c357600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663677fdac8338a84888f8d8151811061334757fe5b60200260200101516040518663ffffffff1660e01b815260040161336f95949392919061541a565b602060405180830381600087803b15801561338957600080fd5b505af115801561339d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133c1919061504f565b505b600060018b510388106133d657896133ee565b8a88600101815181106133e557fe5b60200260200101515b604080516000815260208101918290527f022c0d9f0000000000000000000000000000000000000000000000000000000090915290915073ffffffffffffffffffffffffffffffffffffffff88169063022c0d9f906134569087908790869060248101615cd3565b600060405180830381600087803b15801561347057600080fd5b505af1158015613484573d6000803e3d6000fd5b505050507fddac40937f35385a34f721af292e5a83fc5b840f722bff57c2fc71adba708c488786846040516134bb939291906156f0565b60405180910390a1509650506001909401935061315392505050565b3390565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0836040518263ffffffff1660e01b81526004016000604051808303818588803b15801561354357600080fd5b505af1158015613557573d6000803e3d6000fd5b50506040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb92506135d09150849086906004016156ca565b602060405180830381600087803b1580156135ea57600080fd5b505af11580156135fe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613622919061504f565b61100f57fe5b80820382811115613665576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c906157e3565b92915050565b73ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee145b919050565b6040805160008082526020820190925273ffffffffffffffffffffffffffffffffffffffff84169083906040516136d5919061520f565b60006040518083038185875af1925050503d8060008114613712576040519150601f19603f3d011682016040523d82523d6000602084013e613717565b606091505b5050905080613752576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615bd4565b505050565b6000808473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85856040516024016137899291906156ca565b6040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516137d7919061520f565b6000604051808303816000865af19150503d8060008114613814576040519150601f19603f3d011682016040523d82523d6000602084013e613819565b606091505b5091509150818015613843575080511580613843575080806020019051810190613843919061504f565b612a4c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c9061581a565b60e0811415613a80576000808573ffffffffffffffffffffffffffffffffffffffff1663d505accf60e01b85856040516020016138b8939291906151d3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526138f09161520f565b6000604051808303816000865af19150503d806000811461392d576040519150601f19603f3d011682016040523d82523d6000602084013e613932565b606091505b50915091508161252d57600061397d826040518060400160405280601481526020017f5065726d69742063616c6c206661696c65643a20000000000000000000000000815250613b5d565b9050858773ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e33306040518363ffffffff1660e01b81526004016139bb9291906153a5565b60206040518083038186803b1580156139d357600080fd5b505afa1580156139e7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a0b9190615111565b1015613a4557806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c91906157d0565b7f08c379a0afcc32b1a39302f7cb8073359698411ab5fd6e3edb2c02c0b5fba8aa81604051613a7491906157d0565b60405180910390a15050505b50505050565b6000613a918361366b565b15613ab4575073ffffffffffffffffffffffffffffffffffffffff811631613665565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190613b06908590600401615384565b60206040518083038186803b158015613b1e57600080fd5b505afa158015613b32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b569190615111565b9050613665565b60606044835110158015613bc4575082600081518110613b7957fe5b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f0800000000000000000000000000000000000000000000000000000000000000145b8015613c23575082600181518110613bd857fe5b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167fc300000000000000000000000000000000000000000000000000000000000000145b8015613c82575082600281518110613c3757fe5b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f7900000000000000000000000000000000000000000000000000000000000000145b8015613ce1575082600381518110613c9657fe5b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167fa000000000000000000000000000000000000000000000000000000000000000145b15613d57576060604484019050805160440184511015613d2d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615b40565b8281604051602001613d4092919061532f565b604051602081830303815290604052915050613665565b82516024148015613dbb575082600081518110613d7057fe5b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f4e00000000000000000000000000000000000000000000000000000000000000145b8015613e1a575082600181518110613dcf57fe5b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f4800000000000000000000000000000000000000000000000000000000000000145b8015613e79575082600281518110613e2e57fe5b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f7b00000000000000000000000000000000000000000000000000000000000000145b8015613ed8575082600381518110613e8d57fe5b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f7100000000000000000000000000000000000000000000000000000000000000145b15613efd57602483015182613eec82614472565b604051602001613d4092919061522b565b81613f0784614498565b604051602001613f189291906152ad565b604051602081830303815290604052905092915050565b80820182811015613665576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c9061598a565b6000811580613f8757505080820282828281613f8457fe5b04145b613665576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c906158e5565b6040517ff2734c3800000000000000000000000000000000000000000000000000000000815260609073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063f2734c389061405c907f0000000000000000000000000000000000000000000000000000000000000000908b908b908b908a908a906004016155c0565b60006040518083038186803b15801561407457600080fd5b505afa158015614088573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526140ce9190810190614fbf565b905083816001835103815181106140e157fe5b60200260200101511015614121576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615b77565b9695505050505050565b60008061413d89898989898989614166565b909250905061414e88338b85612409565b61415a87338b84612409565b97509795505050505050565b6000806000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663327494618c8c8c6040518463ffffffff1660e01b81526004016141c9939291906154cf565b604080518083038186803b1580156141e057600080fd5b505afa1580156141f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142189190615129565b9150915081600014801561422a575080155b1561423a57879350869250611aba565b6040517fad615dec00000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063ad615dec906142b3908c9087908790600401615d0e565b60206040518083038186803b1580156142cb57600080fd5b505afa1580156142df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143039190615111565b90508781116143515785811015614346576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615953565b889450925082612fcf565b6040517fad615dec00000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063ad615dec906143ca908c9087908990600401615d0e565b60206040518083038186803b1580156143e257600080fd5b505afa1580156143f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061441a9190615111565b90508981111561442657fe5b87811015614460576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c906159f8565b9c979b50969950505050505050505050565b606061366582604051602001614488919061537b565b6040516020818303038152906040525b80516060907f30313233343536373839616263646566000000000000000000000000000000009060009060029081020167ffffffffffffffff811180156144de57600080fd5b506040519080825280601f01601f191660200182016040528015614509576020820181803683370190505b5090507f30000000000000000000000000000000000000000000000000000000000000008160008151811061453a57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061459757fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060005b84518110156146cc578260048683815181106145e157fe5b01602001517fff0000000000000000000000000000000000000000000000000000000000000016901c60f81c6010811061461757fe5b1a60f81b82826002026002018151811061462d57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508285828151811061466957fe5b60209101015160f81c600f166010811061467f57fe5b1a60f81b82826002026003018151811061469557fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506001016145c9565b509392505050565b803561369981615e29565b60008083601f8401126146f0578182fd5b50813567ffffffffffffffff811115614707578182fd5b602083019150836020808302850101111561472157600080fd5b9250929050565b600082601f830112614738578081fd5b8135602061474d61474883615ddf565b615dbb565b8281528181019085830183850287018401881015614769578586fd5b855b8581101561478e5761477c8261479b565b8452928401929084019060010161476b565b5090979650505050505050565b803560ff8116811461369957600080fd5b6000602082840312156147bd578081fd5b8135612b3281615e29565b6000602082840312156147d9578081fd5b8151612b3281615e29565b600080604083850312156147f6578081fd5b825161480181615e29565b602084015190925061481281615e29565b809150509250929050565b600080600080600080600080610100898b031215614839578384fd5b883561484481615e29565b9750602089013561485481615e29565b9650604089013561486481615e29565b9550606089013594506080890135935060a0890135925060c089013561488981615e29565b8092505060e089013590509295985092959890939650565b6000806000806000806000806000806000806101808d8f0312156148c3578586fd5b8c356148ce81615e29565b9b5060208d01356148de81615e29565b9a5060408d01356148ee81615e29565b995060608d0135985060808d0135975060a08d0135965060c08d013561491381615e29565b955060e08d013594506101008d013561492b81615e4e565b935061493a6101208e0161479b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b60008060008060008060008060006101208a8c03121561497a578283fd5b893561498581615e29565b985060208a013561499581615e29565b975060408a01356149a581615e29565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a01356149d181615e29565b809250506101008a013590509295985092959850929598565b6000806000806000806000806000806101008b8d031215614a09578384fd5b8a35614a1481615e29565b995060208b0135614a2481615e29565b985060408b0135975060608b0135965060808b013567ffffffffffffffff80821115614a4e578586fd5b614a5a8e838f016146df565b909850965060a08d0135915080821115614a72578586fd5b50614a7f8d828e016146df565b90955093505060c08b0135614a9381615e29565b8092505060e08b013590509295989b9194979a5092959850565b600080600080600080600080610100898b031215614ac9578182fd5b614ad38935615e29565b883597506020890135614ae581615e29565b96506040890135955060608901359450608089013567ffffffffffffffff80821115614b0f578384fd5b818b0191508b601f830112614b22578384fd5b8135614b3061474882615ddf565b80828252602082019150602085018f60208086028801011115614b51578788fd5b8795505b83861015614b7e57614b678135615e29565b803583526001959095019460209283019201614b55565b509750505060a08b0135915080821115614b96578384fd5b50614ba38b828c01614728565b935050614bb260c08a016146d4565b915060e089013590509295985092959890939650565b600080600080600080600060e0888a031215614be2578081fd5b8735614bed81615e29565b96506020880135614bfd81615e29565b955060408801359450606088013593506080880135925060a0880135614c2281615e29565b8092505060c0880135905092959891949750929550565b60008060008060008060008060008060006101608c8e031215614c5a578485fd5b8b35614c6581615e29565b9a5060208c0135614c7581615e29565b995060408c0135985060608c0135975060808c0135965060a08c0135614c9a81615e29565b955060c08c0135945060e08c0135614cb181615e4e565b9350614cc06101008d0161479b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600080600080600060e0888a031215614cfc578081fd5b8735614d0781615e29565b96506020880135614d1781615e29565b955060408801359450606088013593506080880135614d3581615e5c565b925060a0880135614d4581615e5c565b915060c0880135614d5581615e29565b8091505092959891949750929550565b60008060408385031215614d77578182fd5b8235614d8281615e29565b946020939093013593505050565b60008060008060008060008060c0898b031215614dab578182fd5b8835614db681615e29565b975060208901359650604089013567ffffffffffffffff80821115614dd9578384fd5b614de58c838d016146df565b909850965060608b0135915080821115614dfd578384fd5b50614e0a8b828c016146df565b9095509350506080890135614e1e81615e29565b8092505060a089013590509295985092959890939650565b600080600080600080600080600060e08a8c031215614e53578283fd5b8935614e5e81615e29565b985060208a0135975060408a0135965060608a013567ffffffffffffffff80821115614e88578485fd5b614e948d838e016146df565b909850965060808c0135915080821115614eac578485fd5b50614eb98c828d016146df565b90955093505060a08a0135614ecd81615e29565b8092505060c08a013590509295985092959850929598565b60008060008060008060c08789031215614efd578384fd5b8651614f0881615e29565b8096505060208701519450604087015193506060870151614f2881615e5c565b6080880151909350614f3981615e5c565b60a0880151909250614f4a81615e5c565b809150509295509295509295565b600080600080600060a08688031215614f6f578283fd5b8535614f7a81615e29565b9450602086013593506040860135614f9181615e5c565b92506060860135614fa181615e5c565b91506080860135614fb181615e29565b809150509295509295909350565b60006020808385031215614fd1578182fd5b825167ffffffffffffffff811115614fe7578283fd5b8301601f81018513614ff7578283fd5b805161500561474882615ddf565b8181528381019083850185840285018601891015615021578687fd5b8694505b83851015615043578051835260019490940193918501918501615025565b50979650505050505050565b600060208284031215615060578081fd5b8151612b3281615e4e565b60008060008060608587031215615080578182fd5b843561508b81615e29565b9350602085013567ffffffffffffffff808211156150a7578384fd5b9086019061010082890312156150bb578384fd5b909350604086013590808211156150d0578384fd5b818701915087601f8301126150e3578384fd5b8135818111156150f1578485fd5b886020828501011115615102578485fd5b95989497505060200194505050565b600060208284031215615122578081fd5b5051919050565b6000806040838503121561513b578182fd5b505080516020909101519092909150565b6000815180845260208085019450808401835b8381101561517e57815160ff168752958201959082019060010161515f565b509495945050505050565b600081518084526151a1816020860160208601615dfd565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60007fffffffff000000000000000000000000000000000000000000000000000000008516825282846004840137910160040190815292915050565b60008251615221818460208701615dfd565b9190910192915050565b6000835161523d818460208801615dfd565b7f50616e69632800000000000000000000000000000000000000000000000000009083019081528351615277816006840160208801615dfd565b7f290000000000000000000000000000000000000000000000000000000000000060069290910191820152600701949350505050565b600083516152bf818460208801615dfd565b7f556e6b6e6f776e2800000000000000000000000000000000000000000000000090830190815283516152f9816008840160208801615dfd565b7f290000000000000000000000000000000000000000000000000000000000000060089290910191820152600901949350505050565b60008351615341818460208801615dfd565b7f4572726f722800000000000000000000000000000000000000000000000000009083019081528351615277816006840160208801615dfd565b90815260200190565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff92831681529116602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff97881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b73ffffffffffffffffffffffffffffffffffffffff9586168152938516602085015291841660408401526060830152909116608082015260a00190565b73ffffffffffffffffffffffffffffffffffffffff9384168152919092166020820152604081019190915260600190565b73ffffffffffffffffffffffffffffffffffffffff96871681529486166020860152928516604085015293166060830152608082019290925260a081019190915260c00190565b73ffffffffffffffffffffffffffffffffffffffff93841681529183166020830152909116604082015260600190565b600060c0820173ffffffffffffffffffffffffffffffffffffffff808c1684526020818c1681860152818b16604086015289606086015260c060808601528288845260e086019050899350845b8981101561557357843561555f81615e29565b84168252938201939082019060010161554c565b5085810360a087015286815281019250869150835b868110156155ae5760ff61559b8461479b565b1684529281019291810191600101615588565b50919c9b505050505050505050505050565b600060c0820173ffffffffffffffffffffffffffffffffffffffff808a1684526020818a1681860152818916604086015287606086015260c0608086015282875180855260e0870191508289019450855b8181101561562f578551851683529483019491830191600101615611565b505085810360a0870152615643818861514c565b9c9b505050505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff948516815292841660208401529216604082015260ff909116606082015260800190565b73ffffffffffffffffffffffffffffffffffffffff948516815292909316602083015263ffffffff9081166040830152909116606082015260800190565b73ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff93841681526020810192909252909116604082015260600190565b6020808252825182820181905260009190848201906040850190845b818110156157585783518352928401929184019160010161573c565b50909695505050505050565b60006040825283604083015283856060840137806060858401015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f860116830101905073ffffffffffffffffffffffffffffffffffffffff83166020830152949350505050565b600060208252612b326020830184615189565b60208082526015908201527f64732d6d6174682d7375622d756e646572666c6f770000000000000000000000604082015260600190565b6020808252601f908201527f5472616e7366657248656c7065723a205452414e534645525f4641494c454400604082015260600190565b60208082526012908201527f436c61696d20746f6b656e206973204554480000000000000000000000000000604082015260600190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201527f6464726573730000000000000000000000000000000000000000000000000000606082015260800190565b60208082526014908201527f64732d6d6174682d6d756c2d6f766572666c6f77000000000000000000000000604082015260600190565b6020808252601e908201527f526f757465723a204558434553534956455f494e5055545f414d4f554e540000604082015260600190565b6020808252601d908201527f526f757465723a20494e53554646494349454e545f425f414d4f554e54000000604082015260600190565b60208082526014908201527f64732d6d6174682d6164642d6f766572666c6f77000000000000000000000000604082015260600190565b60208082526011908201527f496e76616c6964206d73672e76616c7565000000000000000000000000000000604082015260600190565b6020808252601d908201527f526f757465723a20494e53554646494349454e545f415f414d4f554e54000000604082015260600190565b6020808252601b908201527f52657475726e20616d6f756e74206973206e6f7420656e6f7567680000000000604082015260600190565b6020808252601a908201527f4d696e2072657475726e2073686f756c64206e6f742062652030000000000000604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252600f908201527f526f757465723a20455850495245440000000000000000000000000000000000604082015260600190565b60208082526017908201527f646174612073686f756c64206265206e6f74207a65726f000000000000000000604082015260600190565b60208082526015908201527f496e76616c69642072657665727420726561736f6e0000000000000000000000604082015260600190565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f5560408201527f4e54000000000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526023908201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960408201527f4c45440000000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526024908201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f464160408201527f494c454400000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526014908201527f526f757465723a20496e76616c69642070616972000000000000000000000000604082015260600190565b918252602082015260400190565b600085825284602083015273ffffffffffffffffffffffffffffffffffffffff84166040830152608060608301526141216080830184615189565b9283526020830191909152604082015260600190565b9586526020860194909452604085019290925263ffffffff908116606085015290811660808401521660a082015260c00190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112615d8c578283fd5b83018035915067ffffffffffffffff821115615da6578283fd5b60200191503681900382131561472157600080fd5b60405181810167ffffffffffffffff81118282101715615dd757fe5b604052919050565b600067ffffffffffffffff821115615df357fe5b5060209081020190565b60005b83811015615e18578181015183820152602001615e00565b83811115613a805750506000910152565b73ffffffffffffffffffffffffffffffffffffffff81168114615e4b57600080fd5b50565b8015158114615e4b57600080fd5b63ffffffff81168114615e4b57600080fdfea26469706673582212206728b2f1db4aa975ef23a242ae450725b894889710785d22b62abebb050e348964736f6c63430007060033000000000000000000000000c7a50fe12c864963ea5a5e0858a0e7abe5b875c4000000000000000000000000ba926938022aed393436635fed939cadf5afe4d5000000000000000000000000b7ddc6414bf4f5515b52d8bdd69973ae205ff101

Deployed ByteCode

0x6080604052600436106101c65760003560e01c8063991bffc7116100f7578063d0f2c82a11610095578063f0c62e2b11610064578063f0c62e2b146104fb578063f2fde38b1461050e578063fbbeedf11461052e578063fbf451351461054e5761020c565b8063d0f2c82a1461047b578063dc9f70291461049b578063e1f4a784146104bb578063ebb5d2e9146104db5761020c565b8063ad5c4648116100d1578063ad5c464814610411578063af7e6aec14610426578063b56b681d14610446578063c45a0155146104665761020c565b8063991bffc7146103c9578063a3ddb30b146103dc578063a4aabb08146103f15761020c565b8063715018a6116101645780637a286fa21161013e5780637a286fa2146103615780637c0252001461038157806389df37af146103945780638da5cb5b146103b45761020c565b8063715018a614610319578063752ebb7c1461032e57806378e3214f146103415761020c565b80634b75f54f116101a05780634b75f54f146102895780634c17fd7c146102ab578063674f19f8146102d95780636cb49428146103065761020c565b80630e2f024c14610211578063242e3b9f146102475780633990ba54146102675761020c565b3661020c573373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000b7ddc6414bf4f5515b52d8bdd69973ae205ff101161461020a57fe5b005b600080fd5b34801561021d57600080fd5b5061023161022c366004614c39565b61056e565b60405161023e919061537b565b60405180910390f35b34801561025357600080fd5b5061020a610262366004614e36565b610651565b61027a610275366004614bc8565b610860565b60405161023e93929190615d0e565b34801561029557600080fd5b5061029e6108c2565b60405161023e9190615384565b3480156102b757600080fd5b506102cb6102c63660046148a1565b6108e6565b60405161023e929190615cc5565b3480156102e557600080fd5b506102f96102f4366004614e36565b6109f6565b60405161023e9190615720565b610231610314366004614f58565b610b2b565b34801561032557600080fd5b5061020a610c1d565b61020a61033c366004614d90565b610cff565b34801561034d57600080fd5b5061020a61035c366004614d65565b610f74565b34801561036d57600080fd5b506102f961037c3660046149ea565b611013565b61023161038f36600461506b565b6110c3565b3480156103a057600080fd5b506102f96103af366004614aad565b611607565b3480156103c057600080fd5b5061029e611694565b6102f96103d7366004614d90565b6116b0565b3480156103e857600080fd5b5061029e611816565b3480156103fd57600080fd5b506102cb61040c366004614c39565b611832565b34801561041d57600080fd5b5061029e61191b565b34801561043257600080fd5b506102f9610441366004614e36565b61193f565b34801561045257600080fd5b506102cb610461366004614bc8565b611a1e565b34801561047257600080fd5b5061029e611ac8565b34801561048757600080fd5b50610231610496366004614ce2565b611aec565b3480156104a757600080fd5b5061020a6104b63660046149ea565b611c58565b3480156104c757600080fd5b506102cb6104d636600461481d565b611e32565b3480156104e757600080fd5b506102316104f6366004614bc8565b611e91565b6102f9610509366004614d90565b611fdd565b34801561051a57600080fd5b5061020a6105293660046147ac565b6120f8565b34801561053a57600080fd5b5061020a6105493660046147ac565b612245565b34801561055a57600080fd5b5061027a61056936600461495c565b6122ff565b6000808561057c578a61059e565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b6040517fd505accf00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff8e169063d505accf906105ff903390309086908d908c908c908c906004016153cc565b600060405180830381600087803b15801561061957600080fd5b505af115801561062d573d6000803e3d6000fd5b505050506106408d8d8d8d8d8d8d611e91565b9d9c50505050505050505050505050565b8042811015610695576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615ad2565b60405180910390fd5b6106c28a33898960008181106106a757fe5b90506020020160208101906106bc91906147ac565b8c612409565b6107328a88888080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808c0282810182019093528b82529093508b92508a918291850190849080828437600092019190915250309250612535915050565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000b7ddc6414bf4f5515b52d8bdd69973ae205ff10116906370a08231906107a7903090600401615384565b60206040518083038186803b1580156107bf57600080fd5b505afa1580156107d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107f79190615111565b905088811015610833576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615b77565b61085273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8583612a53565b505050505050505050505050565b600080600083428110156108a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615ad2565b6108ae8b8b8b8b8b8b612b39565b919d909c50909a5098505050505050505050565b7f000000000000000000000000ba926938022aed393436635fed939cadf5afe4d581565b6000808642811015610924576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615ad2565b600087610931578c610953565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b90508f73ffffffffffffffffffffffffffffffffffffffff1663d505accf3330848d8c8c8c6040518863ffffffff1660e01b815260040161099a97969594939291906153cc565b600060405180830381600087803b1580156109b457600080fd5b505af11580156109c8573d6000803e3d6000fd5b50505050506109dc8f8f8f8f8f8f8f612c4e565b8093508194505050509c509c9a5050505050505050505050565b60608142811015610a33576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615ad2565b610a638b7f000000000000000000000000b7ddc6414bf4f5515b52d8bdd69973ae205ff1018c8c8c8c8c8c612fde565b9150610aa68b338a8a6000818110610a7757fe5b9050602002016020810190610a8c91906147ac565b85600081518110610a9957fe5b6020026020010151612409565b610ae68b838a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525030925061314f915050565b610b1c73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8584600186510381518110610b0f57fe5b6020026020010151612a53565b50509998505050505050505050565b6000807f000000000000000000000000c7a50fe12c864963ea5a5e0858a0e7abe5b875c473ffffffffffffffffffffffffffffffffffffffff166314572adb887f000000000000000000000000b7ddc6414bf4f5515b52d8bdd69973ae205ff10188886040518563ffffffff1660e01b8152600401610bad949392919061568c565b602060405180830381600087803b158015610bc757600080fd5b505af1158015610bdb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bff91906147c8565b9050610c1081888860008088612b39565b9998505050505050505050565b610c256134d7565b73ffffffffffffffffffffffffffffffffffffffff16610c43611694565b73ffffffffffffffffffffffffffffffffffffffff1614610c90576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615a9d565b6000805460405173ffffffffffffffffffffffffffffffffffffffff909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b8042811015610d3a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615ad2565b34610d64818989600081610d4a57fe5b9050602002016020810190610d5f91906147ac565b6134db565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff8c16906370a0823190610db9908890600401615384565b60206040518083038186803b158015610dd157600080fd5b505afa158015610de5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e099190615111565b9050610e9b7f000000000000000000000000b7ddc6414bf4f5515b52d8bdd69973ae205ff1018a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250612535915050565b89610f2f828d73ffffffffffffffffffffffffffffffffffffffff166370a08231896040518263ffffffff1660e01b8152600401610ed99190615384565b60206040518083038186803b158015610ef157600080fd5b505afa158015610f05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f299190615111565b90613628565b1015610f67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615b77565b5050505050505050505050565b610f7c6134d7565b73ffffffffffffffffffffffffffffffffffffffff16610f9a611694565b73ffffffffffffffffffffffffffffffffffffffff1614610fe7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615a9d565b610ff08261366b565b1561100457610fff338261369e565b61100f565b61100f823383613757565b5050565b60608142811015611050576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615ad2565b6110608c8c8c8c8c8c8c8c612fde565b91506110748c338a8a6000818110610a7757fe5b6110b48c838a8a808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508a925061314f915050565b509a9950505050505050505050565b6000808460a0013511611102576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615a66565b81611139576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615b09565b60c08401356080850135600061115260208801886147ac565b905060006111666040890160208a016147ac565b905060028416156111c45761117a8261366b565b611185576000611187565b825b34116111bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c906159c1565b611212565b6111cd8261366b565b6111d85760006111da565b825b3414611212576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c906159c1565b600484161561128d576112248261366b565b1561125b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615851565b611272828461126d60e08c018c615d58565b613879565b61128d823361128760608c0160408d016147ac565b86612409565b6000806112a060808b0160608c016147ac565b73ffffffffffffffffffffffffffffffffffffffff16146112d0576112cb60808a0160608b016147ac565b6112d2565b335b90506000600186166112e55760006112ef565b6112ef8433613a86565b905060006112fd8484613a86565b90506000808d73ffffffffffffffffffffffffffffffffffffffff1634635697e45360e01b8e8e3360405160240161133793929190615764565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516113c0919061520f565b60006040518083038185875af1925050503d80600081146113fd576040519150601f19603f3d011682016040523d82523d6000602084013e611402565b606091505b50915091508161147e5761144b816040518060400160405280601281526020017f63616c6c4279746573206661696c65643a200000000000000000000000000000815250613b5d565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c91906157d0565b5086905061149082610f298787613a86565b98506001881615611509576114b26114a88733613a86565b610f29858a613f2f565b90506114c260a08d013582613f6c565b6114cc8a89613f6c565b1015611504576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615a2f565b611547565b8b60a00135891015611547576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615a2f565b7fd6d4f5681c246c9f42c203e287975af1601f8df8035a9251f79aab5c8f09e2f833878787858e60405161158096959493929190615488565b60405180910390a17fddac40937f35385a34f721af292e5a83fc5b840f722bff57c2fc71adba708c488d8a6115b48861366b565b6115be57876115e0565b7f000000000000000000000000b7ddc6414bf4f5515b52d8bdd69973ae205ff1015b6040516115ef939291906156f0565b60405180910390a15050505050505050949350505050565b60608142811015611644576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615ad2565b6116528a8a8a8a8a8a613fbd565b915061167b8a338860008151811061166657fe5b602002602001015185600081518110610a9957fe5b6116878a83888761314f565b5098975050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1690565b606081428110156116ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615ad2565b61178f7f000000000000000000000000b7ddc6414bf4f5515b52d8bdd69973ae205ff1018b348c8c8c80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508b8b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250613fbd92505050565b91506117b6826000815181106117a157fe5b602002602001015189896000818110610d4a57fe5b6116877f000000000000000000000000b7ddc6414bf4f5515b52d8bdd69973ae205ff101838a8a808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508a925061314f915050565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b600080600086611842578b611864565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b6040517fd505accf00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff8f169063d505accf906118c5903390309086908e908d908d908d906004016153cc565b600060405180830381600087803b1580156118df57600080fd5b505af11580156118f3573d6000803e3d6000fd5b505050506119068e8e8e8e8e8e8e611a1e565b909f909e509c50505050505050505050505050565b7f000000000000000000000000b7ddc6414bf4f5515b52d8bdd69973ae205ff10181565b6060814281101561197c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615ad2565b610a638b7f000000000000000000000000b7ddc6414bf4f5515b52d8bdd69973ae205ff1018c8c8c8c80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508b8b80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250613fbd92505050565b6000808242811015611a5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615ad2565b611a8b8a8a7f000000000000000000000000b7ddc6414bf4f5515b52d8bdd69973ae205ff1018b8b8b30612c4e565b9093509150611a9b898685613757565b611aba73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8684612a53565b505097509795505050505050565b7f000000000000000000000000c7a50fe12c864963ea5a5e0858a0e7abe5b875c481565b6000807f000000000000000000000000c7a50fe12c864963ea5a5e0858a0e7abe5b875c473ffffffffffffffffffffffffffffffffffffffff166314572adb8a8a88886040518563ffffffff1660e01b8152600401611b4e949392919061568c565b602060405180830381600087803b158015611b6857600080fd5b505af1158015611b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba091906147c8565b9050611bb2818a8a8a8a60008061412b565b50506040517f6a62784200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821690636a62784290611c06908690600401615384565b602060405180830381600087803b158015611c2057600080fd5b505af1158015611c34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c109190615111565b8042811015611c93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615ad2565b611ca58b33898960008181106106a757fe5b6040517f70a0823100000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff8c16906370a0823190611cfa908790600401615384565b60206040518083038186803b158015611d1257600080fd5b505afa158015611d26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d4a9190615111565b9050611dbc8c89898080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808d0282810182019093528c82529093508c92508b9182918501908490808284376000920191909152508a9250612535915050565b88611dfa828d73ffffffffffffffffffffffffffffffffffffffff166370a08231886040518263ffffffff1660e01b8152600401610ed99190615384565b1015610852576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615b77565b6000808242811015611e70576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615ad2565b611e7f8b8b8b8b8b8b8b612c4e565b909c909b509950505050505050505050565b60008142811015611ece576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615ad2565b611efe89897f000000000000000000000000b7ddc6414bf4f5515b52d8bdd69973ae205ff1018a8a8a308a611e32565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152909350611fb191508990869073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190611f5c903090600401615384565b60206040518083038186803b158015611f7457600080fd5b505afa158015611f88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fac9190615111565b613757565b611fd073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8584612a53565b5050979650505050505050565b6060814281101561201a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615ad2565b61204a7f000000000000000000000000b7ddc6414bf4f5515b52d8bdd69973ae205ff1018b8b348c8c8c8c612fde565b915061205c826000815181106117a157fe5b6120bc7f000000000000000000000000b7ddc6414bf4f5515b52d8bdd69973ae205ff101838a8a808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508a925061314f915050565b816000815181106120c957fe5b60200260200101513411156116875761168733836000815181106120e957fe5b6020026020010151340361369e565b6121006134d7565b73ffffffffffffffffffffffffffffffffffffffff1661211e611694565b73ffffffffffffffffffffffffffffffffffffffff161461216b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615a9d565b73ffffffffffffffffffffffffffffffffffffffff81166121b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615888565b6000805460405173ffffffffffffffffffffffffffffffffffffffff808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b61224d6134d7565b73ffffffffffffffffffffffffffffffffffffffff1661226b611694565b73ffffffffffffffffffffffffffffffffffffffff16146122b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615a9d565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6000806000834281101561233f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615ad2565b61234e8d8d8d8d8d8d8d61412b565b6040517f6a627842000000000000000000000000000000000000000000000000000000008152919550935073ffffffffffffffffffffffffffffffffffffffff8e1690636a627842906123a5908990600401615384565b602060405180830381600087803b1580156123bf57600080fd5b505af11580156123d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123f79190615111565b91505099509950999650505050505050565b6000808573ffffffffffffffffffffffffffffffffffffffff166323b872dd86868660405160240161243d93929190615457565b6040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161248b919061520f565b6000604051808303816000865af19150503d80600081146124c8576040519150601f19603f3d011682016040523d82523d6000602084013e6124cd565b606091505b50915091508180156124f75750805115806124f75750808060200190518101906124f7919061504f565b61252d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615c31565b505050505050565b60005b8351811015612a4c5760008060008060008060007f000000000000000000000000ba926938022aed393436635fed939cadf5afe4d573ffffffffffffffffffffffffffffffffffffffff1663eb22d54f7f000000000000000000000000c7a50fe12c864963ea5a5e0858a0e7abe5b875c48d8b815181106125b557fe5b60200260200101518f8e8d815181106125ca57fe5b60200260200101516040518563ffffffff1660e01b81526004016125f19493929190615653565b60c06040518083038186803b15801561260957600080fd5b505afa15801561261d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126419190614ee5565b9550509450945094509450600061269e858e73ffffffffffffffffffffffffffffffffffffffff166370a082318f8d8151811061267a57fe5b60200260200101516040518263ffffffff1660e01b8152600401610ed99190615384565b90507f000000000000000000000000ba926938022aed393436635fed939cadf5afe4d573ffffffffffffffffffffffffffffffffffffffff1663671a11b58287878788606403886040518763ffffffff1660e01b815260040161270696959493929190615d24565b60206040518083038186803b15801561271e57600080fd5b505afa158015612732573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127569190615111565b9750859650505050505050600086848151811061276f57fe5b602002602001015190506000808273ffffffffffffffffffffffffffffffffffffffff16630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b1580156127c257600080fd5b505afa1580156127d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127fa91906147c8565b73ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff161461283457846000612838565b6000855b600154919350915073ffffffffffffffffffffffffffffffffffffffff161561292557600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663677fdac8338c87898e8c815181106128a957fe5b60200260200101516040518663ffffffff1660e01b81526004016128d195949392919061541a565b602060405180830381600087803b1580156128eb57600080fd5b505af11580156128ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612923919061504f565b505b600060018a510387106129385787612950565b89876001018151811061294757fe5b60200260200101515b604080516000815260208101918290527f022c0d9f0000000000000000000000000000000000000000000000000000000090915290915073ffffffffffffffffffffffffffffffffffffffff85169063022c0d9f906129b89086908690869060248101615cd3565b600060405180830381600087803b1580156129d257600080fd5b505af11580156129e6573d6000803e3d6000fd5b505050507fddac40937f35385a34f721af292e5a83fc5b840f722bff57c2fc71adba708c488a8881518110612a1757fe5b60200260200101518787604051612a30939291906156f0565b60405180910390a1509298505060019093019250612538915050565b5050505050565b600081612a6257506001612b32565b612a6b8461366b565b15612b23576040517f2e1a7d4d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000b7ddc6414bf4f5515b52d8bdd69973ae205ff1011690632e1a7d4d90612ae290859060040161537b565b600060405180830381600087803b158015612afc57600080fd5b505af1158015612b10573d6000803e3d6000fd5b50505050612b1e838361369e565b612b2e565b612b2e848484613757565b5060015b9392505050565b6000806000612b6d89897f000000000000000000000000b7ddc6414bf4f5515b52d8bdd69973ae205ff1018a348b8b614166565b9093509150612b7e88338b86612409565b612b88828a6134db565b6040517f6a62784200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a1690636a62784290612bda908790600401615384565b602060405180830381600087803b158015612bf457600080fd5b505af1158015612c08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c2c9190615111565b905081341115612c4257612c423383340361369e565b96509650969350505050565b6000807f000000000000000000000000c7a50fe12c864963ea5a5e0858a0e7abe5b875c473ffffffffffffffffffffffffffffffffffffffff1663e5e31b138a6040518263ffffffff1660e01b8152600401612caa9190615384565b60206040518083038186803b158015612cc257600080fd5b505afa158015612cd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cfa919061504f565b612d30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615c8e565b6040517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a16906323b872dd90612d869033908d908b90600401615457565b602060405180830381600087803b158015612da057600080fd5b505af1158015612db4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dd8919061504f565b506000808a73ffffffffffffffffffffffffffffffffffffffff166389afcb44866040518263ffffffff1660e01b8152600401612e159190615384565b6040805180830381600087803b158015612e2e57600080fd5b505af1158015612e42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e669190615129565b9150915060007f000000000000000000000000ba926938022aed393436635fed939cadf5afe4d573ffffffffffffffffffffffffffffffffffffffff1663544caa568c8c6040518363ffffffff1660e01b8152600401612ec79291906153a5565b604080518083038186803b158015612ede57600080fd5b505afa158015612ef2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f1691906147e4565b5090508073ffffffffffffffffffffffffffffffffffffffff168b73ffffffffffffffffffffffffffffffffffffffff1614612f53578183612f56565b82825b909550935087851015612f95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c906159f8565b86841015612fcf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615953565b50505097509795505050505050565b6040517f30994f7100000000000000000000000000000000000000000000000000000000815260609073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba926938022aed393436635fed939cadf5afe4d516906330994f7190613081907f000000000000000000000000c7a50fe12c864963ea5a5e0858a0e7abe5b875c4908d908d908d908c908c908c908c906004016154ff565b60006040518083038186803b15801561309957600080fd5b505afa1580156130ad573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526130f39190810190614fbf565b9050858160008151811061310357fe5b60200260200101511115613143576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c9061591c565b98975050505050505050565b8360005b835181101561252d57600084828151811061316a57fe5b6020026020010151905060008173ffffffffffffffffffffffffffffffffffffffff16630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b1580156131bc57600080fd5b505afa1580156131d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131f491906147c8565b9050600087846001018151811061320757fe5b6020026020010151905060008060008473ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161461325257836000866132d3565b6000848773ffffffffffffffffffffffffffffffffffffffff1663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b15801561329b57600080fd5b505afa1580156132af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132d391906147c8565b600154929550909350915073ffffffffffffffffffffffffffffffffffffffff16156133c357600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663677fdac8338a84888f8d8151811061334757fe5b60200260200101516040518663ffffffff1660e01b815260040161336f95949392919061541a565b602060405180830381600087803b15801561338957600080fd5b505af115801561339d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133c1919061504f565b505b600060018b510388106133d657896133ee565b8a88600101815181106133e557fe5b60200260200101515b604080516000815260208101918290527f022c0d9f0000000000000000000000000000000000000000000000000000000090915290915073ffffffffffffffffffffffffffffffffffffffff88169063022c0d9f906134569087908790869060248101615cd3565b600060405180830381600087803b15801561347057600080fd5b505af1158015613484573d6000803e3d6000fd5b505050507fddac40937f35385a34f721af292e5a83fc5b840f722bff57c2fc71adba708c488786846040516134bb939291906156f0565b60405180910390a1509650506001909401935061315392505050565b3390565b7f000000000000000000000000b7ddc6414bf4f5515b52d8bdd69973ae205ff10173ffffffffffffffffffffffffffffffffffffffff1663d0e30db0836040518263ffffffff1660e01b81526004016000604051808303818588803b15801561354357600080fd5b505af1158015613557573d6000803e3d6000fd5b50506040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000b7ddc6414bf4f5515b52d8bdd69973ae205ff10116935063a9059cbb92506135d09150849086906004016156ca565b602060405180830381600087803b1580156135ea57600080fd5b505af11580156135fe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613622919061504f565b61100f57fe5b80820382811115613665576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c906157e3565b92915050565b73ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee145b919050565b6040805160008082526020820190925273ffffffffffffffffffffffffffffffffffffffff84169083906040516136d5919061520f565b60006040518083038185875af1925050503d8060008114613712576040519150601f19603f3d011682016040523d82523d6000602084013e613717565b606091505b5050905080613752576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615bd4565b505050565b6000808473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85856040516024016137899291906156ca565b6040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516137d7919061520f565b6000604051808303816000865af19150503d8060008114613814576040519150601f19603f3d011682016040523d82523d6000602084013e613819565b606091505b5091509150818015613843575080511580613843575080806020019051810190613843919061504f565b612a4c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c9061581a565b60e0811415613a80576000808573ffffffffffffffffffffffffffffffffffffffff1663d505accf60e01b85856040516020016138b8939291906151d3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526138f09161520f565b6000604051808303816000865af19150503d806000811461392d576040519150601f19603f3d011682016040523d82523d6000602084013e613932565b606091505b50915091508161252d57600061397d826040518060400160405280601481526020017f5065726d69742063616c6c206661696c65643a20000000000000000000000000815250613b5d565b9050858773ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e33306040518363ffffffff1660e01b81526004016139bb9291906153a5565b60206040518083038186803b1580156139d357600080fd5b505afa1580156139e7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a0b9190615111565b1015613a4557806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c91906157d0565b7f08c379a0afcc32b1a39302f7cb8073359698411ab5fd6e3edb2c02c0b5fba8aa81604051613a7491906157d0565b60405180910390a15050505b50505050565b6000613a918361366b565b15613ab4575073ffffffffffffffffffffffffffffffffffffffff811631613665565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190613b06908590600401615384565b60206040518083038186803b158015613b1e57600080fd5b505afa158015613b32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b569190615111565b9050613665565b60606044835110158015613bc4575082600081518110613b7957fe5b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f0800000000000000000000000000000000000000000000000000000000000000145b8015613c23575082600181518110613bd857fe5b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167fc300000000000000000000000000000000000000000000000000000000000000145b8015613c82575082600281518110613c3757fe5b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f7900000000000000000000000000000000000000000000000000000000000000145b8015613ce1575082600381518110613c9657fe5b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167fa000000000000000000000000000000000000000000000000000000000000000145b15613d57576060604484019050805160440184511015613d2d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615b40565b8281604051602001613d4092919061532f565b604051602081830303815290604052915050613665565b82516024148015613dbb575082600081518110613d7057fe5b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f4e00000000000000000000000000000000000000000000000000000000000000145b8015613e1a575082600181518110613dcf57fe5b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f4800000000000000000000000000000000000000000000000000000000000000145b8015613e79575082600281518110613e2e57fe5b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f7b00000000000000000000000000000000000000000000000000000000000000145b8015613ed8575082600381518110613e8d57fe5b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f7100000000000000000000000000000000000000000000000000000000000000145b15613efd57602483015182613eec82614472565b604051602001613d4092919061522b565b81613f0784614498565b604051602001613f189291906152ad565b604051602081830303815290604052905092915050565b80820182811015613665576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c9061598a565b6000811580613f8757505080820282828281613f8457fe5b04145b613665576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c906158e5565b6040517ff2734c3800000000000000000000000000000000000000000000000000000000815260609073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba926938022aed393436635fed939cadf5afe4d5169063f2734c389061405c907f000000000000000000000000c7a50fe12c864963ea5a5e0858a0e7abe5b875c4908b908b908b908a908a906004016155c0565b60006040518083038186803b15801561407457600080fd5b505afa158015614088573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526140ce9190810190614fbf565b905083816001835103815181106140e157fe5b60200260200101511015614121576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615b77565b9695505050505050565b60008061413d89898989898989614166565b909250905061414e88338b85612409565b61415a87338b84612409565b97509795505050505050565b6000806000807f000000000000000000000000ba926938022aed393436635fed939cadf5afe4d573ffffffffffffffffffffffffffffffffffffffff1663327494618c8c8c6040518463ffffffff1660e01b81526004016141c9939291906154cf565b604080518083038186803b1580156141e057600080fd5b505afa1580156141f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142189190615129565b9150915081600014801561422a575080155b1561423a57879350869250611aba565b6040517fad615dec00000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba926938022aed393436635fed939cadf5afe4d5169063ad615dec906142b3908c9087908790600401615d0e565b60206040518083038186803b1580156142cb57600080fd5b505afa1580156142df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143039190615111565b90508781116143515785811015614346576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90615953565b889450925082612fcf565b6040517fad615dec00000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba926938022aed393436635fed939cadf5afe4d5169063ad615dec906143ca908c9087908990600401615d0e565b60206040518083038186803b1580156143e257600080fd5b505afa1580156143f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061441a9190615111565b90508981111561442657fe5b87811015614460576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c906159f8565b9c979b50969950505050505050505050565b606061366582604051602001614488919061537b565b6040516020818303038152906040525b80516060907f30313233343536373839616263646566000000000000000000000000000000009060009060029081020167ffffffffffffffff811180156144de57600080fd5b506040519080825280601f01601f191660200182016040528015614509576020820181803683370190505b5090507f30000000000000000000000000000000000000000000000000000000000000008160008151811061453a57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061459757fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060005b84518110156146cc578260048683815181106145e157fe5b01602001517fff0000000000000000000000000000000000000000000000000000000000000016901c60f81c6010811061461757fe5b1a60f81b82826002026002018151811061462d57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508285828151811061466957fe5b60209101015160f81c600f166010811061467f57fe5b1a60f81b82826002026003018151811061469557fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506001016145c9565b509392505050565b803561369981615e29565b60008083601f8401126146f0578182fd5b50813567ffffffffffffffff811115614707578182fd5b602083019150836020808302850101111561472157600080fd5b9250929050565b600082601f830112614738578081fd5b8135602061474d61474883615ddf565b615dbb565b8281528181019085830183850287018401881015614769578586fd5b855b8581101561478e5761477c8261479b565b8452928401929084019060010161476b565b5090979650505050505050565b803560ff8116811461369957600080fd5b6000602082840312156147bd578081fd5b8135612b3281615e29565b6000602082840312156147d9578081fd5b8151612b3281615e29565b600080604083850312156147f6578081fd5b825161480181615e29565b602084015190925061481281615e29565b809150509250929050565b600080600080600080600080610100898b031215614839578384fd5b883561484481615e29565b9750602089013561485481615e29565b9650604089013561486481615e29565b9550606089013594506080890135935060a0890135925060c089013561488981615e29565b8092505060e089013590509295985092959890939650565b6000806000806000806000806000806000806101808d8f0312156148c3578586fd5b8c356148ce81615e29565b9b5060208d01356148de81615e29565b9a5060408d01356148ee81615e29565b995060608d0135985060808d0135975060a08d0135965060c08d013561491381615e29565b955060e08d013594506101008d013561492b81615e4e565b935061493a6101208e0161479b565b92506101408d013591506101608d013590509295989b509295989b509295989b565b60008060008060008060008060006101208a8c03121561497a578283fd5b893561498581615e29565b985060208a013561499581615e29565b975060408a01356149a581615e29565b965060608a0135955060808a0135945060a08a0135935060c08a0135925060e08a01356149d181615e29565b809250506101008a013590509295985092959850929598565b6000806000806000806000806000806101008b8d031215614a09578384fd5b8a35614a1481615e29565b995060208b0135614a2481615e29565b985060408b0135975060608b0135965060808b013567ffffffffffffffff80821115614a4e578586fd5b614a5a8e838f016146df565b909850965060a08d0135915080821115614a72578586fd5b50614a7f8d828e016146df565b90955093505060c08b0135614a9381615e29565b8092505060e08b013590509295989b9194979a5092959850565b600080600080600080600080610100898b031215614ac9578182fd5b614ad38935615e29565b883597506020890135614ae581615e29565b96506040890135955060608901359450608089013567ffffffffffffffff80821115614b0f578384fd5b818b0191508b601f830112614b22578384fd5b8135614b3061474882615ddf565b80828252602082019150602085018f60208086028801011115614b51578788fd5b8795505b83861015614b7e57614b678135615e29565b803583526001959095019460209283019201614b55565b509750505060a08b0135915080821115614b96578384fd5b50614ba38b828c01614728565b935050614bb260c08a016146d4565b915060e089013590509295985092959890939650565b600080600080600080600060e0888a031215614be2578081fd5b8735614bed81615e29565b96506020880135614bfd81615e29565b955060408801359450606088013593506080880135925060a0880135614c2281615e29565b8092505060c0880135905092959891949750929550565b60008060008060008060008060008060006101608c8e031215614c5a578485fd5b8b35614c6581615e29565b9a5060208c0135614c7581615e29565b995060408c0135985060608c0135975060808c0135965060a08c0135614c9a81615e29565b955060c08c0135945060e08c0135614cb181615e4e565b9350614cc06101008d0161479b565b92506101208c013591506101408c013590509295989b509295989b9093969950565b600080600080600080600060e0888a031215614cfc578081fd5b8735614d0781615e29565b96506020880135614d1781615e29565b955060408801359450606088013593506080880135614d3581615e5c565b925060a0880135614d4581615e5c565b915060c0880135614d5581615e29565b8091505092959891949750929550565b60008060408385031215614d77578182fd5b8235614d8281615e29565b946020939093013593505050565b60008060008060008060008060c0898b031215614dab578182fd5b8835614db681615e29565b975060208901359650604089013567ffffffffffffffff80821115614dd9578384fd5b614de58c838d016146df565b909850965060608b0135915080821115614dfd578384fd5b50614e0a8b828c016146df565b9095509350506080890135614e1e81615e29565b8092505060a089013590509295985092959890939650565b600080600080600080600080600060e08a8c031215614e53578283fd5b8935614e5e81615e29565b985060208a0135975060408a0135965060608a013567ffffffffffffffff80821115614e88578485fd5b614e948d838e016146df565b909850965060808c0135915080821115614eac578485fd5b50614eb98c828d016146df565b90955093505060a08a0135614ecd81615e29565b8092505060c08a013590509295985092959850929598565b60008060008060008060c08789031215614efd578384fd5b8651614f0881615e29565b8096505060208701519450604087015193506060870151614f2881615e5c565b6080880151909350614f3981615e5c565b60a0880151909250614f4a81615e5c565b809150509295509295509295565b600080600080600060a08688031215614f6f578283fd5b8535614f7a81615e29565b9450602086013593506040860135614f9181615e5c565b92506060860135614fa181615e5c565b91506080860135614fb181615e29565b809150509295509295909350565b60006020808385031215614fd1578182fd5b825167ffffffffffffffff811115614fe7578283fd5b8301601f81018513614ff7578283fd5b805161500561474882615ddf565b8181528381019083850185840285018601891015615021578687fd5b8694505b83851015615043578051835260019490940193918501918501615025565b50979650505050505050565b600060208284031215615060578081fd5b8151612b3281615e4e565b60008060008060608587031215615080578182fd5b843561508b81615e29565b9350602085013567ffffffffffffffff808211156150a7578384fd5b9086019061010082890312156150bb578384fd5b909350604086013590808211156150d0578384fd5b818701915087601f8301126150e3578384fd5b8135818111156150f1578485fd5b886020828501011115615102578485fd5b95989497505060200194505050565b600060208284031215615122578081fd5b5051919050565b6000806040838503121561513b578182fd5b505080516020909101519092909150565b6000815180845260208085019450808401835b8381101561517e57815160ff168752958201959082019060010161515f565b509495945050505050565b600081518084526151a1816020860160208601615dfd565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60007fffffffff000000000000000000000000000000000000000000000000000000008516825282846004840137910160040190815292915050565b60008251615221818460208701615dfd565b9190910192915050565b6000835161523d818460208801615dfd565b7f50616e69632800000000000000000000000000000000000000000000000000009083019081528351615277816006840160208801615dfd565b7f290000000000000000000000000000000000000000000000000000000000000060069290910191820152600701949350505050565b600083516152bf818460208801615dfd565b7f556e6b6e6f776e2800000000000000000000000000000000000000000000000090830190815283516152f9816008840160208801615dfd565b7f290000000000000000000000000000000000000000000000000000000000000060089290910191820152600901949350505050565b60008351615341818460208801615dfd565b7f4572726f722800000000000000000000000000000000000000000000000000009083019081528351615277816006840160208801615dfd565b90815260200190565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff92831681529116602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff97881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b73ffffffffffffffffffffffffffffffffffffffff9586168152938516602085015291841660408401526060830152909116608082015260a00190565b73ffffffffffffffffffffffffffffffffffffffff9384168152919092166020820152604081019190915260600190565b73ffffffffffffffffffffffffffffffffffffffff96871681529486166020860152928516604085015293166060830152608082019290925260a081019190915260c00190565b73ffffffffffffffffffffffffffffffffffffffff93841681529183166020830152909116604082015260600190565b600060c0820173ffffffffffffffffffffffffffffffffffffffff808c1684526020818c1681860152818b16604086015289606086015260c060808601528288845260e086019050899350845b8981101561557357843561555f81615e29565b84168252938201939082019060010161554c565b5085810360a087015286815281019250869150835b868110156155ae5760ff61559b8461479b565b1684529281019291810191600101615588565b50919c9b505050505050505050505050565b600060c0820173ffffffffffffffffffffffffffffffffffffffff808a1684526020818a1681860152818916604086015287606086015260c0608086015282875180855260e0870191508289019450855b8181101561562f578551851683529483019491830191600101615611565b505085810360a0870152615643818861514c565b9c9b505050505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff948516815292841660208401529216604082015260ff909116606082015260800190565b73ffffffffffffffffffffffffffffffffffffffff948516815292909316602083015263ffffffff9081166040830152909116606082015260800190565b73ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff93841681526020810192909252909116604082015260600190565b6020808252825182820181905260009190848201906040850190845b818110156157585783518352928401929184019160010161573c565b50909695505050505050565b60006040825283604083015283856060840137806060858401015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f860116830101905073ffffffffffffffffffffffffffffffffffffffff83166020830152949350505050565b600060208252612b326020830184615189565b60208082526015908201527f64732d6d6174682d7375622d756e646572666c6f770000000000000000000000604082015260600190565b6020808252601f908201527f5472616e7366657248656c7065723a205452414e534645525f4641494c454400604082015260600190565b60208082526012908201527f436c61696d20746f6b656e206973204554480000000000000000000000000000604082015260600190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201527f6464726573730000000000000000000000000000000000000000000000000000606082015260800190565b60208082526014908201527f64732d6d6174682d6d756c2d6f766572666c6f77000000000000000000000000604082015260600190565b6020808252601e908201527f526f757465723a204558434553534956455f494e5055545f414d4f554e540000604082015260600190565b6020808252601d908201527f526f757465723a20494e53554646494349454e545f425f414d4f554e54000000604082015260600190565b60208082526014908201527f64732d6d6174682d6164642d6f766572666c6f77000000000000000000000000604082015260600190565b60208082526011908201527f496e76616c6964206d73672e76616c7565000000000000000000000000000000604082015260600190565b6020808252601d908201527f526f757465723a20494e53554646494349454e545f415f414d4f554e54000000604082015260600190565b6020808252601b908201527f52657475726e20616d6f756e74206973206e6f7420656e6f7567680000000000604082015260600190565b6020808252601a908201527f4d696e2072657475726e2073686f756c64206e6f742062652030000000000000604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252600f908201527f526f757465723a20455850495245440000000000000000000000000000000000604082015260600190565b60208082526017908201527f646174612073686f756c64206265206e6f74207a65726f000000000000000000604082015260600190565b60208082526015908201527f496e76616c69642072657665727420726561736f6e0000000000000000000000604082015260600190565b60208082526022908201527f526f757465723a20494e53554646494349454e545f4f55545055545f414d4f5560408201527f4e54000000000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526023908201527f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960408201527f4c45440000000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526024908201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f464160408201527f494c454400000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526014908201527f526f757465723a20496e76616c69642070616972000000000000000000000000604082015260600190565b918252602082015260400190565b600085825284602083015273ffffffffffffffffffffffffffffffffffffffff84166040830152608060608301526141216080830184615189565b9283526020830191909152604082015260600190565b9586526020860194909452604085019290925263ffffffff908116606085015290811660808401521660a082015260c00190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112615d8c578283fd5b83018035915067ffffffffffffffff821115615da6578283fd5b60200191503681900382131561472157600080fd5b60405181810167ffffffffffffffff81118282101715615dd757fe5b604052919050565b600067ffffffffffffffff821115615df357fe5b5060209081020190565b60005b83811015615e18578181015183820152602001615e00565b83811115613a805750506000910152565b73ffffffffffffffffffffffffffffffffffffffff81168114615e4b57600080fd5b50565b8015158114615e4b57600080fd5b63ffffffff81168114615e4b57600080fdfea26469706673582212206728b2f1db4aa975ef23a242ae450725b894889710785d22b62abebb050e348964736f6c63430007060033