Overview
ETH Balance
0.056608605993685759 ETH
ETH Value
$217.53 (@ $3,842.75/ETH)Token Holdings
More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 41,754 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Fulfill | 113992759 | 357 days ago | IN | 0 ETH | 0.000103133428 | ||||
Fulfill | 113992650 | 357 days ago | IN | 0 ETH | 0.000105518018 | ||||
Fulfill | 113991818 | 357 days ago | IN | 0 ETH | 0.000430965498 | ||||
Remove Liquidity | 111676737 | 411 days ago | IN | 0 ETH | 0.000058984244 | ||||
Remove Liquidity | 82922980 | 636 days ago | IN | 0 ETH | 0.00013325258 | ||||
Remove Liquidity | 82922638 | 636 days ago | IN | 0 ETH | 0.000159192097 | ||||
Remove Liquidity | 79496892 | 649 days ago | IN | 0 ETH | 0.00011504651 | ||||
Cancel | 78921947 | 652 days ago | IN | 0 ETH | 0.00065197047 | ||||
Prepare | 78591823 | 654 days ago | IN | 0 ETH | 0.000870626283 | ||||
Fulfill | 78181471 | 656 days ago | IN | 0 ETH | 0.00059082522 | ||||
Fulfill | 78168266 | 656 days ago | IN | 0 ETH | 0.000795977963 | ||||
Fulfill | 78140116 | 656 days ago | IN | 0 ETH | 0.000820166784 | ||||
Fulfill | 78139940 | 656 days ago | IN | 0 ETH | 0.000203230994 | ||||
Prepare | 78117151 | 657 days ago | IN | 0 ETH | 0.000890225625 | ||||
Prepare | 77960431 | 657 days ago | IN | 0 ETH | 0.000932709463 | ||||
Cancel | 77955089 | 657 days ago | IN | 0 ETH | 0.000537892562 | ||||
Prepare | 77945392 | 657 days ago | IN | 0 ETH | 0.000913150231 | ||||
Prepare | 77942437 | 657 days ago | IN | 0 ETH | 0.000901640638 | ||||
Fulfill | 77927151 | 657 days ago | IN | 0 ETH | 0.001006474652 | ||||
Prepare | 77899186 | 658 days ago | IN | 0 ETH | 0.000787375847 | ||||
Prepare | 77863388 | 658 days ago | IN | 0 ETH | 0.001648947173 | ||||
Fulfill | 77847082 | 658 days ago | IN | 0 ETH | 0.000736959656 | ||||
Prepare | 77784073 | 658 days ago | IN | 0 ETH | 0.001032257867 | ||||
Prepare | 77759666 | 658 days ago | IN | 0 ETH | 0.001393757797 | ||||
Fulfill | 77720826 | 658 days ago | IN | 0 ETH | 0.000526352993 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
82922638 | 636 days ago | 0.741851371335573 ETH | ||||
80615664 | 645 days ago | 0.234744386258871 ETH | ||||
79496892 | 649 days ago | 1 ETH | ||||
78171408 | 656 days ago | 0.025 ETH | ||||
78164509 | 656 days ago | 0.003 ETH | ||||
78139940 | 656 days ago | 0.00106345451824 ETH | ||||
77960536 | 657 days ago | 0.000335258894728 ETH | ||||
77960536 | 657 days ago | 0.000424026118791 ETH | ||||
77955089 | 657 days ago | 0.0025 ETH | ||||
77945504 | 657 days ago | 0.002456171198476 ETH | ||||
77945504 | 657 days ago | 0.000403972049079 ETH | ||||
77942556 | 657 days ago | 0.002565681530942 ETH | ||||
77942556 | 657 days ago | 0.000393366725676 ETH | ||||
77926784 | 657 days ago | 0.026 ETH | ||||
77899282 | 658 days ago | 0.000889448997947 ETH | ||||
77899282 | 658 days ago | 0.000272326300799 ETH | ||||
77846905 | 658 days ago | 0.0017 ETH | ||||
77784165 | 658 days ago | 0.002262281417492 ETH | ||||
77784165 | 658 days ago | 0.000527481653515 ETH | ||||
77759750 | 658 days ago | 0.018984231922981 ETH | ||||
77759750 | 658 days ago | 0.001019941144225 ETH | ||||
77708711 | 658 days ago | 0.000699903509874 ETH | ||||
77708711 | 658 days ago | 0.000297466991189 ETH | ||||
77702506 | 658 days ago | 0.00693875 ETH | ||||
77689118 | 659 days ago | 0.035 ETH |
Loading...
Loading
Contract Name:
TransactionManager
Compiler Version
v0.8.4+commit.c7e474f2
Contract Source Code (Solidity)
/** *Submitted for verification at optimistic.etherscan.io on 2021-11-16 */ // Sources flattened with hardhat v2.6.8 https://hardhat.org // SPDX-License-Identifier: UNLICENSED // File contracts/PriceOracle.sol pragma solidity ^0.8.4; abstract contract PriceOracle { /// @notice Indicator that this is a PriceOracle contract (for inspection) bool public constant isPriceOracle = true; /** * @notice Get the price of a token * @param token The token to get the price of * @return The asset price mantissa (scaled by 1e18). * Zero means the price is unavailable. */ function getTokenPrice(address token) external virtual view returns (uint); } // File @openzeppelin/contracts/utils/math/[email protected] pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is no longer needed starting with Solidity 0.8. The compiler * now has built in overflow checking. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } } // File @openzeppelin/contracts/token/ERC20/[email protected] pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } // File @openzeppelin/contracts/utils/[email protected] pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) private pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } } // File @openzeppelin/contracts/token/ERC20/utils/[email protected] pragma solidity ^0.8.0; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } // File contracts/interfaces/IERC20Extended.sol pragma solidity ^0.8.4; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20Extended { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the token decimals. */ function decimals() external view returns (uint8); /** * @dev Returns the token symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the token name. */ function name() external view returns (string memory); /** * @dev Returns the bep token owner. */ function getOwner() external view returns (address); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address _owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } // File contracts/ConnextPriceOracle.sol pragma solidity ^0.8.4; interface AggregatorV3Interface { function decimals() external view returns (uint8); function description() external view returns (string memory); function version() external view returns (uint256); // getRoundData and latestRoundData should both raise "No data present" // if they do not have data to report, instead of returning unset values // which could be misinterpreted as actual reported values. function getRoundData(uint80 _roundId) external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); function latestRoundData() external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); } contract ConnextPriceOracle is PriceOracle { using SafeMath for uint256; using SafeERC20 for IERC20Extended; address public admin; address public wrapped; /// @notice Chainlink Aggregators mapping(address => AggregatorV3Interface) public aggregators; struct PriceInfo { address token; // Address of token contract, TOKEN address baseToken; // Address of base token contract, BASETOKEN address lpToken; // Address of TOKEN-BASETOKEN pair contract bool active; // Active status of price record 0 } mapping(address => PriceInfo) public priceRecords; event NewAdmin(address oldAdmin, address newAdmin); event PriceRecordUpdated(address token, address baseToken, address lpToken, bool _active); event AggregatorUpdated(address tokenAddress, address source); constructor(address _wrapped) { wrapped = _wrapped; admin = msg.sender; } function getTokenPrice(address _tokenAddress) public view override returns (uint256) { address tokenAddress = _tokenAddress; if (_tokenAddress == address(0)) { tokenAddress = wrapped; } uint256 tokenPrice = getPriceFromOracle(tokenAddress); if (tokenPrice == 0) { tokenPrice = getPriceFromDex(tokenAddress); } return tokenPrice; } function getPriceFromDex(address _tokenAddress) public view returns (uint256) { PriceInfo storage priceInfo = priceRecords[_tokenAddress]; if (priceInfo.active) { uint256 rawTokenAmount = IERC20Extended(priceInfo.token).balanceOf(priceInfo.lpToken); uint256 tokenDecimalDelta = 18-uint256(IERC20Extended(priceInfo.token).decimals()); uint256 tokenAmount = rawTokenAmount.mul(10**tokenDecimalDelta); uint256 rawBaseTokenAmount = IERC20Extended(priceInfo.baseToken).balanceOf(priceInfo.lpToken); uint256 baseTokenDecimalDelta = 18-uint256(IERC20Extended(priceInfo.baseToken).decimals()); uint256 baseTokenAmount = rawBaseTokenAmount.mul(10**baseTokenDecimalDelta); uint256 baseTokenPrice = getPriceFromOracle(priceInfo.baseToken); uint256 tokenPrice = baseTokenPrice.mul(baseTokenAmount).div(tokenAmount); return tokenPrice; } else { return 0; } } function getPriceFromOracle(address _tokenAddress) public view returns (uint256) { uint256 chainLinkPrice = getPriceFromChainlink(_tokenAddress); return chainLinkPrice; } function getPriceFromChainlink(address _tokenAddress) public view returns (uint256) { AggregatorV3Interface aggregator = aggregators[_tokenAddress]; if (address(aggregator) != address(0)) { ( , int answer, , , ) = aggregator.latestRoundData(); // It's fine for price to be 0. We have two price feeds. if (answer == 0) { return 0; } // Extend the decimals to 1e18. uint retVal = uint(answer); uint price = retVal.mul(10**(18 - uint(aggregator.decimals()))); return price; } return 0; } function setDexPriceInfo(address _token, address _baseToken, address _lpToken, bool _active) public { require(msg.sender == admin, "only admin can set DEX price"); PriceInfo storage priceInfo = priceRecords[_token]; uint256 baseTokenPrice = getPriceFromOracle(_baseToken); require(baseTokenPrice > 0, "invalid base token"); priceInfo.token = _token; priceInfo.baseToken = _baseToken; priceInfo.lpToken = _lpToken; priceInfo.active = _active; emit PriceRecordUpdated(_token, _baseToken, _lpToken, _active); } function setAdmin(address newAdmin) external { require(msg.sender == admin, "only admin can set new admin"); address oldAdmin = admin; admin = newAdmin; emit NewAdmin(oldAdmin, newAdmin); } function setAggregators(address[] calldata tokenAddresses, address[] calldata sources) external { require(msg.sender == admin, "only the admin may set the aggregators"); for (uint i = 0; i < tokenAddresses.length; i++) { aggregators[tokenAddresses[i]] = AggregatorV3Interface(sources[i]); emit AggregatorUpdated(tokenAddresses[i], sources[i]); } } function compareStrings(string memory a, string memory b) internal pure returns (bool) { return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b)))); } } // File contracts/interfaces/IFulfillInterpreter.sol pragma solidity 0.8.4; interface IFulfillInterpreter { event Executed( bytes32 indexed transactionId, address payable callTo, address assetId, address payable fallbackAddress, uint256 amount, bytes callData, bytes returnData, bool success, bool isContract ); function getTransactionManager() external returns (address); function execute( bytes32 transactionId, address payable callTo, address assetId, address payable fallbackAddress, uint256 amount, bytes calldata callData ) external payable returns (bool success, bool isContract, bytes memory returnData); } // File contracts/lib/LibAsset.sol pragma solidity 0.8.4; /** * @title LibAsset * @author Connext <[email protected]> * @notice This library contains helpers for dealing with onchain transfers * of assets, including accounting for the native asset `assetId` * conventions and any noncompliant ERC20 transfers */ library LibAsset { /** * @dev All native assets use the empty address for their asset id * by convention */ address constant NATIVE_ASSETID = address(0); /** * @notice Determines whether the given assetId is the native asset * @param assetId The asset identifier to evaluate * @return Boolean indicating if the asset is the native asset */ function isNativeAsset(address assetId) internal pure returns (bool) { return assetId == NATIVE_ASSETID; } /** * @notice Gets the balance of the inheriting contract for the given asset * @param assetId The asset identifier to get the balance of * @return Balance held by contracts using this library */ function getOwnBalance(address assetId) internal view returns (uint256) { return isNativeAsset(assetId) ? address(this).balance : IERC20(assetId).balanceOf(address(this)); } /** * @notice Transfers ether from the inheriting contract to a given * recipient * @param recipient Address to send ether to * @param amount Amount to send to given recipient */ function transferNativeAsset(address payable recipient, uint256 amount) internal { Address.sendValue(recipient, amount); } /** * @notice Transfers tokens from the inheriting contract to a given * recipient * @param assetId Token address to transfer * @param recipient Address to send ether to * @param amount Amount to send to given recipient */ function transferERC20( address assetId, address recipient, uint256 amount ) internal { SafeERC20.safeTransfer(IERC20(assetId), recipient, amount); } /** * @notice Transfers tokens from a sender to a given recipient * @param assetId Token address to transfer * @param from Address of sender/owner * @param to Address of recipient/spender * @param amount Amount to transfer from owner to spender */ function transferFromERC20( address assetId, address from, address to, uint256 amount ) internal { SafeERC20.safeTransferFrom(IERC20(assetId), from, to, amount); } /** * @notice Increases the allowance of a token to a spender * @param assetId Token address of asset to increase allowance of * @param spender Account whos allowance is increased * @param amount Amount to increase allowance by */ function increaseERC20Allowance( address assetId, address spender, uint256 amount ) internal { require(!isNativeAsset(assetId), "#IA:034"); SafeERC20.safeIncreaseAllowance(IERC20(assetId), spender, amount); } /** * @notice Decreases the allowance of a token to a spender * @param assetId Token address of asset to decrease allowance of * @param spender Account whos allowance is decreased * @param amount Amount to decrease allowance by */ function decreaseERC20Allowance( address assetId, address spender, uint256 amount ) internal { require(!isNativeAsset(assetId), "#DA:034"); SafeERC20.safeDecreaseAllowance(IERC20(assetId), spender, amount); } /** * @notice Wrapper function to transfer a given asset (native or erc20) to * some recipient. Should handle all non-compliant return value * tokens as well by using the SafeERC20 contract by open zeppelin. * @param assetId Asset id for transfer (address(0) for native asset, * token address for erc20s) * @param recipient Address to send asset to * @param amount Amount to send to given recipient */ function transferAsset( address assetId, address payable recipient, uint256 amount ) internal { isNativeAsset(assetId) ? transferNativeAsset(recipient, amount) : transferERC20(assetId, recipient, amount); } } // File @openzeppelin/contracts/utils/[email protected] pragma solidity ^0.8.0; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with 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) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } } // File @openzeppelin/contracts/access/[email protected] pragma solidity ^0.8.0; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _setOwner(_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 { _setOwner(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"); _setOwner(newOwner); } function _setOwner(address newOwner) private { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } } // File @openzeppelin/contracts/security/[email protected] pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } } // File contracts/interpreters/FulfillInterpreter.sol pragma solidity 0.8.4; /** * @title FulfillInterpreter * @author Connext <[email protected]> * @notice This library contains an `execute` function that is callabale by * an associated TransactionManager contract. This is used to execute * arbitrary calldata on a receiving chain. */ contract FulfillInterpreter is ReentrancyGuard, IFulfillInterpreter { address private immutable _transactionManager; constructor(address transactionManager) { _transactionManager = transactionManager; } /** * @notice Errors if the sender is not the transaction manager */ modifier onlyTransactionManager { require(msg.sender == _transactionManager, "#OTM:027"); _; } /** * @notice Returns the transaction manager address (only address that can * call the `execute` function) * @return The address of the associated transaction manager */ function getTransactionManager() override external view returns (address) { return _transactionManager; } /** * @notice Executes some arbitrary call data on a given address. The * call data executes can be payable, and will have `amount` sent * along with the function (or approved to the contract). If the * call fails, rather than reverting, funds are sent directly to * some provided fallbaack address * @param transactionId Unique identifier of transaction id that necessitated * calldata execution * @param callTo The address to execute the calldata on * @param assetId The assetId of the funds to approve to the contract or * send along with the call * @param fallbackAddress The address to send funds to if the `call` fails * @param amount The amount to approve or send with the call * @param callData The data to execute */ function execute( bytes32 transactionId, address payable callTo, address assetId, address payable fallbackAddress, uint256 amount, bytes calldata callData ) override external payable onlyTransactionManager returns (bool, bool, bytes memory) { // If it is not ether, approve the callTo // We approve here rather than transfer since many external contracts // simply require an approval, and it is unclear if they can handle // funds transferred directly to them (i.e. Uniswap) bool isNative = LibAsset.isNativeAsset(assetId); if (!isNative) { LibAsset.increaseERC20Allowance(assetId, callTo, amount); } // Check if the callTo is a contract bool success; bytes memory returnData; bool isContract = Address.isContract(callTo); if (isContract) { // Try to execute the callData // the low level call will return `false` if its execution reverts (success, returnData) = callTo.call{value: isNative ? amount : 0}(callData); } // Handle failure cases if (!success) { // If it fails, transfer to fallback LibAsset.transferAsset(assetId, fallbackAddress, amount); // Decrease allowance if (!isNative) { LibAsset.decreaseERC20Allowance(assetId, callTo, amount); } } // Emit event emit Executed( transactionId, callTo, assetId, fallbackAddress, amount, callData, returnData, success, isContract ); return (success, isContract, returnData); } } // File contracts/test/Counter.sol pragma solidity 0.8.4; contract Counter { bool public shouldRevert; uint256 public count = 0; constructor() { shouldRevert = false; } function setShouldRevert(bool value) public { shouldRevert = value; } function increment() public { require(!shouldRevert, "increment: shouldRevert is true"); count += 1; } function incrementAndSend(address assetId, address recipient, uint256 amount) public payable { if (LibAsset.isNativeAsset(assetId)) { require(msg.value == amount, "incrementAndSend: INVALID_ETH_AMOUNT"); } else { require(msg.value == 0, "incrementAndSend: ETH_WITH_ERC"); LibAsset.transferFromERC20(assetId, msg.sender, address(this), amount); } increment(); LibAsset.transferAsset(assetId, payable(recipient), amount); } } // File contracts/interfaces/IERC20Minimal.sol pragma solidity >=0.5.0; /// @title Minimal ERC20 interface for Uniswap /// @notice Contains a subset of the full ERC20 interface that is used in Uniswap V3 interface IERC20Minimal { /// @notice Returns the balance of a token /// @param account The account for which to look up the number of tokens it has, i.e. its balance /// @return The number of tokens held by the account function balanceOf(address account) external view returns (uint256); /// @notice Transfers the amount of token from the `msg.sender` to the recipient /// @param recipient The account that will receive the amount transferred /// @param amount The number of tokens to send from the sender to the recipient /// @return Returns true for a successful transfer, false for an unsuccessful transfer function transfer(address recipient, uint256 amount) external returns (bool); /// @notice Returns the current allowance given to a spender by an owner /// @param owner The account of the token owner /// @param spender The account of the token spender /// @return The current allowance granted by `owner` to `spender` function allowance(address owner, address spender) external view returns (uint256); /// @notice Sets the allowance of a spender from the `msg.sender` to the value `amount` /// @param spender The account which will be allowed to spend a given amount of the owners tokens /// @param amount The amount of tokens allowed to be used by `spender` /// @return Returns true for a successful approval, false for unsuccessful function approve(address spender, uint256 amount) external returns (bool); /// @notice Transfers `amount` tokens from `sender` to `recipient` up to the allowance given to the `msg.sender` /// @param sender The account from which the transfer will be initiated /// @param recipient The recipient of the transfer /// @param amount The amount of the transfer /// @return Returns true for a successful transfer, false for unsuccessful function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /// @notice Event emitted when tokens are transferred from one address to another, either via `#transfer` or `#transferFrom`. /// @param from The account from which the tokens were sent, i.e. the balance decreased /// @param to The account to which the tokens were sent, i.e. the balance increased /// @param value The amount of tokens that were transferred event Transfer(address indexed from, address indexed to, uint256 value); /// @notice Event emitted when the approval amount for the spender of a given owner's tokens changes. /// @param owner The account that approved spending of its tokens /// @param spender The account for which the spending allowance was modified /// @param value The new allowance from the owner to the spender event Approval(address indexed owner, address indexed spender, uint256 value); } // File @openzeppelin/contracts/token/ERC20/extensions/[email protected] pragma solidity ^0.8.0; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); } // File @openzeppelin/contracts/token/ERC20/[email protected] pragma solidity ^0.8.0; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin guidelines: functions revert instead * of returning `false` on failure. This behavior is nonetheless conventional * and does not conflict with the expectations of ERC20 applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * The default value of {decimals} is 18. To select a different value for * {decimals} you should overload it. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless this function is * overridden; * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * Requirements: * * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for ``sender``'s tokens of at least * `amount`. */ function transferFrom( address sender, address recipient, uint256 amount ) public virtual override returns (bool) { _transfer(sender, recipient, amount); uint256 currentAllowance = _allowances[sender][_msgSender()]; require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); unchecked { _approve(sender, _msgSender(), currentAllowance - amount); } return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { uint256 currentAllowance = _allowances[_msgSender()][spender]; require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(_msgSender(), spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `sender` to `recipient`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer( address sender, address recipient, uint256 amount ) internal virtual { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(sender, recipient, amount); uint256 senderBalance = _balances[sender]; require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[sender] = senderBalance - amount; } _balances[recipient] += amount; emit Transfer(sender, recipient, amount); _afterTokenTransfer(sender, recipient, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; _balances[account] += amount; emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; } _totalSupply -= amount; emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 amount ) internal virtual {} } // File contracts/test/FeeERC20.sol pragma solidity 0.8.4; /* This token is ONLY useful for testing * Anybody can mint as many tokens as they like * Anybody can burn anyone else's tokens */ contract FeeERC20 is ERC20 { uint256 public fee = 1; constructor() ERC20("Fee Token", "FEERC20") { _mint(msg.sender, 1000000 ether); } function setFee(uint256 _fee) external { fee = _fee; } function mint(address account, uint256 amount) external { _mint(account, amount); } function burn(address account, uint256 amount) external { _burn(account, amount); } function transfer(address account, uint256 amount) public override returns (bool) { uint256 toTransfer = amount - fee; _transfer(msg.sender, account, toTransfer); return true; } function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) { uint256 toTransfer = amount - fee; _burn(sender, fee); _transfer(sender, recipient, toTransfer); return true; } } // File contracts/test/LibAssetTest.sol pragma solidity 0.8.4; /// @title LibAssetTest /// @author Connext /// @notice Used to easily test the internal methods of /// LibAsset.sol by aliasing them to public /// methods. contract LibAssetTest { constructor() {} receive() external payable {} function isNativeAsset(address assetId) public pure returns (bool) { return LibAsset.isNativeAsset(assetId); } function getOwnBalance(address assetId) public view returns (uint256) { return LibAsset.getOwnBalance(assetId); } function transferNativeAsset(address payable recipient, uint256 amount) public { LibAsset.transferNativeAsset(recipient, amount); } function increaseERC20Allowance(address assetId, address spender, uint256 amount) public { LibAsset.increaseERC20Allowance(assetId, spender, amount); } function decreaseERC20Allowance(address assetId, address spender, uint256 amount) public { LibAsset.decreaseERC20Allowance(assetId, spender, amount); } function transferERC20( address assetId, address recipient, uint256 amount ) public { LibAsset.transferERC20(assetId, recipient, amount); } // This function is a wrapper for transfers of Ether or ERC20 tokens, // both standard-compliant ones as well as tokens that exhibit the // missing-return-value bug. function transferAsset( address assetId, address payable recipient, uint256 amount ) public { LibAsset.transferAsset(assetId, recipient, amount); } } // File contracts/test/RevertableERC20.sol pragma solidity 0.8.4; /* This token is ONLY useful for testing * Anybody can mint as many tokens as they like * Anybody can burn anyone else's tokens */ contract RevertableERC20 is ERC20 { bool public shouldRevert = false; constructor() ERC20("Revertable Token", "RVRT") { _mint(msg.sender, 1000000 ether); } function mint(address account, uint256 amount) external { require(!shouldRevert, "mint: SHOULD_REVERT"); _mint(account, amount); } function burn(address account, uint256 amount) external { require(!shouldRevert, "burn: SHOULD_REVERT"); _burn(account, amount); } function transfer(address account, uint256 amount) public override returns (bool) { require(!shouldRevert, "transfer: SHOULD_REVERT"); _transfer(msg.sender, account, amount); return true; } function setShouldRevert(bool _shouldRevert) external { shouldRevert = _shouldRevert; } } // File contracts/test/TestERC20.sol pragma solidity 0.8.4; /* This token is ONLY useful for testing * Anybody can mint as many tokens as they like * Anybody can burn anyone else's tokens */ contract TestERC20 is ERC20 { constructor() ERC20("Test Token", "TEST") { _mint(msg.sender, 1000000 ether); } function mint(address account, uint256 amount) external { _mint(account, amount); } function burn(address account, uint256 amount) external { _burn(account, amount); } } // File contracts/interfaces/ITransactionManager.sol pragma solidity 0.8.4; interface ITransactionManager { // Structs // Holds all data that is constant between sending and // receiving chains. The hash of this is what gets signed // to ensure the signature can be used on both chains. struct InvariantTransactionData { address receivingChainTxManagerAddress; address user; address router; address initiator; // msg.sender of sending side address sendingAssetId; address receivingAssetId; address sendingChainFallback; // funds sent here on cancel address receivingAddress; address callTo; uint256 sendingChainId; uint256 receivingChainId; bytes32 callDataHash; // hashed to prevent free option bytes32 transactionId; } // Holds all data that varies between sending and receiving // chains. The hash of this is stored onchain to ensure the // information passed in is valid. struct VariantTransactionData { uint256 amount; uint256 expiry; uint256 preparedBlockNumber; } // All Transaction data, constant and variable struct TransactionData { address receivingChainTxManagerAddress; address user; address router; address initiator; // msg.sender of sending side address sendingAssetId; address receivingAssetId; address sendingChainFallback; address receivingAddress; address callTo; bytes32 callDataHash; bytes32 transactionId; uint256 sendingChainId; uint256 receivingChainId; uint256 amount; uint256 expiry; uint256 preparedBlockNumber; // Needed for removal of active blocks on fulfill/cancel } // The structure of the signed data for fulfill struct SignedFulfillData { bytes32 transactionId; uint256 relayerFee; string functionIdentifier; // "fulfill" or "cancel" uint256 receivingChainId; // For domain separation address receivingChainTxManagerAddress; // For domain separation } // The structure of the signed data for cancellation struct SignedCancelData { bytes32 transactionId; string functionIdentifier; uint256 receivingChainId; address receivingChainTxManagerAddress; // For domain separation } /** * Arguments for calling prepare() * @param invariantData The data for a crosschain transaction that will * not change between sending and receiving chains. * The hash of this data is used as the key to store * the inforamtion that does change between chains * (amount,expiry,preparedBlock) for verification * @param amount The amount of the transaction on this chain * @param expiry The block.timestamp when the transaction will no longer be * fulfillable and is freely cancellable on this chain * @param encryptedCallData The calldata to be executed when the tx is * fulfilled. Used in the function to allow the user * to reconstruct the tx from events. Hash is stored * onchain to prevent shenanigans. * @param encodedBid The encoded bid that was accepted by the user for this * crosschain transfer. It is supplied as a param to the * function but is only used in event emission * @param bidSignature The signature of the bidder on the encoded bid for * this transaction. Only used within the function for * event emission. The validity of the bid and * bidSignature are enforced offchain * @param encodedMeta The meta for the function */ struct PrepareArgs { InvariantTransactionData invariantData; uint256 amount; uint256 expiry; bytes encryptedCallData; bytes encodedBid; bytes bidSignature; bytes encodedMeta; } /** * @param txData All of the data (invariant and variant) for a crosschain * transaction. The variant data provided is checked against * what was stored when the `prepare` function was called. * @param relayerFee The fee that should go to the relayer when they are * calling the function on the receiving chain for the user * @param signature The users signature on the transaction id + fee that * can be used by the router to unlock the transaction on * the sending chain * @param callData The calldata to be sent to and executed by the * `FulfillHelper` * @param encodedMeta The meta for the function */ struct FulfillArgs { TransactionData txData; uint256 relayerFee; bytes signature; bytes callData; bytes encodedMeta; } /** * Arguments for calling cancel() * @param txData All of the data (invariant and variant) for a crosschain * transaction. The variant data provided is checked against * what was stored when the `prepare` function was called. * @param signature The user's signature that allows a transaction to be * cancelled by a relayer * @param encodedMeta The meta for the function */ struct CancelArgs { TransactionData txData; bytes signature; bytes encodedMeta; } // Adding/removing asset events event RouterAdded(address indexed addedRouter, address indexed caller); event RouterRemoved(address indexed removedRouter, address indexed caller); // Adding/removing router events event AssetAdded(address indexed addedAssetId, address indexed caller); event AssetRemoved(address indexed removedAssetId, address indexed caller); // Liquidity events event LiquidityAdded(address indexed router, address indexed assetId, uint256 amount, address caller); event LiquidityRemoved(address indexed router, address indexed assetId, uint256 amount, address recipient); // Transaction events event TransactionPrepared( address indexed user, address indexed router, bytes32 indexed transactionId, TransactionData txData, address caller, PrepareArgs args ); event TransactionFulfilled( address indexed user, address indexed router, bytes32 indexed transactionId, FulfillArgs args, bool success, bool isContract, bytes returnData, address caller ); event TransactionCancelled( address indexed user, address indexed router, bytes32 indexed transactionId, CancelArgs args, address caller ); // Getters function getChainId() external view returns (uint256); function getStoredChainId() external view returns (uint256); // Owner only methods function addRouter(address router) external; function removeRouter(address router) external; function addAssetId(address assetId) external; function removeAssetId(address assetId) external; // Router only methods function addLiquidityFor(uint256 amount, address assetId, address router) external payable; function addLiquidity(uint256 amount, address assetId) external payable; function removeLiquidity( uint256 amount, address assetId, address payable recipient ) external; // Methods for crosschain transfers // called in the following order (in happy case) // 1. prepare by user on sending chain // 2. prepare by router on receiving chain // 3. fulfill by user on receiving chain // 4. fulfill by router on sending chain function prepare( PrepareArgs calldata args ) external payable returns (TransactionData memory); function fulfill( FulfillArgs calldata args ) external returns (TransactionData memory); function cancel(CancelArgs calldata args) external returns (TransactionData memory); } // File contracts/ProposedOwnable.sol pragma solidity 0.8.4; /** * @title ProposedOwnable * @notice 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 via a two step process: * 1. Call `proposeOwner` * 2. Wait out the delay period * 3. Call `acceptOwner` * * @dev 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. * * @dev The majority of this code was taken from the openzeppelin Ownable * contract * */ abstract contract ProposedOwnable { address private _owner; address private _proposed; uint256 private _proposedOwnershipTimestamp; bool private _routerOwnershipRenounced; uint256 private _routerOwnershipTimestamp; bool private _assetOwnershipRenounced; uint256 private _assetOwnershipTimestamp; uint256 private constant _delay = 7 days; event RouterOwnershipRenunciationProposed(uint256 timestamp); event RouterOwnershipRenounced(bool renounced); event AssetOwnershipRenunciationProposed(uint256 timestamp); event AssetOwnershipRenounced(bool renounced); event OwnershipProposed(address indexed proposedOwner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @notice Initializes the contract setting the deployer as the initial * owner. */ constructor() { _setOwner(msg.sender); } /** * @notice Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @notice Returns the address of the proposed owner. */ function proposed() public view virtual returns (address) { return _proposed; } /** * @notice Returns the address of the proposed owner. */ function proposedTimestamp() public view virtual returns (uint256) { return _proposedOwnershipTimestamp; } /** * @notice Returns the timestamp when router ownership was last proposed to be renounced */ function routerOwnershipTimestamp() public view virtual returns (uint256) { return _routerOwnershipTimestamp; } /** * @notice Returns the timestamp when asset ownership was last proposed to be renounced */ function assetOwnershipTimestamp() public view virtual returns (uint256) { return _assetOwnershipTimestamp; } /** * @notice Returns the delay period before a new owner can be accepted. */ function delay() public view virtual returns (uint256) { return _delay; } /** * @notice Throws if called by any account other than the owner. */ modifier onlyOwner() { require(_owner == msg.sender, "#OO:029"); _; } /** * @notice Throws if called by any account other than the proposed owner. */ modifier onlyProposed() { require(_proposed == msg.sender, "#OP:035"); _; } /** * @notice Indicates if the ownership of the router whitelist has * been renounced */ function isRouterOwnershipRenounced() public view returns (bool) { return _owner == address(0) || _routerOwnershipRenounced; } /** * @notice Indicates if the ownership of the router whitelist has * been renounced */ function proposeRouterOwnershipRenunciation() public virtual onlyOwner { // Use contract as source of truth // Will fail if all ownership is renounced by modifier require(!_routerOwnershipRenounced, "#PROR:038"); // Begin delay, emit event _setRouterOwnershipTimestamp(); } /** * @notice Indicates if the ownership of the asset whitelist has * been renounced */ function renounceRouterOwnership() public virtual onlyOwner { // Contract as sournce of truth // Will fail if all ownership is renounced by modifier require(!_routerOwnershipRenounced, "#RRO:038"); // Ensure there has been a proposal cycle started require(_routerOwnershipTimestamp > 0, "#RRO:037"); // Delay has elapsed require((block.timestamp - _routerOwnershipTimestamp) > _delay, "#RRO:030"); // Set renounced, emit event, reset timestamp to 0 _setRouterOwnership(true); } /** * @notice Indicates if the ownership of the asset whitelist has * been renounced */ function isAssetOwnershipRenounced() public view returns (bool) { return _owner == address(0) || _assetOwnershipRenounced; } /** * @notice Indicates if the ownership of the asset whitelist has * been renounced */ function proposeAssetOwnershipRenunciation() public virtual onlyOwner { // Contract as sournce of truth // Will fail if all ownership is renounced by modifier require(!_assetOwnershipRenounced, "#PAOR:038"); // Start cycle, emit event _setAssetOwnershipTimestamp(); } /** * @notice Indicates if the ownership of the asset whitelist has * been renounced */ function renounceAssetOwnership() public virtual onlyOwner { // Contract as sournce of truth // Will fail if all ownership is renounced by modifier require(!_assetOwnershipRenounced, "#RAO:038"); // Ensure there has been a proposal cycle started require(_assetOwnershipTimestamp > 0, "#RAO:037"); // Ensure delay has elapsed require((block.timestamp - _assetOwnershipTimestamp) > _delay, "#RAO:030"); // Set ownership, reset timestamp, emit event _setAssetOwnership(true); } /** * @notice Indicates if the ownership has been renounced() by * checking if current owner is address(0) */ function renounced() public view returns (bool) { return _owner == address(0); } /** * @notice Sets the timestamp for an owner to be proposed, and sets the * newly proposed owner as step 1 in a 2-step process */ function proposeNewOwner(address newlyProposed) public virtual onlyOwner { // Contract as source of truth require(_proposed != newlyProposed || newlyProposed == address(0), "#PNO:036"); // Sanity check: reasonable proposal require(_owner != newlyProposed, "#PNO:038"); _setProposed(newlyProposed); } /** * @notice Renounces ownership of the contract after a delay */ function renounceOwnership() public virtual onlyOwner { // Ensure there has been a proposal cycle started require(_proposedOwnershipTimestamp > 0, "#RO:037"); // Ensure delay has elapsed require((block.timestamp - _proposedOwnershipTimestamp) > _delay, "#RO:030"); // Require proposed is set to 0 require(_proposed == address(0), "#RO:036"); // Emit event, set new owner, reset timestamp _setOwner(_proposed); } /** * @notice Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function acceptProposedOwner() public virtual onlyProposed { // Contract as source of truth require(_owner != _proposed, "#APO:038"); // NOTE: no need to check if _proposedOwnershipTimestamp > 0 because // the only time this would happen is if the _proposed was never // set (will fail from modifier) or if the owner == _proposed (checked // above) // Ensure delay has elapsed require((block.timestamp - _proposedOwnershipTimestamp) > _delay, "#APO:030"); // Emit event, set new owner, reset timestamp _setOwner(_proposed); } ////// INTERNAL ////// function _setRouterOwnershipTimestamp() private { _routerOwnershipTimestamp = block.timestamp; emit RouterOwnershipRenunciationProposed(_routerOwnershipTimestamp); } function _setRouterOwnership(bool value) private { _routerOwnershipRenounced = value; _routerOwnershipTimestamp = 0; emit RouterOwnershipRenounced(value); } function _setAssetOwnershipTimestamp() private { _assetOwnershipTimestamp = block.timestamp; emit AssetOwnershipRenunciationProposed(_assetOwnershipTimestamp); } function _setAssetOwnership(bool value) private { _assetOwnershipRenounced = value; _assetOwnershipTimestamp = 0; emit AssetOwnershipRenounced(value); } function _setOwner(address newOwner) private { address oldOwner = _owner; _owner = newOwner; _proposedOwnershipTimestamp = 0; emit OwnershipTransferred(oldOwner, newOwner); } function _setProposed(address newlyProposed) private { _proposedOwnershipTimestamp = block.timestamp; _proposed = newlyProposed; emit OwnershipProposed(_proposed); } } // File @openzeppelin/contracts/utils/cryptography/[email protected] pragma solidity ^0.8.0; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { // Check the signature length // - case 65: r,s,v signature (standard) // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._ if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return recover(hash, v, r, s); } else if (signature.length == 64) { bytes32 r; bytes32 vs; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. assembly { r := mload(add(signature, 0x20)) vs := mload(add(signature, 0x40)) } return recover(hash, r, vs); } else { revert("ECDSA: invalid signature length"); } } /** * @dev Overload of {ECDSA-recover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.2._ */ function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address) { bytes32 s; uint8 v; assembly { s := and(vs, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) v := add(shr(255, vs), 27) } return recover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, `r` and `s` signature fields separately. */ function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. require( uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, "ECDSA: invalid signature 's' value" ); require(v == 27 || v == 28, "ECDSA: invalid signature 'v' value"); // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); require(signer != address(0), "ECDSA: invalid signature"); return signer; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } } // File contracts/TransactionManager.sol pragma solidity 0.8.4; /** * * @title TransactionManager * @author Connext <[email protected]> * @notice This contract holds the logic to facilitate crosschain transactions. * Transactions go through three phases in the happy case: * * 1. Route Auction (offchain): User broadcasts to our network * signalling their desired route. Routers respond with sealed bids * containing commitments to fulfilling the transaction within a * certain time and price range. * * 2. Prepare: Once the auction is completed, the transaction can be * prepared. The user submits a transaction to `TransactionManager` * contract on sender-side chain containing router's signed bid. This * transaction locks up the users funds on the sending chain. Upon * detecting an event containing their signed bid from the chain, * router submits the same transaction to `TransactionManager` on the * receiver-side chain, and locks up a corresponding amount of * liquidity. The amount locked on the receiving chain is `sending * amount - auction fee` so the router is incentivized to complete the * transaction. * * 3. Fulfill: Upon detecting the `TransactionPrepared` event on the * receiver-side chain, the user signs a message and sends it to a * relayer, who will earn a fee for submission. The relayer (which may * be the router) then submits the message to the `TransactionManager` * to complete their transaction on receiver-side chain and claim the * funds locked by the router. A relayer is used here to allow users * to submit transactions with arbitrary calldata on the receiving * chain without needing gas to do so. The router then submits the * same signed message and completes transaction on sender-side, * unlocking the original `amount`. * * If a transaction is not fulfilled within a fixed timeout, it * reverts and can be reclaimed by the party that called `prepare` on * each chain (initiator). Additionally, transactions can be cancelled * unilaterally by the person owed funds on that chain (router for * sending chain, user for receiving chain) prior to expiry. */ contract TransactionManager is ReentrancyGuard, ProposedOwnable, ITransactionManager { /** * @dev Mapping of router to balance specific to asset */ mapping(address => mapping(address => uint256)) public routerBalances; /** * @dev Mapping of allowed router addresses. Must be added to both * sending and receiving chains when forwarding a transfer. */ mapping(address => bool) public approvedRouters; /** * @dev Mapping of allowed assetIds on same chain as contract */ mapping(address => bool) public approvedAssets; /** * @dev Mapping of hash of `InvariantTransactionData` to the hash * of the `VariantTransactionData` */ mapping(bytes32 => bytes32) public variantTransactionData; /** * @dev The stored chain id of the contract, may be passed in to avoid any * evm issues */ uint256 private immutable chainId; /** * @dev Minimum timeout (will be the lowest on the receiving chain) */ uint256 public constant MIN_TIMEOUT = 1 days; // 24 hours /** * @dev Maximum timeout (will be the highest on the sending chain) */ uint256 public constant MAX_TIMEOUT = 30 days; // 720 hours /** * @dev The external contract that will execute crosschain * calldata */ IFulfillInterpreter public immutable interpreter; constructor(uint256 _chainId) { chainId = _chainId; interpreter = new FulfillInterpreter(address(this)); } /** * @notice Gets the chainId for this contract. If not specified during init * will use the block.chainId */ function getChainId() public view override returns (uint256 _chainId) { // Hold in memory to reduce sload calls uint256 chain = chainId; if (chain == 0) { // If not provided, pull from block chain = block.chainid; } return chain; } /** * @notice Allows us to get the chainId that this contract has stored */ function getStoredChainId() external view override returns (uint256) { return chainId; } /** * @notice Used to add routers that can transact crosschain * @param router Router address to add */ function addRouter(address router) external override onlyOwner { // Sanity check: not empty require(router != address(0), "#AR:001"); // Sanity check: needs approval require(approvedRouters[router] == false, "#AR:032"); // Update mapping approvedRouters[router] = true; // Emit event emit RouterAdded(router, msg.sender); } /** * @notice Used to remove routers that can transact crosschain * @param router Router address to remove */ function removeRouter(address router) external override onlyOwner { // Sanity check: not empty require(router != address(0), "#RR:001"); // Sanity check: needs removal require(approvedRouters[router] == true, "#RR:033"); // Update mapping approvedRouters[router] = false; // Emit event emit RouterRemoved(router, msg.sender); } /** * @notice Used to add assets on same chain as contract that can * be transferred. * @param assetId AssetId to add */ function addAssetId(address assetId) external override onlyOwner { // Sanity check: needs approval require(approvedAssets[assetId] == false, "#AA:032"); // Update mapping approvedAssets[assetId] = true; // Emit event emit AssetAdded(assetId, msg.sender); } /** * @notice Used to remove assets on same chain as contract that can * be transferred. * @param assetId AssetId to remove */ function removeAssetId(address assetId) external override onlyOwner { // Sanity check: already approval require(approvedAssets[assetId] == true, "#RA:033"); // Update mapping approvedAssets[assetId] = false; // Emit event emit AssetRemoved(assetId, msg.sender); } /** * @notice This is used by anyone to increase a router's available * liquidity for a given asset. * @param amount The amount of liquidity to add for the router * @param assetId The address (or `address(0)` if native asset) of the * asset you're adding liquidity for * @param router The router you are adding liquidity on behalf of */ function addLiquidityFor(uint256 amount, address assetId, address router) external payable override nonReentrant { _addLiquidityForRouter(amount, assetId, router); } /** * @notice This is used by any router to increase their available * liquidity for a given asset. * @param amount The amount of liquidity to add for the router * @param assetId The address (or `address(0)` if native asset) of the * asset you're adding liquidity for */ function addLiquidity(uint256 amount, address assetId) external payable override nonReentrant { _addLiquidityForRouter(amount, assetId, msg.sender); } /** * @notice This is used by any router to decrease their available * liquidity for a given asset. * @param amount The amount of liquidity to remove for the router * @param assetId The address (or `address(0)` if native asset) of the * asset you're removing liquidity for * @param recipient The address that will receive the liquidity being removed */ function removeLiquidity( uint256 amount, address assetId, address payable recipient ) external override nonReentrant { // Sanity check: recipient is sensible require(recipient != address(0), "#RL:007"); // Sanity check: nonzero amounts require(amount > 0, "#RL:002"); uint256 routerBalance = routerBalances[msg.sender][assetId]; // Sanity check: amount can be deducted for the router require(routerBalance >= amount, "#RL:008"); // Update router balances unchecked { routerBalances[msg.sender][assetId] = routerBalance - amount; } // Transfer from contract to specified recipient LibAsset.transferAsset(assetId, recipient, amount); // Emit event emit LiquidityRemoved(msg.sender, assetId, amount, recipient); } /** * @notice This function creates a crosschain transaction. When called on * the sending chain, the user is expected to lock up funds. When * called on the receiving chain, the router deducts the transfer * amount from the available liquidity. The majority of the * information about a given transfer does not change between chains, * with three notable exceptions: `amount`, `expiry`, and * `preparedBlock`. The `amount` and `expiry` are decremented * between sending and receiving chains to provide an incentive for * the router to complete the transaction and time for the router to * fulfill the transaction on the sending chain after the unlocking * signature is revealed, respectively. * @param args TODO */ function prepare( PrepareArgs calldata args ) external payable override nonReentrant returns (TransactionData memory) { // Sanity check: user is sensible require(args.invariantData.user != address(0), "#P:009"); // Sanity check: router is sensible require(args.invariantData.router != address(0), "#P:001"); // Router is approved *on both chains* require(isRouterOwnershipRenounced() || approvedRouters[args.invariantData.router], "#P:003"); // Sanity check: sendingChainFallback is sensible require(args.invariantData.sendingChainFallback != address(0), "#P:010"); // Sanity check: valid fallback require(args.invariantData.receivingAddress != address(0), "#P:026"); // Make sure the chains are different require(args.invariantData.sendingChainId != args.invariantData.receivingChainId, "#P:011"); // Make sure the chains are relevant uint256 _chainId = getChainId(); require(args.invariantData.sendingChainId == _chainId || args.invariantData.receivingChainId == _chainId, "#P:012"); { // Expiry scope // Make sure the expiry is greater than min uint256 buffer = args.expiry - block.timestamp; require(buffer >= MIN_TIMEOUT, "#P:013"); // Make sure the expiry is lower than max require(buffer <= MAX_TIMEOUT, "#P:014"); } // Make sure the hash is not a duplicate bytes32 digest = keccak256(abi.encode(args.invariantData)); require(variantTransactionData[digest] == bytes32(0), "#P:015"); // NOTE: the `encodedBid` and `bidSignature` are simply passed through // to the contract emitted event to ensure the availability of // this information. Their validity is asserted offchain, and // is out of scope of this contract. They are used as inputs so // in the event of a router or user crash, they may recover the // correct bid information without requiring an offchain store. // Amount actually used (if fee-on-transfer will be different than // supplied) uint256 amount = args.amount; // First determine if this is sender side or receiver side if (args.invariantData.sendingChainId == _chainId) { // Check the sender is correct require(msg.sender == args.invariantData.initiator, "#P:039"); // Sanity check: amount is sensible // Only check on sending chain to enforce router fees. Transactions could // be 0-valued on receiving chain if it is just a value-less call to some // `IFulfillHelper` require(args.amount > 0, "#P:002"); // Assets are approved // NOTE: Cannot check this on receiving chain because of differing // chain contexts require(isAssetOwnershipRenounced() || approvedAssets[args.invariantData.sendingAssetId], "#P:004"); // This is sender side prepare. The user is beginning the process of // submitting an onchain tx after accepting some bid. They should // lock their funds in the contract for the router to claim after // they have revealed their signature on the receiving chain via // submitting a corresponding `fulfill` tx // Validate correct amounts on msg and transfer from user to // contract amount = transferAssetToContract( args.invariantData.sendingAssetId, args.amount ); // Store the transaction variants. This happens after transferring to // account for fee on transfer tokens variantTransactionData[digest] = hashVariantTransactionData( amount, args.expiry, block.number ); } else { // This is receiver side prepare. The router has proposed a bid on the // transfer which the user has accepted. They can now lock up their // own liquidity on th receiving chain, which the user can unlock by // calling `fulfill`. When creating the `amount` and `expiry` on the // receiving chain, the router should have decremented both. The // expiry should be decremented to ensure the router has time to // complete the sender-side transaction after the user completes the // receiver-side transactoin. The amount should be decremented to act as // a fee to incentivize the router to complete the transaction properly. // Check that the callTo is a contract // NOTE: This cannot happen on the sending chain (different chain // contexts), so a user could mistakenly create a transfer that must be // cancelled if this is incorrect require(args.invariantData.callTo == address(0) || Address.isContract(args.invariantData.callTo), "#P:031"); // Check that the asset is approved // NOTE: This cannot happen on both chains because of differing chain // contexts. May be possible for user to create transaction that is not // prepare-able on the receiver chain. require(isAssetOwnershipRenounced() || approvedAssets[args.invariantData.receivingAssetId], "#P:004"); // Check that the caller is the router require(msg.sender == args.invariantData.router, "#P:016"); // Check that the router isnt accidentally locking funds in the contract require(msg.value == 0, "#P:017"); // Check that router has liquidity uint256 balance = routerBalances[args.invariantData.router][args.invariantData.receivingAssetId]; require(balance >= amount, "#P:018"); // Store the transaction variants variantTransactionData[digest] = hashVariantTransactionData( amount, args.expiry, block.number ); // Decrement the router liquidity // using unchecked because underflow protected against with require unchecked { routerBalances[args.invariantData.router][args.invariantData.receivingAssetId] = balance - amount; } } // Emit event TransactionData memory txData = TransactionData({ receivingChainTxManagerAddress: args.invariantData.receivingChainTxManagerAddress, user: args.invariantData.user, router: args.invariantData.router, initiator: args.invariantData.initiator, sendingAssetId: args.invariantData.sendingAssetId, receivingAssetId: args.invariantData.receivingAssetId, sendingChainFallback: args.invariantData.sendingChainFallback, callTo: args.invariantData.callTo, receivingAddress: args.invariantData.receivingAddress, callDataHash: args.invariantData.callDataHash, transactionId: args.invariantData.transactionId, sendingChainId: args.invariantData.sendingChainId, receivingChainId: args.invariantData.receivingChainId, amount: amount, expiry: args.expiry, preparedBlockNumber: block.number }); emit TransactionPrepared( txData.user, txData.router, txData.transactionId, txData, msg.sender, args ); return txData; } /** * @notice This function completes a crosschain transaction. When called on * the receiving chain, the user reveals their signature on the * transactionId and is sent the amount corresponding to the number * of shares the router locked when calling `prepare`. The router * then uses this signature to unlock the corresponding funds on the * receiving chain, which are then added back to their available * liquidity. The user includes a relayer fee since it is not * assumed they will have gas on the receiving chain. This function * *must* be called before the transaction expiry has elapsed. * @param args TODO */ function fulfill( FulfillArgs calldata args ) external override nonReentrant returns (TransactionData memory) { // Get the hash of the invariant tx data. This hash is the same // between sending and receiving chains. The variant data is stored // in the contract when `prepare` is called within the mapping. { // scope: validation and effects bytes32 digest = hashInvariantTransactionData(args.txData); // Make sure that the variant data matches what was stored require(variantTransactionData[digest] == hashVariantTransactionData( args.txData.amount, args.txData.expiry, args.txData.preparedBlockNumber ), "#F:019"); // Make sure the expiry has not elapsed require(args.txData.expiry >= block.timestamp, "#F:020"); // Make sure the transaction wasn't already completed require(args.txData.preparedBlockNumber > 0, "#F:021"); // Check provided callData matches stored hash require(keccak256(args.callData) == args.txData.callDataHash, "#F:024"); // To prevent `fulfill` / `cancel` from being called multiple times, the // preparedBlockNumber is set to 0 before being hashed. The value of the // mapping is explicitly *not* zeroed out so users who come online without // a store can tell the difference between a transaction that has not been // prepared, and a transaction that was already completed on the receiver // chain. variantTransactionData[digest] = hashVariantTransactionData( args.txData.amount, args.txData.expiry, 0 ); } // Declare these variables for the event emission. Are only assigned // IFF there is an external call on the receiving chain bool success; bool isContract; bytes memory returnData; uint256 _chainId = getChainId(); if (args.txData.sendingChainId == _chainId) { // The router is completing the transaction, they should get the // amount that the user deposited credited to their liquidity // reserves. // Make sure that the user is not accidentally fulfilling the transaction // on the sending chain require(msg.sender == args.txData.router, "#F:016"); // Validate the user has signed require( recoverFulfillSignature( args.txData.transactionId, args.relayerFee, args.txData.receivingChainId, args.txData.receivingChainTxManagerAddress, args.signature ) == args.txData.user, "#F:022" ); // Complete tx to router for original sending amount routerBalances[args.txData.router][args.txData.sendingAssetId] += args.txData.amount; } else { // Validate the user has signed, using domain of contract require( recoverFulfillSignature( args.txData.transactionId, args.relayerFee, _chainId, address(this), args.signature ) == args.txData.user, "#F:022" ); // Sanity check: fee <= amount. Allow `=` in case of only // wanting to execute 0-value crosschain tx, so only providing // the fee amount require(args.relayerFee <= args.txData.amount, "#F:023"); (success, isContract, returnData) = _receivingChainFulfill( args.txData, args.relayerFee, args.callData ); } // Emit event emit TransactionFulfilled( args.txData.user, args.txData.router, args.txData.transactionId, args, success, isContract, returnData, msg.sender ); return args.txData; } /** * @notice Any crosschain transaction can be cancelled after it has been * created to prevent indefinite lock up of funds. After the * transaction has expired, anyone can cancel it. Before the * expiry, only the recipient of the funds on the given chain is * able to cancel. On the sending chain, this means only the router * is able to cancel before the expiry, while only the user can * prematurely cancel on the receiving chain. * @param args TODO */ function cancel(CancelArgs calldata args) external override nonReentrant returns (TransactionData memory) { // Make sure params match against stored data // Also checks that there is an active transfer here // Also checks that sender or receiver chainID is this chainId (bc we checked it previously) // Get the hash of the invariant tx data. This hash is the same // between sending and receiving chains. The variant data is stored // in the contract when `prepare` is called within the mapping. bytes32 digest = hashInvariantTransactionData(args.txData); // Verify the variant data is correct require(variantTransactionData[digest] == hashVariantTransactionData(args.txData.amount, args.txData.expiry, args.txData.preparedBlockNumber), "#C:019"); // Make sure the transaction wasn't already completed require(args.txData.preparedBlockNumber > 0, "#C:021"); // To prevent `fulfill` / `cancel` from being called multiple times, the // preparedBlockNumber is set to 0 before being hashed. The value of the // mapping is explicitly *not* zeroed out so users who come online without // a store can tell the difference between a transaction that has not been // prepared, and a transaction that was already completed on the receiver // chain. variantTransactionData[digest] = hashVariantTransactionData(args.txData.amount, args.txData.expiry, 0); // Get chainId for gas uint256 _chainId = getChainId(); // Return the appropriate locked funds if (args.txData.sendingChainId == _chainId) { // Sender side, funds must be returned to the user if (args.txData.expiry >= block.timestamp) { // Timeout has not expired and tx may only be cancelled by router // NOTE: no need to validate the signature here, since you are requiring // the router must be the sender when the cancellation is during the // fulfill-able window require(msg.sender == args.txData.router, "#C:025"); } // Return users locked funds // NOTE: no need to check if amount > 0 because cant be prepared on // sending chain with 0 value LibAsset.transferAsset( args.txData.sendingAssetId, payable(args.txData.sendingChainFallback), args.txData.amount ); } else { // Receiver side, router liquidity is returned if (args.txData.expiry >= block.timestamp) { // Timeout has not expired and tx may only be cancelled by user // Validate signature require(msg.sender == args.txData.user || recoverCancelSignature(args.txData.transactionId, _chainId, address(this), args.signature) == args.txData.user, "#C:022"); // NOTE: there is no incentive here for relayers to submit this on // behalf of the user (i.e. fee not respected) because the user has not // locked funds on this contract. However, if the user reveals their // cancel signature to the router, they are incentivized to submit it // to unlock their own funds } // Return liquidity to router routerBalances[args.txData.router][args.txData.receivingAssetId] += args.txData.amount; } // Emit event emit TransactionCancelled( args.txData.user, args.txData.router, args.txData.transactionId, args, msg.sender ); // Return return args.txData; } ////////////////////////// /// Private functions /// ////////////////////////// /** * @notice Contains the logic to verify + increment a given routers liquidity * @param amount The amount of liquidity to add for the router * @param assetId The address (or `address(0)` if native asset) of the * asset you're adding liquidity for * @param router The router you are adding liquidity on behalf of */ function _addLiquidityForRouter( uint256 amount, address assetId, address router ) internal { // Sanity check: router is sensible require(router != address(0), "#AL:001"); // Sanity check: nonzero amounts require(amount > 0, "#AL:002"); // Router is approved require(isRouterOwnershipRenounced() || approvedRouters[router], "#AL:003"); // Asset is approved require(isAssetOwnershipRenounced() || approvedAssets[assetId], "#AL:004"); // Transfer funds to contract amount = transferAssetToContract(assetId, amount); // Update the router balances. Happens after pulling funds to account for // the fee on transfer tokens routerBalances[router][assetId] += amount; // Emit event emit LiquidityAdded(router, assetId, amount, msg.sender); } /** * @notice Handles transferring funds from msg.sender to the * transaction manager contract. Used in prepare, addLiquidity * @param assetId The address to transfer * @param specifiedAmount The specified amount to transfer. May not be the * actual amount transferred (i.e. fee on transfer * tokens) */ function transferAssetToContract(address assetId, uint256 specifiedAmount) internal returns (uint256) { uint256 trueAmount = specifiedAmount; // Validate correct amounts are transferred if (LibAsset.isNativeAsset(assetId)) { require(msg.value == specifiedAmount, "#TA:005"); } else { uint256 starting = LibAsset.getOwnBalance(assetId); require(msg.value == 0, "#TA:006"); LibAsset.transferFromERC20(assetId, msg.sender, address(this), specifiedAmount); // Calculate the *actual* amount that was sent here trueAmount = LibAsset.getOwnBalance(assetId) - starting; } return trueAmount; } /// @notice Recovers the signer from the signature provided by the user /// @param transactionId Transaction identifier of tx being recovered /// @param signature The signature you are recovering the signer from function recoverCancelSignature( bytes32 transactionId, uint256 receivingChainId, address receivingChainTxManagerAddress, bytes calldata signature ) internal pure returns (address) { // Create the signed payload SignedCancelData memory payload = SignedCancelData({ transactionId: transactionId, functionIdentifier: "cancel", receivingChainId: receivingChainId, receivingChainTxManagerAddress: receivingChainTxManagerAddress }); // Recover return recoverSignature(abi.encode(payload), signature); } /** * @notice Recovers the signer from the signature provided by the user * @param transactionId Transaction identifier of tx being recovered * @param relayerFee The fee paid to the relayer for submitting the * tx on behalf of the user. * @param signature The signature you are recovering the signer from */ function recoverFulfillSignature( bytes32 transactionId, uint256 relayerFee, uint256 receivingChainId, address receivingChainTxManagerAddress, bytes calldata signature ) internal pure returns (address) { // Create the signed payload SignedFulfillData memory payload = SignedFulfillData({ transactionId: transactionId, relayerFee: relayerFee, functionIdentifier: "fulfill", receivingChainId: receivingChainId, receivingChainTxManagerAddress: receivingChainTxManagerAddress }); // Recover return recoverSignature(abi.encode(payload), signature); } /** * @notice Holds the logic to recover the signer from an encoded payload. * Will hash and convert to an eth signed message. * @param encodedPayload The payload that was signed * @param signature The signature you are recovering the signer from */ function recoverSignature(bytes memory encodedPayload, bytes calldata signature) internal pure returns (address) { // Recover return ECDSA.recover( ECDSA.toEthSignedMessageHash(keccak256(encodedPayload)), signature ); } /** * @notice Returns the hash of only the invariant portions of a given * crosschain transaction * @param txData TransactionData to hash */ function hashInvariantTransactionData(TransactionData calldata txData) internal pure returns (bytes32) { InvariantTransactionData memory invariant = InvariantTransactionData({ receivingChainTxManagerAddress: txData.receivingChainTxManagerAddress, user: txData.user, router: txData.router, initiator: txData.initiator, sendingAssetId: txData.sendingAssetId, receivingAssetId: txData.receivingAssetId, sendingChainFallback: txData.sendingChainFallback, callTo: txData.callTo, receivingAddress: txData.receivingAddress, sendingChainId: txData.sendingChainId, receivingChainId: txData.receivingChainId, callDataHash: txData.callDataHash, transactionId: txData.transactionId }); return keccak256(abi.encode(invariant)); } /** * @notice Returns the hash of only the variant portions of a given * crosschain transaction * @param amount amount to hash * @param expiry expiry to hash * @param preparedBlockNumber preparedBlockNumber to hash * @return Hash of the variant data * */ function hashVariantTransactionData(uint256 amount, uint256 expiry, uint256 preparedBlockNumber) internal pure returns (bytes32) { VariantTransactionData memory variant = VariantTransactionData({ amount: amount, expiry: expiry, preparedBlockNumber: preparedBlockNumber }); return keccak256(abi.encode(variant)); } /** * @notice Handles the receiving-chain fulfillment. This function should * pay the relayer and either send funds to the specified address * or execute the calldata. Will return a tuple of boolean,bytes * indicating the success and return data of the external call. * @dev Separated from fulfill function to avoid stack too deep errors * * @param txData The TransactionData that needs to be fulfilled * @param relayerFee The fee to be paid to the relayer for submission * @param callData The data to be executed on the receiving chain * * @return Tuple representing (success, returnData) of the external call */ function _receivingChainFulfill( TransactionData calldata txData, uint256 relayerFee, bytes calldata callData ) internal returns (bool, bool, bytes memory) { // The user is completing the transaction, they should get the // amount that the router deposited less fees for relayer. // Get the amount to send uint256 toSend; unchecked { toSend = txData.amount - relayerFee; } // Send the relayer the fee if (relayerFee > 0) { LibAsset.transferAsset(txData.receivingAssetId, payable(msg.sender), relayerFee); } // Handle receiver chain external calls if needed if (txData.callTo == address(0)) { // No external calls, send directly to receiving address if (toSend > 0) { LibAsset.transferAsset(txData.receivingAssetId, payable(txData.receivingAddress), toSend); } return (false, false, new bytes(0)); } else { // Handle external calls with a fallback to the receiving // address in case the call fails so the funds dont remain // locked. bool isNativeAsset = LibAsset.isNativeAsset(txData.receivingAssetId); // First, transfer the funds to the helper if needed if (!isNativeAsset && toSend > 0) { LibAsset.transferERC20(txData.receivingAssetId, address(interpreter), toSend); } // Next, call `execute` on the helper. Helpers should internally // track funds to make sure no one user is able to take all funds // for tx, and handle the case of reversions return interpreter.execute{ value: isNativeAsset ? toSend : 0}( txData.transactionId, payable(txData.callTo), txData.receivingAssetId, payable(txData.receivingAddress), toSend, callData ); } } } // File contracts/interfaces/IPriceOracle.sol pragma solidity ^0.8.4; interface IPriceOracle { /** * @notice Get the price of a token * @param token The token to get the price of * @return The asset price mantissa (scaled by 1e18). * Zero means the price is unavailable. */ function getTokenPrice(address token) external view returns (uint256); }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addedAssetId","type":"address"},{"indexed":true,"internalType":"address","name":"caller","type":"address"}],"name":"AssetAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"renounced","type":"bool"}],"name":"AssetOwnershipRenounced","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"AssetOwnershipRenunciationProposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"removedAssetId","type":"address"},{"indexed":true,"internalType":"address","name":"caller","type":"address"}],"name":"AssetRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"router","type":"address"},{"indexed":true,"internalType":"address","name":"assetId","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"LiquidityAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"router","type":"address"},{"indexed":true,"internalType":"address","name":"assetId","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"}],"name":"LiquidityRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"proposedOwner","type":"address"}],"name":"OwnershipProposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addedRouter","type":"address"},{"indexed":true,"internalType":"address","name":"caller","type":"address"}],"name":"RouterAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"renounced","type":"bool"}],"name":"RouterOwnershipRenounced","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"RouterOwnershipRenunciationProposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"removedRouter","type":"address"},{"indexed":true,"internalType":"address","name":"caller","type":"address"}],"name":"RouterRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"router","type":"address"},{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"components":[{"components":[{"internalType":"address","name":"receivingChainTxManagerAddress","type":"address"},{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"router","type":"address"},{"internalType":"address","name":"initiator","type":"address"},{"internalType":"address","name":"sendingAssetId","type":"address"},{"internalType":"address","name":"receivingAssetId","type":"address"},{"internalType":"address","name":"sendingChainFallback","type":"address"},{"internalType":"address","name":"receivingAddress","type":"address"},{"internalType":"address","name":"callTo","type":"address"},{"internalType":"bytes32","name":"callDataHash","type":"bytes32"},{"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"internalType":"uint256","name":"sendingChainId","type":"uint256"},{"internalType":"uint256","name":"receivingChainId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"preparedBlockNumber","type":"uint256"}],"internalType":"struct ITransactionManager.TransactionData","name":"txData","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes","name":"encodedMeta","type":"bytes"}],"indexed":false,"internalType":"struct ITransactionManager.CancelArgs","name":"args","type":"tuple"},{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"TransactionCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"router","type":"address"},{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"components":[{"components":[{"internalType":"address","name":"receivingChainTxManagerAddress","type":"address"},{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"router","type":"address"},{"internalType":"address","name":"initiator","type":"address"},{"internalType":"address","name":"sendingAssetId","type":"address"},{"internalType":"address","name":"receivingAssetId","type":"address"},{"internalType":"address","name":"sendingChainFallback","type":"address"},{"internalType":"address","name":"receivingAddress","type":"address"},{"internalType":"address","name":"callTo","type":"address"},{"internalType":"bytes32","name":"callDataHash","type":"bytes32"},{"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"internalType":"uint256","name":"sendingChainId","type":"uint256"},{"internalType":"uint256","name":"receivingChainId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"preparedBlockNumber","type":"uint256"}],"internalType":"struct ITransactionManager.TransactionData","name":"txData","type":"tuple"},{"internalType":"uint256","name":"relayerFee","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"bytes","name":"encodedMeta","type":"bytes"}],"indexed":false,"internalType":"struct ITransactionManager.FulfillArgs","name":"args","type":"tuple"},{"indexed":false,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"bool","name":"isContract","type":"bool"},{"indexed":false,"internalType":"bytes","name":"returnData","type":"bytes"},{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"TransactionFulfilled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"router","type":"address"},{"indexed":true,"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"components":[{"internalType":"address","name":"receivingChainTxManagerAddress","type":"address"},{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"router","type":"address"},{"internalType":"address","name":"initiator","type":"address"},{"internalType":"address","name":"sendingAssetId","type":"address"},{"internalType":"address","name":"receivingAssetId","type":"address"},{"internalType":"address","name":"sendingChainFallback","type":"address"},{"internalType":"address","name":"receivingAddress","type":"address"},{"internalType":"address","name":"callTo","type":"address"},{"internalType":"bytes32","name":"callDataHash","type":"bytes32"},{"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"internalType":"uint256","name":"sendingChainId","type":"uint256"},{"internalType":"uint256","name":"receivingChainId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"preparedBlockNumber","type":"uint256"}],"indexed":false,"internalType":"struct ITransactionManager.TransactionData","name":"txData","type":"tuple"},{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"components":[{"components":[{"internalType":"address","name":"receivingChainTxManagerAddress","type":"address"},{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"router","type":"address"},{"internalType":"address","name":"initiator","type":"address"},{"internalType":"address","name":"sendingAssetId","type":"address"},{"internalType":"address","name":"receivingAssetId","type":"address"},{"internalType":"address","name":"sendingChainFallback","type":"address"},{"internalType":"address","name":"receivingAddress","type":"address"},{"internalType":"address","name":"callTo","type":"address"},{"internalType":"uint256","name":"sendingChainId","type":"uint256"},{"internalType":"uint256","name":"receivingChainId","type":"uint256"},{"internalType":"bytes32","name":"callDataHash","type":"bytes32"},{"internalType":"bytes32","name":"transactionId","type":"bytes32"}],"internalType":"struct ITransactionManager.InvariantTransactionData","name":"invariantData","type":"tuple"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"bytes","name":"encryptedCallData","type":"bytes"},{"internalType":"bytes","name":"encodedBid","type":"bytes"},{"internalType":"bytes","name":"bidSignature","type":"bytes"},{"internalType":"bytes","name":"encodedMeta","type":"bytes"}],"indexed":false,"internalType":"struct ITransactionManager.PrepareArgs","name":"args","type":"tuple"}],"name":"TransactionPrepared","type":"event"},{"inputs":[],"name":"MAX_TIMEOUT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_TIMEOUT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptProposedOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"assetId","type":"address"}],"name":"addAssetId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"assetId","type":"address"}],"name":"addLiquidity","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"assetId","type":"address"},{"internalType":"address","name":"router","type":"address"}],"name":"addLiquidityFor","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"router","type":"address"}],"name":"addRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"approvedAssets","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"approvedRouters","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"assetOwnershipTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"receivingChainTxManagerAddress","type":"address"},{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"router","type":"address"},{"internalType":"address","name":"initiator","type":"address"},{"internalType":"address","name":"sendingAssetId","type":"address"},{"internalType":"address","name":"receivingAssetId","type":"address"},{"internalType":"address","name":"sendingChainFallback","type":"address"},{"internalType":"address","name":"receivingAddress","type":"address"},{"internalType":"address","name":"callTo","type":"address"},{"internalType":"bytes32","name":"callDataHash","type":"bytes32"},{"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"internalType":"uint256","name":"sendingChainId","type":"uint256"},{"internalType":"uint256","name":"receivingChainId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"preparedBlockNumber","type":"uint256"}],"internalType":"struct ITransactionManager.TransactionData","name":"txData","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes","name":"encodedMeta","type":"bytes"}],"internalType":"struct ITransactionManager.CancelArgs","name":"args","type":"tuple"}],"name":"cancel","outputs":[{"components":[{"internalType":"address","name":"receivingChainTxManagerAddress","type":"address"},{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"router","type":"address"},{"internalType":"address","name":"initiator","type":"address"},{"internalType":"address","name":"sendingAssetId","type":"address"},{"internalType":"address","name":"receivingAssetId","type":"address"},{"internalType":"address","name":"sendingChainFallback","type":"address"},{"internalType":"address","name":"receivingAddress","type":"address"},{"internalType":"address","name":"callTo","type":"address"},{"internalType":"bytes32","name":"callDataHash","type":"bytes32"},{"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"internalType":"uint256","name":"sendingChainId","type":"uint256"},{"internalType":"uint256","name":"receivingChainId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"preparedBlockNumber","type":"uint256"}],"internalType":"struct ITransactionManager.TransactionData","name":"","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"delay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"receivingChainTxManagerAddress","type":"address"},{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"router","type":"address"},{"internalType":"address","name":"initiator","type":"address"},{"internalType":"address","name":"sendingAssetId","type":"address"},{"internalType":"address","name":"receivingAssetId","type":"address"},{"internalType":"address","name":"sendingChainFallback","type":"address"},{"internalType":"address","name":"receivingAddress","type":"address"},{"internalType":"address","name":"callTo","type":"address"},{"internalType":"bytes32","name":"callDataHash","type":"bytes32"},{"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"internalType":"uint256","name":"sendingChainId","type":"uint256"},{"internalType":"uint256","name":"receivingChainId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"preparedBlockNumber","type":"uint256"}],"internalType":"struct ITransactionManager.TransactionData","name":"txData","type":"tuple"},{"internalType":"uint256","name":"relayerFee","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"bytes","name":"encodedMeta","type":"bytes"}],"internalType":"struct ITransactionManager.FulfillArgs","name":"args","type":"tuple"}],"name":"fulfill","outputs":[{"components":[{"internalType":"address","name":"receivingChainTxManagerAddress","type":"address"},{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"router","type":"address"},{"internalType":"address","name":"initiator","type":"address"},{"internalType":"address","name":"sendingAssetId","type":"address"},{"internalType":"address","name":"receivingAssetId","type":"address"},{"internalType":"address","name":"sendingChainFallback","type":"address"},{"internalType":"address","name":"receivingAddress","type":"address"},{"internalType":"address","name":"callTo","type":"address"},{"internalType":"bytes32","name":"callDataHash","type":"bytes32"},{"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"internalType":"uint256","name":"sendingChainId","type":"uint256"},{"internalType":"uint256","name":"receivingChainId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"preparedBlockNumber","type":"uint256"}],"internalType":"struct ITransactionManager.TransactionData","name":"","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getChainId","outputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStoredChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"interpreter","outputs":[{"internalType":"contract IFulfillInterpreter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isAssetOwnershipRenounced","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isRouterOwnershipRenounced","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"receivingChainTxManagerAddress","type":"address"},{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"router","type":"address"},{"internalType":"address","name":"initiator","type":"address"},{"internalType":"address","name":"sendingAssetId","type":"address"},{"internalType":"address","name":"receivingAssetId","type":"address"},{"internalType":"address","name":"sendingChainFallback","type":"address"},{"internalType":"address","name":"receivingAddress","type":"address"},{"internalType":"address","name":"callTo","type":"address"},{"internalType":"uint256","name":"sendingChainId","type":"uint256"},{"internalType":"uint256","name":"receivingChainId","type":"uint256"},{"internalType":"bytes32","name":"callDataHash","type":"bytes32"},{"internalType":"bytes32","name":"transactionId","type":"bytes32"}],"internalType":"struct ITransactionManager.InvariantTransactionData","name":"invariantData","type":"tuple"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"bytes","name":"encryptedCallData","type":"bytes"},{"internalType":"bytes","name":"encodedBid","type":"bytes"},{"internalType":"bytes","name":"bidSignature","type":"bytes"},{"internalType":"bytes","name":"encodedMeta","type":"bytes"}],"internalType":"struct ITransactionManager.PrepareArgs","name":"args","type":"tuple"}],"name":"prepare","outputs":[{"components":[{"internalType":"address","name":"receivingChainTxManagerAddress","type":"address"},{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"router","type":"address"},{"internalType":"address","name":"initiator","type":"address"},{"internalType":"address","name":"sendingAssetId","type":"address"},{"internalType":"address","name":"receivingAssetId","type":"address"},{"internalType":"address","name":"sendingChainFallback","type":"address"},{"internalType":"address","name":"receivingAddress","type":"address"},{"internalType":"address","name":"callTo","type":"address"},{"internalType":"bytes32","name":"callDataHash","type":"bytes32"},{"internalType":"bytes32","name":"transactionId","type":"bytes32"},{"internalType":"uint256","name":"sendingChainId","type":"uint256"},{"internalType":"uint256","name":"receivingChainId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"preparedBlockNumber","type":"uint256"}],"internalType":"struct ITransactionManager.TransactionData","name":"","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"proposeAssetOwnershipRenunciation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newlyProposed","type":"address"}],"name":"proposeNewOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"proposeRouterOwnershipRenunciation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"proposed","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposedTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"assetId","type":"address"}],"name":"removeAssetId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"assetId","type":"address"},{"internalType":"address payable","name":"recipient","type":"address"}],"name":"removeLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"router","type":"address"}],"name":"removeRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceAssetOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceRouterOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounced","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"routerBalances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"routerOwnershipTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"variantTransactionData","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60c06040523480156200001157600080fd5b5060405162004fd338038062004fd3833981016040819052620000349162000105565b600160005562000044336200009e565b608081905260405130906200005990620000f7565b6001600160a01b039091168152602001604051809103906000f08015801562000086573d6000803e3d6000fd5b5060601b6001600160601b03191660a052506200011e565b600180546001600160a01b038381166001600160a01b0319831681179093556000600381905560405191909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b610bf080620043e383390190565b60006020828403121562000117578081fd5b5051919050565b60805160a05160601c6142876200015c600039600081816102ee015281816127710152612798015260008181610264015261078901526142876000f3fe6080604052600436106102045760003560e01c80638da5cb5b11610118578063c95f9d0e116100a0578063de38eb3a1161006f578063de38eb3a146105db578063e070da09146105f2578063e47602f714610605578063e8be0dfc1461061a578063f31abcc41461062f57600080fd5b8063c95f9d0e14610578578063d1851c921461058b578063d232c220146105a9578063d9459372146105c857600080fd5b8063b1f8100d116100e7578063b1f8100d146104f9578063be91a2ba14610519578063c0c17baf14610539578063c1a049591461054e578063c5b350df1461056357600080fd5b80638da5cb5b1461045e57806397eb00881461047c5780639b151a80146104ac578063b1d2618d146104d957600080fd5b806341258b5c1161019b5780636a41633a1161016a5780636a41633a146103e95780636a42b8f8146103fe5780636ae0b15414610414578063715018a6146104345780638741eac51461044957600080fd5b806341258b5c1461033d578063445b1e4b14610375578063543ad1df146103a55780635e679856146103bc57600080fd5b806334e9393c116101d757806334e9393c146102a75780633855b467146102c75780633a35cf17146102dc5780633cf52ffb1461032857600080fd5b80632004ef451461020957806324ca984e1461023357806332a130c9146102555780633408e47014610292575b600080fd5b34801561021557600080fd5b5061021e61064f565b60405190151581526020015b60405180910390f35b34801561023f57600080fd5b5061025361024e366004613486565b610671565b005b34801561026157600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405190815260200161022a565b34801561029e57600080fd5b50610284610785565b3480156102b357600080fd5b506102536102c2366004613486565b6107b5565b3480156102d357600080fd5b50610253610880565b3480156102e857600080fd5b506103107f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161022a565b34801561033457600080fd5b50600354610284565b34801561034957600080fd5b506102846103583660046134a2565b600860209081526000928352604080842090915290825290205481565b34801561038157600080fd5b5061021e610390366004613486565b60096020526000908152604090205460ff1681565b3480156103b157600080fd5b506102846201518081565b3480156103c857600080fd5b506102846103d73660046135a7565b600b6020526000908152604090205481565b3480156103f557600080fd5b50600754610284565b34801561040a57600080fd5b5062093a80610284565b34801561042057600080fd5b5061025361042f366004613486565b61097b565b34801561044057600080fd5b50610253610a87565b34801561045557600080fd5b50610253610b8e565b34801561046a57600080fd5b506001546001600160a01b0316610310565b34801561048857600080fd5b5061021e610497366004613486565b600a6020526000908152604090205460ff1681565b3480156104b857600080fd5b506104cc6104c73660046135f8565b610bff565b60405161022a9190613fbf565b3480156104e557600080fd5b506102536104f4366004613486565b61108e565b34801561050557600080fd5b50610253610514366004613486565b61115a565b34801561052557600080fd5b506104cc6105343660046135bf565b611234565b34801561054557600080fd5b50610253611597565b34801561055a57600080fd5b50600554610284565b34801561056f57600080fd5b50610253611690565b610253610586366004613786565b61176a565b34801561059757600080fd5b506002546001600160a01b0316610310565b3480156105b557600080fd5b506001546001600160a01b03161561021e565b6104cc6105d6366004613631565b6117a6565b3480156105e757600080fd5b5061028462278d0081565b6102536106003660046137aa565b612104565b34801561061157600080fd5b50610253612141565b34801561062657600080fd5b5061021e6121b2565b34801561063b57600080fd5b5061025361064a3660046137aa565b6121d2565b6001546000906001600160a01b0316158061066c575060045460ff165b905090565b6001546001600160a01b031633146106a45760405162461bcd60e51b815260040161069b90613c3e565b60405180910390fd5b6001600160a01b0381166106e45760405162461bcd60e51b81526020600482015260076024820152662341523a30303160c81b604482015260640161069b565b6001600160a01b03811660009081526009602052604090205460ff16156107375760405162461bcd60e51b815260206004820152600760248201526611a0a91d18199960c91b604482015260640161069b565b6001600160a01b038116600081815260096020526040808220805460ff19166001179055513392917fbc68405e644da2aaf25623ce2199da82c6dfd2e1de102b400eba6a091704d4f491a350565b60007f0000000000000000000000000000000000000000000000000000000000000000806107b05750465b919050565b6001546001600160a01b031633146107df5760405162461bcd60e51b815260040161069b90613c3e565b6001600160a01b0381166000908152600a602052604090205460ff16156108325760405162461bcd60e51b815260206004820152600760248201526611a0a09d18199960c91b604482015260640161069b565b6001600160a01b0381166000818152600a6020526040808220805460ff19166001179055513392917f0bb5715f0f217c2fe9a0c877ea87d474380c641102f3440ee2a4c8b9d979091891a350565b6001546001600160a01b031633146108aa5760405162461bcd60e51b815260040161069b90613c3e565b60065460ff16156108e85760405162461bcd60e51b8152602060048201526008602482015267046a4829e746066760c31b604482015260640161069b565b6000600754116109255760405162461bcd60e51b81526020600482015260086024820152672352414f3a30333760c01b604482015260640161069b565b62093a806007544261093791906141cd565b1161096f5760405162461bcd60e51b815260206004820152600860248201526702352414f3a3033360c41b604482015260640161069b565b6109796001612357565b565b6001546001600160a01b031633146109a55760405162461bcd60e51b815260040161069b90613c3e565b6001600160a01b0381166109e55760405162461bcd60e51b81526020600482015260076024820152662352523a30303160c81b604482015260640161069b565b6001600160a01b03811660009081526009602052604090205460ff161515600114610a3c5760405162461bcd60e51b81526020600482015260076024820152662352523a30333360c81b604482015260640161069b565b6001600160a01b038116600081815260096020526040808220805460ff19169055513392917fbee3e974bb6a6f44f20096ede047c191eef60322e65e4ee4bd3392230a8716d591a350565b6001546001600160a01b03163314610ab15760405162461bcd60e51b815260040161069b90613c3e565b600060035411610aed5760405162461bcd60e51b815260206004820152600760248201526623524f3a30333760c81b604482015260640161069b565b62093a8060035442610aff91906141cd565b11610b365760405162461bcd60e51b8152602060048201526007602482015266023524f3a3033360cc1b604482015260640161069b565b6002546001600160a01b031615610b795760405162461bcd60e51b815260206004820152600760248201526611a9279d18199b60c91b604482015260640161069b565b600254610979906001600160a01b03166123a4565b6001546001600160a01b03163314610bb85760405162461bcd60e51b815260040161069b90613c3e565b60065460ff1615610bf75760405162461bcd60e51b8152602060048201526009602482015268046a0829ea4746066760bb1b604482015260640161069b565b6109796123fd565b610c076133e7565b60026000541415610c2a5760405162461bcd60e51b815260040161069b90613c5f565b60026000908155610c3a83612439565b9050610c566101a08401356101c08501356101e08601356125b7565b6000828152600b602052604090205414610c9b5760405162461bcd60e51b815260206004820152600660248201526523463a30313960d01b604482015260640161069b565b426101c08401351015610cd95760405162461bcd60e51b8152602060048201526006602482015265023463a3032360d41b604482015260640161069b565b6101e0830135610d145760405162461bcd60e51b815260206004820152600660248201526523463a30323160d01b604482015260640161069b565b610120830135610d286102408501856140c9565b604051610d36929190613bb0565b604051809103902014610d745760405162461bcd60e51b815260206004820152600660248201526508d18e8c0c8d60d21b604482015260640161069b565b610d8a6101a08401356101c085013560006125b7565b6000918252600b602052604082205580606081610da5610785565b9050610160860135811415610f1a57610dc46060870160408801613486565b6001600160a01b0316336001600160a01b031614610e0d5760405162461bcd60e51b815260206004820152600660248201526511a31d18189b60d11b604482015260640161069b565b610e1d6040870160208801613486565b6001600160a01b0316610e5b6101408801356102008901356101808a0135610e4860208c018c613486565b610e566102208d018d6140c9565b612605565b6001600160a01b031614610e9a5760405162461bcd60e51b815260206004820152600660248201526511a31d18191960d11b604482015260640161069b565b6101a086013560086000610eb460608a0160408b01613486565b6001600160a01b031681526020810191909152604001600090812090610ee060a08a0160808b01613486565b6001600160a01b03166001600160a01b031681526020019081526020016000206000828254610f0f91906141b5565b90915550610ff99050565b610f2a6040870160208801613486565b6001600160a01b0316610f526101408801356102008901358430610e566102208d018d6140c9565b6001600160a01b031614610f915760405162461bcd60e51b815260206004820152600660248201526511a31d18191960d11b604482015260640161069b565b6101a08601356102008701351115610fd45760405162461bcd60e51b815260206004820152600660248201526523463a30323360d01b604482015260640161069b565b610ff186610200810135610fec6102408301836140c9565b612687565b919550935091505b61014086013561100f6060880160408901613486565b6001600160a01b03166110286040890160208a01613486565b6001600160a01b03167f8e5df24f8b9ac0e3455417a1d7060762388ce3c1d4941aa49dc1b61943031d328988888833604051611068959493929190613d10565b60405180910390a461107f3687900387018761366a565b60016000559695505050505050565b6001546001600160a01b031633146110b85760405162461bcd60e51b815260040161069b90613c3e565b6001600160a01b0381166000908152600a602052604090205460ff16151560011461110f5760405162461bcd60e51b81526020600482015260076024820152662352413a30333360c81b604482015260640161069b565b6001600160a01b0381166000818152600a6020526040808220805460ff19169055513392917f0fa1e4606af435f32f05b3804033d2933e691fab32ee74d2db6fa82d2741f1ea91a350565b6001546001600160a01b031633146111845760405162461bcd60e51b815260040161069b90613c3e565b6002546001600160a01b0382811691161415806111a857506001600160a01b038116155b6111df5760405162461bcd60e51b815260206004820152600860248201526711a827279d18199b60c11b604482015260640161069b565b6001546001600160a01b03828116911614156112285760405162461bcd60e51b8152602060048201526008602482015267046a09c9e746066760c31b604482015260640161069b565b6112318161289f565b50565b61123c6133e7565b6002600054141561125f5760405162461bcd60e51b815260040161069b90613c5f565b6002600090815561126f83612439565b905061128b6101a08401356101c08501356101e08601356125b7565b6000828152600b6020526040902054146112d05760405162461bcd60e51b815260206004820152600660248201526523433a30313960d01b604482015260640161069b565b6101e083013561130b5760405162461bcd60e51b815260206004820152600660248201526523433a30323160d01b604482015260640161069b565b6113216101a08401356101c085013560006125b7565b6000828152600b602052604081209190915561133b610785565b90506101608401358114156113e257426101c0850135106113af576113666060850160408601613486565b6001600160a01b0316336001600160a01b0316146113af5760405162461bcd60e51b815260206004820152600660248201526523433a30323560d01b604482015260640161069b565b6113dd6113c260a0860160808701613486565b6113d260e0870160c08801613486565b6101a08701356128ed565b61150a565b426101c08501351061148f576113fe6040850160208601613486565b6001600160a01b0316336001600160a01b0316148061145a57506114286040850160208601613486565b6001600160a01b031661144f610140860135833061144a6102008a018a6140c9565b612916565b6001600160a01b0316145b61148f5760405162461bcd60e51b815260206004820152600660248201526511a19d18191960d11b604482015260640161069b565b6101a0840135600860006114a96060880160408901613486565b6001600160a01b0316815260208101919091526040016000908120906114d560c0880160a08901613486565b6001600160a01b03166001600160a01b03168152602001908152602001600020600082825461150491906141b5565b90915550505b6101408401356115206060860160408701613486565b6001600160a01b03166115396040870160208801613486565b6001600160a01b03167f56a92405e111173b950d90846413f755ca35bb7631d49a4a564778b21affe2878733604051611573929190613c96565b60405180910390a461158a3685900385018561366a565b6001600055949350505050565b6001546001600160a01b031633146115c15760405162461bcd60e51b815260040161069b90613c3e565b60045460ff16156115ff5760405162461bcd60e51b8152602060048201526008602482015267046a4a49e746066760c31b604482015260640161069b565b60006005541161163c5760405162461bcd60e51b81526020600482015260086024820152672352524f3a30333760c01b604482015260640161069b565b62093a806005544261164e91906141cd565b116116865760405162461bcd60e51b815260206004820152600860248201526702352524f3a3033360c41b604482015260640161069b565b6109796001612982565b6002546001600160a01b031633146116d45760405162461bcd60e51b8152602060048201526007602482015266234f503a30333560c81b604482015260640161069b565b6002546001546001600160a01b03908116911614156117205760405162461bcd60e51b815260206004820152600860248201526704682a09e746066760c31b604482015260640161069b565b62093a806003544261173291906141cd565b11610b795760405162461bcd60e51b815260206004820152600860248201526702341504f3a3033360c41b604482015260640161069b565b6002600054141561178d5760405162461bcd60e51b815260040161069b90613c5f565b600260005561179d8282336129c8565b50506001600055565b6117ae6133e7565b600260005414156117d15760405162461bcd60e51b815260040161069b90613c5f565b600260009081556117e86040840160208501613486565b6001600160a01b031614156118285760405162461bcd60e51b815260206004820152600660248201526523503a30303960d01b604482015260640161069b565b600061183a6060840160408501613486565b6001600160a01b0316141561187a5760405162461bcd60e51b815260206004820152600660248201526523503a30303160d01b604482015260640161069b565b61188261064f565b806118ba57506009600061189c6060850160408601613486565b6001600160a01b0316815260208101919091526040016000205460ff165b6118ef5760405162461bcd60e51b815260206004820152600660248201526523503a30303360d01b604482015260640161069b565b600061190160e0840160c08501613486565b6001600160a01b031614156119415760405162461bcd60e51b8152602060048201526006602482015265023503a3031360d41b604482015260640161069b565b6000611954610100840160e08501613486565b6001600160a01b031614156119945760405162461bcd60e51b815260206004820152600660248201526511a81d18191b60d11b604482015260640161069b565b61012082013561014083013514156119d75760405162461bcd60e51b815260206004820152600660248201526523503a30313160d01b604482015260640161069b565b60006119e1610785565b90506101208301358114806119fa575061014083013581145b611a2f5760405162461bcd60e51b815260206004820152600660248201526511a81d18189960d11b604482015260640161069b565b6000611a40426101c08601356141cd565b905062015180811015611a7e5760405162461bcd60e51b815260206004820152600660248201526523503a30313360d01b604482015260640161069b565b62278d00811115611aba5760405162461bcd60e51b815260206004820152600660248201526508d40e8c0c4d60d21b604482015260640161069b565b50604051600090611acf908590602001613dee565b60408051601f1981840301815291815281516020928301206000818152600b90935291205490915015611b2d5760405162461bcd60e51b815260206004820152600660248201526523503a30313560d01b604482015260640161069b565b6101a0840135610120850135831415611c9057611b506080860160608701613486565b6001600160a01b0316336001600160a01b031614611b995760405162461bcd60e51b815260206004820152600660248201526523503a30333960d01b604482015260640161069b565b6000856101a0013511611bd75760405162461bcd60e51b815260206004820152600660248201526511a81d18181960d11b604482015260640161069b565b611bdf6121b2565b80611c175750600a6000611bf960a0880160808901613486565b6001600160a01b0316815260208101919091526040016000205460ff165b611c4c5760405162461bcd60e51b815260206004820152600660248201526508d40e8c0c0d60d21b604482015260640161069b565b611c6a611c5f60a0870160808801613486565b866101a00135612b9c565b9050611c7c81866101c00135436125b7565b6000838152600b6020526040902055611f29565b6000611ca461012087016101008801613486565b6001600160a01b03161480611ccf5750611ccf611cc961012087016101008801613486565b3b151590565b611d045760405162461bcd60e51b815260206004820152600660248201526523503a30333160d01b604482015260640161069b565b611d0c6121b2565b80611d445750600a6000611d2660c0880160a08901613486565b6001600160a01b0316815260208101919091526040016000205460ff165b611d795760405162461bcd60e51b815260206004820152600660248201526508d40e8c0c0d60d21b604482015260640161069b565b611d896060860160408701613486565b6001600160a01b0316336001600160a01b031614611dd25760405162461bcd60e51b815260206004820152600660248201526511a81d18189b60d11b604482015260640161069b565b3415611e095760405162461bcd60e51b815260206004820152600660248201526523503a30313760d01b604482015260640161069b565b6000600881611e1e6060890160408a01613486565b6001600160a01b031681526020810191909152604001600090812090611e4a60c0890160a08a01613486565b6001600160a01b03166001600160a01b0316815260200190815260200160002054905081811015611ea65760405162461bcd60e51b8152602060048201526006602482015265046a0746062760d31b604482015260640161069b565b611eb682876101c00135436125b7565b6000848152600b6020526040808220929092558383039160089190611ee19060608b01908b01613486565b6001600160a01b031681526020810191909152604001600090812090611f0d60c08a0160a08b01613486565b6001600160a01b03168152602081019190915260400160002055505b60408051610200810190915260009080611f466020890189613486565b6001600160a01b03168152602090810190611f679060408a01908a01613486565b6001600160a01b03168152602001611f856060890160408a01613486565b6001600160a01b03168152602001611fa36080890160608a01613486565b6001600160a01b03168152602001611fc160a0890160808a01613486565b6001600160a01b03168152602001611fdf60c0890160a08a01613486565b6001600160a01b03168152602001611ffd60e0890160c08a01613486565b6001600160a01b0316815260200161201c610100890160e08a01613486565b6001600160a01b0316815260200161203c61012089016101008a01613486565b6001600160a01b031681526020018760000161016001358152602001876000016101800135815260200187600001610120013581526020018760000161014001358152602001838152602001876101c00135815260200143815250905080610140015181604001516001600160a01b031682602001516001600160a01b03167f88fbf1dbc326c404155bad4643bd0ddadd23f0636929c66442f0433208b2c90584338b6040516120ee93929190613fce565b60405180910390a4600160005595945050505050565b600260005414156121275760405162461bcd60e51b815260040161069b90613c5f565b60026000556121378383836129c8565b5050600160005550565b6001546001600160a01b0316331461216b5760405162461bcd60e51b815260040161069b90613c3e565b60045460ff16156121aa5760405162461bcd60e51b8152602060048201526009602482015268046a0a49ea4746066760bb1b604482015260640161069b565b610979612c5d565b6001546000906001600160a01b0316158061066c57505060065460ff1690565b600260005414156121f55760405162461bcd60e51b815260040161069b90613c5f565b60026000556001600160a01b03811661223a5760405162461bcd60e51b815260206004820152600760248201526623524c3a30303760c81b604482015260640161069b565b600083116122745760405162461bcd60e51b815260206004820152600760248201526611a9261d18181960c91b604482015260640161069b565b3360009081526008602090815260408083206001600160a01b0386168452909152902054838110156122d25760405162461bcd60e51b8152602060048201526007602482015266046a498746060760cb1b604482015260640161069b565b3360009081526008602090815260408083206001600160a01b0387168452909152902084820390556123058383866128ed565b604080518581526001600160a01b03848116602083015285169133917f7da12116be8cb7af4b2d9e9b4a2ca2c3a3243ddd6fd3a94411902367b8eed568910160405180910390a3505060016000555050565b6006805460ff191682151590811790915560006007556040519081527f868d89ead22a5d10f456845ac0014901d9af7203e71cf0892d70d9dc262c2fb9906020015b60405180910390a150565b600180546001600160a01b038381166001600160a01b0319831681179093556000600381905560405191909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b4260078190556040519081527fa78fdca214e4619ef34a695316d423f5b0d8274bc919d29733bf8f92ec8cbb7a906020015b60405180910390a1565b604080516101a081019091526000908190806124586020860186613486565b6001600160a01b031681526020018460200160208101906124799190613486565b6001600160a01b031681526020016124976060860160408701613486565b6001600160a01b031681526020016124b56080860160608701613486565b6001600160a01b031681526020016124d360a0860160808701613486565b6001600160a01b031681526020016124f160c0860160a08701613486565b6001600160a01b0316815260200161250f60e0860160c08701613486565b6001600160a01b0316815260200161252e610100860160e08701613486565b6001600160a01b0316815260200161254e61012086016101008701613486565b6001600160a01b031681526020018461016001358152602001846101800135815260200184610120013581526020018461014001358152509050806040516020016125999190613dfd565b60405160208183030381529060405280519060200120915050919050565b604080516060808201835285825260208083018681529284018581528451808301899052935184860152518383015283518084039092018252608090920190925281519101205b9392505050565b6040805160a0810182528781526020808201889052825180840184526007815266199d5b199a5b1b60ca1b8183015282840152606082018790526001600160a01b038616608083015291516000926126799161266391849101613f64565b6040516020818303038152906040528585612c93565b9150505b9695505050505050565b60008060606101a087013586900386156126b5576126b56126ae60c08a0160a08b01613486565b33896128ed565b60006126c96101208a016101008b01613486565b6001600160a01b03161415612725578015612708576127086126f160c08a0160a08b01613486565b6127026101008b0160e08c01613486565b836128ed565b505060408051600080825260208201909252909250829150612895565b600061274761273a60c08b0160a08c01613486565b6001600160a01b03161590565b9050801580156127575750600082115b156127965761279661276f60c08b0160a08c01613486565b7f000000000000000000000000000000000000000000000000000000000000000084612d3a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663cf9a3604826127d15760006127d3565b835b6101408c01356127eb6101208e016101008f01613486565b8d60a00160208101906127fe9190613486565b8e60e00160208101906128119190613486565b888e8e6040518963ffffffff1660e01b81526004016128369796959493929190613bdc565b6000604051808303818588803b15801561284f57600080fd5b505af1158015612863573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f1916820160405261288c91908101906134f4565b94509450945050505b9450945094915050565b42600355600280546001600160a01b0319166001600160a01b0383169081179091556040517f6ab4d119f23076e8ad491bc65ce85f017fb0591dce08755ba8591059cc51737a90600090a250565b6001600160a01b0383161561290c57612907838383612d3a565b505050565b6129078282612d45565b60008060405180608001604052808881526020016040518060400160405280600681526020016518d85b98d95b60d21b8152508152602001878152602001866001600160a01b03168152509050612977816040516020016126639190613f13565b979650505050505050565b6004805460ff191682151590811790915560006005556040519081527f243ebbb2f905234bbf0556bb38e1f7c23b09ffd2e441a16e58b844eb2ab7a39790602001612399565b6001600160a01b038116612a085760405162461bcd60e51b815260206004820152600760248201526623414c3a30303160c81b604482015260640161069b565b60008311612a425760405162461bcd60e51b815260206004820152600760248201526611a0a61d18181960c91b604482015260640161069b565b612a4a61064f565b80612a6d57506001600160a01b03811660009081526009602052604090205460ff165b612aa35760405162461bcd60e51b815260206004820152600760248201526623414c3a30303360c81b604482015260640161069b565b612aab6121b2565b80612ace57506001600160a01b0382166000908152600a602052604090205460ff165b612b045760405162461bcd60e51b815260206004820152600760248201526608d0530e8c0c0d60ca1b604482015260640161069b565b612b0e8284612b9c565b6001600160a01b038083166000908152600860209081526040808320938716835292905290812080549295508592909190612b4a9084906141b5565b9091555050604080518481523360208201526001600160a01b0380851692908416917f4bd28ccd068c4853d24d35f727ef2a3fea11ce55e8d93461e45f785818e1e139910160405180910390a3505050565b6000816001600160a01b038416612beb57823414612be65760405162461bcd60e51b81526020600482015260076024820152662354413a30303560c81b604482015260640161069b565b612c54565b6000612bf685612d53565b90503415612c305760405162461bcd60e51b815260206004820152600760248201526611aa209d18181b60c91b604482015260640161069b565b612c3c85333087612de7565b80612c4686612d53565b612c5091906141cd565b9150505b90505b92915050565b4260058190556040519081527fa52048c5f468d21a62e4644ac4db19bcaa1a20f0cf37d163ba49c7217d35feb89060200161242f565b6000612d32612cf685805190602001206040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612df992505050565b949350505050565b612907838383612e9d565b612d4f8282612f00565b5050565b60006001600160a01b03821615612de0576040516370a0823160e01b81523060048201526001600160a01b038316906370a082319060240160206040518083038186803b158015612da357600080fd5b505afa158015612db7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ddb919061376e565b612c57565b4792915050565b612df384848484613019565b50505050565b6000815160411415612e2d5760208201516040830151606084015160001a612e2386828585613051565b9350505050612c57565b815160401415612e555760208201516040830151612e4c8583836131fa565b92505050612c57565b60405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015260640161069b565b6040516001600160a01b03831660248201526044810182905261290790849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261321a565b80471015612f505760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015260640161069b565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114612f9d576040519150601f19603f3d011682016040523d82523d6000602084013e612fa2565b606091505b50509050806129075760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d61792068617665207265766572746564000000000000606482015260840161069b565b6040516001600160a01b0380851660248301528316604482015260648101829052612df39085906323b872dd60e01b90608401612ec9565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156130ce5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b606482015260840161069b565b8360ff16601b14806130e357508360ff16601c145b61313a5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b606482015260840161069b565b6040805160008082526020820180845288905260ff871692820192909252606081018590526080810184905260019060a0016020604051602081039080840390855afa15801561318e573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166131f15760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015260640161069b565b95945050505050565b60006001600160ff1b03821660ff83901c601b0161267d86828785613051565b600061326f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166132ec9092919063ffffffff16565b805190915015612907578080602001905181019061328d91906134da565b6129075760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161069b565b6060612d32848460008585843b6133455760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161069b565b600080866001600160a01b031685876040516133619190613bc0565b60006040518083038185875af1925050503d806000811461339e576040519150601f19603f3d011682016040523d82523d6000602084013e6133a3565b606091505b5091509150612977828286606083156133bd5750816125fe565b8251156133cd5782518084602001fd5b8160405162461bcd60e51b815260040161069b9190613c2b565b6040805161020081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e081019190915290565b80356107b08161423c565b805180151581146107b057600080fd5b600060208284031215613497578081fd5b8135612c548161423c565b600080604083850312156134b4578081fd5b82356134bf8161423c565b915060208301356134cf8161423c565b809150509250929050565b6000602082840312156134eb578081fd5b6125fe82613476565b600080600060608486031215613508578081fd5b61351184613476565b925061351f60208501613476565b9150604084015167ffffffffffffffff8082111561353b578283fd5b818601915086601f83011261354e578283fd5b81518181111561356057613560614226565b613573601f8201601f191660200161413f565b9150808252876020828501011115613589578384fd5b61359a8160208401602086016141e4565b5080925050509250925092565b6000602082840312156135b8578081fd5b5035919050565b6000602082840312156135d0578081fd5b813567ffffffffffffffff8111156135e6578182fd5b82016102408185031215612c54578182fd5b600060208284031215613609578081fd5b813567ffffffffffffffff81111561361f578182fd5b82016102808185031215612c54578182fd5b600060208284031215613642578081fd5b813567ffffffffffffffff811115613658578182fd5b82016102608185031215612c54578182fd5b6000610200828403121561367c578081fd5b613684614115565b61368d8361346b565b815261369b6020840161346b565b60208201526136ac6040840161346b565b60408201526136bd6060840161346b565b60608201526136ce6080840161346b565b60808201526136df60a0840161346b565b60a08201526136f060c0840161346b565b60c082015261370160e0840161346b565b60e082015261010061371481850161346b565b9082015261012083810135908201526101408084013590820152610160808401359082015261018080840135908201526101a080840135908201526101c080840135908201526101e0928301359281019290925250919050565b60006020828403121561377f578081fd5b5051919050565b60008060408385031215613798578182fd5b8235915060208301356134cf8161423c565b6000806000606084860312156137be578081fd5b8335925060208401356137d08161423c565b915060408401356137e08161423c565b809150509250925092565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6000815180845261382c8160208601602086016141e4565b601f01601f19169290920160200192915050565b61385a8261384d8361346b565b6001600160a01b03169052565b6138666020820161346b565b6001600160a01b031660208301526138806040820161346b565b6001600160a01b0316604083015261389a6060820161346b565b6001600160a01b031660608301526138b46080820161346b565b6001600160a01b031660808301526138ce60a0820161346b565b6001600160a01b031660a08301526138e860c0820161346b565b6001600160a01b031660c083015261390260e0820161346b565b6001600160a01b031660e083015261010061391e82820161346b565b6001600160a01b03169083015261012081810135908301526101408082013590830152610160808201359083015261018090810135910152565b6139658261384d8361346b565b6139716020820161346b565b6001600160a01b0316602083015261398b6040820161346b565b6001600160a01b031660408301526139a56060820161346b565b6001600160a01b031660608301526139bf6080820161346b565b6001600160a01b031660808301526139d960a0820161346b565b6001600160a01b031660a08301526139f360c0820161346b565b6001600160a01b031660c0830152613a0d60e0820161346b565b6001600160a01b031660e0830152610100613a2982820161346b565b6001600160a01b03169083015261012081810135908301526101408082013590830152610160808201359083015261018080820135908301526101a080820135908301526101c080820135908301526101e090810135910152565b80516001600160a01b031682526020810151613aab60208401826001600160a01b03169052565b506040810151613ac660408401826001600160a01b03169052565b506060810151613ae160608401826001600160a01b03169052565b506080810151613afc60808401826001600160a01b03169052565b5060a0810151613b1760a08401826001600160a01b03169052565b5060c0810151613b3260c08401826001600160a01b03169052565b5060e0810151613b4d60e08401826001600160a01b03169052565b50610100818101516001600160a01b03169083015261012080820151908301526101408082015190830152610160808201519083015261018080820151908301526101a080820151908301526101c080820151908301526101e090810151910152565b8183823760009101908152919050565b60008251613bd28184602087016141e4565b9190910192915050565b8781526001600160a01b0387811660208301528681166040830152851660608201526080810184905260c060a08201819052600090613c1e90830184866137eb565b9998505050505050505050565b6020815260006125fe6020830184613814565b602080825260079082015266234f4f3a30323960c81b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60408152613ca76040820184613958565b6000613cb7610200850185614170565b61024084810152613ccd610280850182846137eb565b915050613cde610220860186614170565b848303603f1901610260860152613cf68382846137eb565b935050505060018060a01b03831660208301529392505050565b60a08152613d2160a0820187613958565b6102008601356102a08201526000613d3d610220880188614170565b6102806102c0850152613d55610320850182846137eb565b915050613d66610240890189614170565b609f1980868503016102e0870152613d7f8483856137eb565b9350613d8f6102608c018c614170565b93509150808685030161030087015250613daa8383836137eb565b92505050613dbc602084018815159052565b85151560408401528281036060840152613dd68186613814565b91505061267d60808301846001600160a01b03169052565b6101a08101612c578284613840565b81516001600160a01b031681526101a081016020830151613e2960208401826001600160a01b03169052565b506040830151613e4460408401826001600160a01b03169052565b506060830151613e5f60608401826001600160a01b03169052565b506080830151613e7a60808401826001600160a01b03169052565b5060a0830151613e9560a08401826001600160a01b03169052565b5060c0830151613eb060c08401826001600160a01b03169052565b5060e0830151613ecb60e08401826001600160a01b03169052565b50610100838101516001600160a01b03169083015261012080840151908301526101408084015190830152610160808401519083015261018092830151929091019190915290565b60208152815160208201526000602083015160806040840152613f3960a0840182613814565b6040850151606085810191909152909401516001600160a01b03166080909301929092525090919050565b6020815281516020820152602082015160408201526000604083015160a06060840152613f9460c0840182613814565b6060850151608085810191909152909401516001600160a01b031660a0909301929092525090919050565b6102008101612c578284613a84565b6000610240613fdd8387613a84565b61020060018060a01b03861681850152610220828186015261400183860187613840565b6101a08601356103e08601526101c08601356104008601526140276101e0870187614170565b61026061042088015261403f6104a0880182846137eb565b91505061404e83880188614170565b935061023f19808884030161044089015261406a8386846137eb565b9450614078848a018a614170565b9450925080888603016104608901526140928585856137eb565b94506140a0868a018a614170565b9650935080888603016104808901525050506140bd8284836137eb565b98975050505050505050565b6000808335601e198436030181126140df578283fd5b83018035915067ffffffffffffffff8211156140f9578283fd5b60200191503681900382131561410e57600080fd5b9250929050565b604051610200810167ffffffffffffffff8111828210171561413957614139614226565b60405290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561416857614168614226565b604052919050565b6000808335601e19843603018112614186578283fd5b830160208101925035905067ffffffffffffffff8111156141a657600080fd5b80360383131561410e57600080fd5b600082198211156141c8576141c8614210565b500190565b6000828210156141df576141df614210565b500390565b60005b838110156141ff5781810151838201526020016141e7565b83811115612df35750506000910152565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461123157600080fdfea2646970667358221220a05c87d31e3a6ea060c72e56be8ebb28bec7975311797ac9ae2c0cf4b2d3d5a264736f6c6343000804003360a060405234801561001057600080fd5b50604051610bf0380380610bf083398101604081905261002f91610049565b600160005560601b6001600160601b031916608052610077565b60006020828403121561005a578081fd5b81516001600160a01b0381168114610070578182fd5b9392505050565b60805160601c610b5661009a600039600081816048015260a90152610b566000f3fe6080604052600436106100295760003560e01c806396f32fb81461002e578063cf9a360414610077575b600080fd5b34801561003a57600080fd5b506040516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001681526020015b60405180910390f35b61008a6100853660046108c4565b610099565b60405161006e93929190610a79565b6000806060336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146101065760405162461bcd60e51b8152602060048201526008602482015267234f544d3a30323760c01b60448201526064015b60405180910390fd5b6001600160a01b038816158061012157610121898b8961021b565b600060608b3b158015906101a0578c6001600160a01b031684610145576000610147565b8a5b8a8a6040516101579291906109c1565b60006040518083038185875af1925050503d8060008114610194576040519150601f19603f3d011682016040523d82523d6000602084013e610199565b606091505b5090935091505b826101c0576101b08c8c8c61026b565b836101c0576101c08c8e8c61028f565b8d7f03196b76502b81bbf14393f8b5ed67dff323f1f86667b064820f1fdf293686a18e8e8e8e8e8e898b8a604051610200999897969594939291906109ed565b60405180910390a2919d919c509a5098505050505050505050565b6001600160a01b03831661025b5760405162461bcd60e51b815260206004820152600760248201526608d2504e8c0ccd60ca1b60448201526064016100fd565b6102668383836102da565b505050565b6001600160a01b03831615610285576102668383836103d4565b61026682826103df565b6001600160a01b0383166102cf5760405162461bcd60e51b815260206004820152600760248201526608d1104e8c0ccd60ca1b60448201526064016100fd565b6102668383836103ed565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e9060440160206040518083038186803b15801561032657600080fd5b505afa15801561033a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061035e919061097d565b6103689190610ab8565b6040516001600160a01b0385166024820152604481018290529091506103ce90859063095ea7b360e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261050f565b50505050565b6102668383836105e1565b6103e98282610611565b5050565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e9060440160206040518083038186803b15801561043857600080fd5b505afa15801561044c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610470919061097d565b9050818110156104d45760405162461bcd60e51b815260206004820152602960248201527f5361666545524332303a2064656372656173656420616c6c6f77616e63652062604482015268656c6f77207a65726f60b81b60648201526084016100fd565b6040516001600160a01b0384166024820152828203604482018190529061050890869063095ea7b360e01b90606401610397565b5050505050565b6000610564826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661072a9092919063ffffffff16565b805190915015610266578080602001905181019061058291906108a4565b6102665760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016100fd565b6040516001600160a01b03831660248201526044810182905261026690849063a9059cbb60e01b90606401610397565b804710156106615760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064016100fd565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146106ae576040519150601f19603f3d011682016040523d82523d6000602084013e6106b3565b606091505b50509050806102665760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d6179206861766520726576657274656400000000000060648201526084016100fd565b60606107398484600085610743565b90505b9392505050565b6060824710156107a45760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016100fd565b843b6107f25760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016100fd565b600080866001600160a01b0316858760405161080e91906109d1565b60006040518083038185875af1925050503d806000811461084b576040519150601f19603f3d011682016040523d82523d6000602084013e610850565b606091505b509150915061086082828661086b565b979650505050505050565b6060831561087a57508161073c565b82511561088a5782518084602001fd5b8160405162461bcd60e51b81526004016100fd9190610aa5565b6000602082840312156108b5578081fd5b8151801515811461073c578182fd5b600080600080600080600060c0888a0312156108de578283fd5b8735965060208801356108f081610b08565b9550604088013561090081610b08565b9450606088013561091081610b08565b93506080880135925060a088013567ffffffffffffffff80821115610933578384fd5b818a0191508a601f830112610946578384fd5b813581811115610954578485fd5b8b6020828501011115610965578485fd5b60208301945080935050505092959891949750929550565b60006020828403121561098e578081fd5b5051919050565b600081518084526109ad816020860160208601610adc565b601f01601f19169290920160200192915050565b8183823760009101908152919050565b600082516109e3818460208701610adc565b9190910192915050565b6001600160a01b038a8116825289811660208301528816604082015260608101879052610100608082018190528101859052600061012086888285013781818885010152601f19601f8801168301818482030160a0850152610a5182820188610995565b9250505083151560c0830152610a6b60e083018415159052565b9a9950505050505050505050565b83151581528215156020820152606060408201526000610a9c6060830184610995565b95945050505050565b60208152600061073c6020830184610995565b60008219821115610ad757634e487b7160e01b81526011600452602481fd5b500190565b60005b83811015610af7578181015183820152602001610adf565b838111156103ce5750506000910152565b6001600160a01b0381168114610b1d57600080fd5b5056fea26469706673582212202269da452bba446914352b77d48fb1282f9d93d6579e7d5164e4949a9439643864736f6c63430008040033000000000000000000000000000000000000000000000000000000000000000a
Deployed Bytecode
0x6080604052600436106102045760003560e01c80638da5cb5b11610118578063c95f9d0e116100a0578063de38eb3a1161006f578063de38eb3a146105db578063e070da09146105f2578063e47602f714610605578063e8be0dfc1461061a578063f31abcc41461062f57600080fd5b8063c95f9d0e14610578578063d1851c921461058b578063d232c220146105a9578063d9459372146105c857600080fd5b8063b1f8100d116100e7578063b1f8100d146104f9578063be91a2ba14610519578063c0c17baf14610539578063c1a049591461054e578063c5b350df1461056357600080fd5b80638da5cb5b1461045e57806397eb00881461047c5780639b151a80146104ac578063b1d2618d146104d957600080fd5b806341258b5c1161019b5780636a41633a1161016a5780636a41633a146103e95780636a42b8f8146103fe5780636ae0b15414610414578063715018a6146104345780638741eac51461044957600080fd5b806341258b5c1461033d578063445b1e4b14610375578063543ad1df146103a55780635e679856146103bc57600080fd5b806334e9393c116101d757806334e9393c146102a75780633855b467146102c75780633a35cf17146102dc5780633cf52ffb1461032857600080fd5b80632004ef451461020957806324ca984e1461023357806332a130c9146102555780633408e47014610292575b600080fd5b34801561021557600080fd5b5061021e61064f565b60405190151581526020015b60405180910390f35b34801561023f57600080fd5b5061025361024e366004613486565b610671565b005b34801561026157600080fd5b507f000000000000000000000000000000000000000000000000000000000000000a5b60405190815260200161022a565b34801561029e57600080fd5b50610284610785565b3480156102b357600080fd5b506102536102c2366004613486565b6107b5565b3480156102d357600080fd5b50610253610880565b3480156102e857600080fd5b506103107f0000000000000000000000005b9e4d0dd21f4e071729a9eb522a2366abed149a81565b6040516001600160a01b03909116815260200161022a565b34801561033457600080fd5b50600354610284565b34801561034957600080fd5b506102846103583660046134a2565b600860209081526000928352604080842090915290825290205481565b34801561038157600080fd5b5061021e610390366004613486565b60096020526000908152604090205460ff1681565b3480156103b157600080fd5b506102846201518081565b3480156103c857600080fd5b506102846103d73660046135a7565b600b6020526000908152604090205481565b3480156103f557600080fd5b50600754610284565b34801561040a57600080fd5b5062093a80610284565b34801561042057600080fd5b5061025361042f366004613486565b61097b565b34801561044057600080fd5b50610253610a87565b34801561045557600080fd5b50610253610b8e565b34801561046a57600080fd5b506001546001600160a01b0316610310565b34801561048857600080fd5b5061021e610497366004613486565b600a6020526000908152604090205460ff1681565b3480156104b857600080fd5b506104cc6104c73660046135f8565b610bff565b60405161022a9190613fbf565b3480156104e557600080fd5b506102536104f4366004613486565b61108e565b34801561050557600080fd5b50610253610514366004613486565b61115a565b34801561052557600080fd5b506104cc6105343660046135bf565b611234565b34801561054557600080fd5b50610253611597565b34801561055a57600080fd5b50600554610284565b34801561056f57600080fd5b50610253611690565b610253610586366004613786565b61176a565b34801561059757600080fd5b506002546001600160a01b0316610310565b3480156105b557600080fd5b506001546001600160a01b03161561021e565b6104cc6105d6366004613631565b6117a6565b3480156105e757600080fd5b5061028462278d0081565b6102536106003660046137aa565b612104565b34801561061157600080fd5b50610253612141565b34801561062657600080fd5b5061021e6121b2565b34801561063b57600080fd5b5061025361064a3660046137aa565b6121d2565b6001546000906001600160a01b0316158061066c575060045460ff165b905090565b6001546001600160a01b031633146106a45760405162461bcd60e51b815260040161069b90613c3e565b60405180910390fd5b6001600160a01b0381166106e45760405162461bcd60e51b81526020600482015260076024820152662341523a30303160c81b604482015260640161069b565b6001600160a01b03811660009081526009602052604090205460ff16156107375760405162461bcd60e51b815260206004820152600760248201526611a0a91d18199960c91b604482015260640161069b565b6001600160a01b038116600081815260096020526040808220805460ff19166001179055513392917fbc68405e644da2aaf25623ce2199da82c6dfd2e1de102b400eba6a091704d4f491a350565b60007f000000000000000000000000000000000000000000000000000000000000000a806107b05750465b919050565b6001546001600160a01b031633146107df5760405162461bcd60e51b815260040161069b90613c3e565b6001600160a01b0381166000908152600a602052604090205460ff16156108325760405162461bcd60e51b815260206004820152600760248201526611a0a09d18199960c91b604482015260640161069b565b6001600160a01b0381166000818152600a6020526040808220805460ff19166001179055513392917f0bb5715f0f217c2fe9a0c877ea87d474380c641102f3440ee2a4c8b9d979091891a350565b6001546001600160a01b031633146108aa5760405162461bcd60e51b815260040161069b90613c3e565b60065460ff16156108e85760405162461bcd60e51b8152602060048201526008602482015267046a4829e746066760c31b604482015260640161069b565b6000600754116109255760405162461bcd60e51b81526020600482015260086024820152672352414f3a30333760c01b604482015260640161069b565b62093a806007544261093791906141cd565b1161096f5760405162461bcd60e51b815260206004820152600860248201526702352414f3a3033360c41b604482015260640161069b565b6109796001612357565b565b6001546001600160a01b031633146109a55760405162461bcd60e51b815260040161069b90613c3e565b6001600160a01b0381166109e55760405162461bcd60e51b81526020600482015260076024820152662352523a30303160c81b604482015260640161069b565b6001600160a01b03811660009081526009602052604090205460ff161515600114610a3c5760405162461bcd60e51b81526020600482015260076024820152662352523a30333360c81b604482015260640161069b565b6001600160a01b038116600081815260096020526040808220805460ff19169055513392917fbee3e974bb6a6f44f20096ede047c191eef60322e65e4ee4bd3392230a8716d591a350565b6001546001600160a01b03163314610ab15760405162461bcd60e51b815260040161069b90613c3e565b600060035411610aed5760405162461bcd60e51b815260206004820152600760248201526623524f3a30333760c81b604482015260640161069b565b62093a8060035442610aff91906141cd565b11610b365760405162461bcd60e51b8152602060048201526007602482015266023524f3a3033360cc1b604482015260640161069b565b6002546001600160a01b031615610b795760405162461bcd60e51b815260206004820152600760248201526611a9279d18199b60c91b604482015260640161069b565b600254610979906001600160a01b03166123a4565b6001546001600160a01b03163314610bb85760405162461bcd60e51b815260040161069b90613c3e565b60065460ff1615610bf75760405162461bcd60e51b8152602060048201526009602482015268046a0829ea4746066760bb1b604482015260640161069b565b6109796123fd565b610c076133e7565b60026000541415610c2a5760405162461bcd60e51b815260040161069b90613c5f565b60026000908155610c3a83612439565b9050610c566101a08401356101c08501356101e08601356125b7565b6000828152600b602052604090205414610c9b5760405162461bcd60e51b815260206004820152600660248201526523463a30313960d01b604482015260640161069b565b426101c08401351015610cd95760405162461bcd60e51b8152602060048201526006602482015265023463a3032360d41b604482015260640161069b565b6101e0830135610d145760405162461bcd60e51b815260206004820152600660248201526523463a30323160d01b604482015260640161069b565b610120830135610d286102408501856140c9565b604051610d36929190613bb0565b604051809103902014610d745760405162461bcd60e51b815260206004820152600660248201526508d18e8c0c8d60d21b604482015260640161069b565b610d8a6101a08401356101c085013560006125b7565b6000918252600b602052604082205580606081610da5610785565b9050610160860135811415610f1a57610dc46060870160408801613486565b6001600160a01b0316336001600160a01b031614610e0d5760405162461bcd60e51b815260206004820152600660248201526511a31d18189b60d11b604482015260640161069b565b610e1d6040870160208801613486565b6001600160a01b0316610e5b6101408801356102008901356101808a0135610e4860208c018c613486565b610e566102208d018d6140c9565b612605565b6001600160a01b031614610e9a5760405162461bcd60e51b815260206004820152600660248201526511a31d18191960d11b604482015260640161069b565b6101a086013560086000610eb460608a0160408b01613486565b6001600160a01b031681526020810191909152604001600090812090610ee060a08a0160808b01613486565b6001600160a01b03166001600160a01b031681526020019081526020016000206000828254610f0f91906141b5565b90915550610ff99050565b610f2a6040870160208801613486565b6001600160a01b0316610f526101408801356102008901358430610e566102208d018d6140c9565b6001600160a01b031614610f915760405162461bcd60e51b815260206004820152600660248201526511a31d18191960d11b604482015260640161069b565b6101a08601356102008701351115610fd45760405162461bcd60e51b815260206004820152600660248201526523463a30323360d01b604482015260640161069b565b610ff186610200810135610fec6102408301836140c9565b612687565b919550935091505b61014086013561100f6060880160408901613486565b6001600160a01b03166110286040890160208a01613486565b6001600160a01b03167f8e5df24f8b9ac0e3455417a1d7060762388ce3c1d4941aa49dc1b61943031d328988888833604051611068959493929190613d10565b60405180910390a461107f3687900387018761366a565b60016000559695505050505050565b6001546001600160a01b031633146110b85760405162461bcd60e51b815260040161069b90613c3e565b6001600160a01b0381166000908152600a602052604090205460ff16151560011461110f5760405162461bcd60e51b81526020600482015260076024820152662352413a30333360c81b604482015260640161069b565b6001600160a01b0381166000818152600a6020526040808220805460ff19169055513392917f0fa1e4606af435f32f05b3804033d2933e691fab32ee74d2db6fa82d2741f1ea91a350565b6001546001600160a01b031633146111845760405162461bcd60e51b815260040161069b90613c3e565b6002546001600160a01b0382811691161415806111a857506001600160a01b038116155b6111df5760405162461bcd60e51b815260206004820152600860248201526711a827279d18199b60c11b604482015260640161069b565b6001546001600160a01b03828116911614156112285760405162461bcd60e51b8152602060048201526008602482015267046a09c9e746066760c31b604482015260640161069b565b6112318161289f565b50565b61123c6133e7565b6002600054141561125f5760405162461bcd60e51b815260040161069b90613c5f565b6002600090815561126f83612439565b905061128b6101a08401356101c08501356101e08601356125b7565b6000828152600b6020526040902054146112d05760405162461bcd60e51b815260206004820152600660248201526523433a30313960d01b604482015260640161069b565b6101e083013561130b5760405162461bcd60e51b815260206004820152600660248201526523433a30323160d01b604482015260640161069b565b6113216101a08401356101c085013560006125b7565b6000828152600b602052604081209190915561133b610785565b90506101608401358114156113e257426101c0850135106113af576113666060850160408601613486565b6001600160a01b0316336001600160a01b0316146113af5760405162461bcd60e51b815260206004820152600660248201526523433a30323560d01b604482015260640161069b565b6113dd6113c260a0860160808701613486565b6113d260e0870160c08801613486565b6101a08701356128ed565b61150a565b426101c08501351061148f576113fe6040850160208601613486565b6001600160a01b0316336001600160a01b0316148061145a57506114286040850160208601613486565b6001600160a01b031661144f610140860135833061144a6102008a018a6140c9565b612916565b6001600160a01b0316145b61148f5760405162461bcd60e51b815260206004820152600660248201526511a19d18191960d11b604482015260640161069b565b6101a0840135600860006114a96060880160408901613486565b6001600160a01b0316815260208101919091526040016000908120906114d560c0880160a08901613486565b6001600160a01b03166001600160a01b03168152602001908152602001600020600082825461150491906141b5565b90915550505b6101408401356115206060860160408701613486565b6001600160a01b03166115396040870160208801613486565b6001600160a01b03167f56a92405e111173b950d90846413f755ca35bb7631d49a4a564778b21affe2878733604051611573929190613c96565b60405180910390a461158a3685900385018561366a565b6001600055949350505050565b6001546001600160a01b031633146115c15760405162461bcd60e51b815260040161069b90613c3e565b60045460ff16156115ff5760405162461bcd60e51b8152602060048201526008602482015267046a4a49e746066760c31b604482015260640161069b565b60006005541161163c5760405162461bcd60e51b81526020600482015260086024820152672352524f3a30333760c01b604482015260640161069b565b62093a806005544261164e91906141cd565b116116865760405162461bcd60e51b815260206004820152600860248201526702352524f3a3033360c41b604482015260640161069b565b6109796001612982565b6002546001600160a01b031633146116d45760405162461bcd60e51b8152602060048201526007602482015266234f503a30333560c81b604482015260640161069b565b6002546001546001600160a01b03908116911614156117205760405162461bcd60e51b815260206004820152600860248201526704682a09e746066760c31b604482015260640161069b565b62093a806003544261173291906141cd565b11610b795760405162461bcd60e51b815260206004820152600860248201526702341504f3a3033360c41b604482015260640161069b565b6002600054141561178d5760405162461bcd60e51b815260040161069b90613c5f565b600260005561179d8282336129c8565b50506001600055565b6117ae6133e7565b600260005414156117d15760405162461bcd60e51b815260040161069b90613c5f565b600260009081556117e86040840160208501613486565b6001600160a01b031614156118285760405162461bcd60e51b815260206004820152600660248201526523503a30303960d01b604482015260640161069b565b600061183a6060840160408501613486565b6001600160a01b0316141561187a5760405162461bcd60e51b815260206004820152600660248201526523503a30303160d01b604482015260640161069b565b61188261064f565b806118ba57506009600061189c6060850160408601613486565b6001600160a01b0316815260208101919091526040016000205460ff165b6118ef5760405162461bcd60e51b815260206004820152600660248201526523503a30303360d01b604482015260640161069b565b600061190160e0840160c08501613486565b6001600160a01b031614156119415760405162461bcd60e51b8152602060048201526006602482015265023503a3031360d41b604482015260640161069b565b6000611954610100840160e08501613486565b6001600160a01b031614156119945760405162461bcd60e51b815260206004820152600660248201526511a81d18191b60d11b604482015260640161069b565b61012082013561014083013514156119d75760405162461bcd60e51b815260206004820152600660248201526523503a30313160d01b604482015260640161069b565b60006119e1610785565b90506101208301358114806119fa575061014083013581145b611a2f5760405162461bcd60e51b815260206004820152600660248201526511a81d18189960d11b604482015260640161069b565b6000611a40426101c08601356141cd565b905062015180811015611a7e5760405162461bcd60e51b815260206004820152600660248201526523503a30313360d01b604482015260640161069b565b62278d00811115611aba5760405162461bcd60e51b815260206004820152600660248201526508d40e8c0c4d60d21b604482015260640161069b565b50604051600090611acf908590602001613dee565b60408051601f1981840301815291815281516020928301206000818152600b90935291205490915015611b2d5760405162461bcd60e51b815260206004820152600660248201526523503a30313560d01b604482015260640161069b565b6101a0840135610120850135831415611c9057611b506080860160608701613486565b6001600160a01b0316336001600160a01b031614611b995760405162461bcd60e51b815260206004820152600660248201526523503a30333960d01b604482015260640161069b565b6000856101a0013511611bd75760405162461bcd60e51b815260206004820152600660248201526511a81d18181960d11b604482015260640161069b565b611bdf6121b2565b80611c175750600a6000611bf960a0880160808901613486565b6001600160a01b0316815260208101919091526040016000205460ff165b611c4c5760405162461bcd60e51b815260206004820152600660248201526508d40e8c0c0d60d21b604482015260640161069b565b611c6a611c5f60a0870160808801613486565b866101a00135612b9c565b9050611c7c81866101c00135436125b7565b6000838152600b6020526040902055611f29565b6000611ca461012087016101008801613486565b6001600160a01b03161480611ccf5750611ccf611cc961012087016101008801613486565b3b151590565b611d045760405162461bcd60e51b815260206004820152600660248201526523503a30333160d01b604482015260640161069b565b611d0c6121b2565b80611d445750600a6000611d2660c0880160a08901613486565b6001600160a01b0316815260208101919091526040016000205460ff165b611d795760405162461bcd60e51b815260206004820152600660248201526508d40e8c0c0d60d21b604482015260640161069b565b611d896060860160408701613486565b6001600160a01b0316336001600160a01b031614611dd25760405162461bcd60e51b815260206004820152600660248201526511a81d18189b60d11b604482015260640161069b565b3415611e095760405162461bcd60e51b815260206004820152600660248201526523503a30313760d01b604482015260640161069b565b6000600881611e1e6060890160408a01613486565b6001600160a01b031681526020810191909152604001600090812090611e4a60c0890160a08a01613486565b6001600160a01b03166001600160a01b0316815260200190815260200160002054905081811015611ea65760405162461bcd60e51b8152602060048201526006602482015265046a0746062760d31b604482015260640161069b565b611eb682876101c00135436125b7565b6000848152600b6020526040808220929092558383039160089190611ee19060608b01908b01613486565b6001600160a01b031681526020810191909152604001600090812090611f0d60c08a0160a08b01613486565b6001600160a01b03168152602081019190915260400160002055505b60408051610200810190915260009080611f466020890189613486565b6001600160a01b03168152602090810190611f679060408a01908a01613486565b6001600160a01b03168152602001611f856060890160408a01613486565b6001600160a01b03168152602001611fa36080890160608a01613486565b6001600160a01b03168152602001611fc160a0890160808a01613486565b6001600160a01b03168152602001611fdf60c0890160a08a01613486565b6001600160a01b03168152602001611ffd60e0890160c08a01613486565b6001600160a01b0316815260200161201c610100890160e08a01613486565b6001600160a01b0316815260200161203c61012089016101008a01613486565b6001600160a01b031681526020018760000161016001358152602001876000016101800135815260200187600001610120013581526020018760000161014001358152602001838152602001876101c00135815260200143815250905080610140015181604001516001600160a01b031682602001516001600160a01b03167f88fbf1dbc326c404155bad4643bd0ddadd23f0636929c66442f0433208b2c90584338b6040516120ee93929190613fce565b60405180910390a4600160005595945050505050565b600260005414156121275760405162461bcd60e51b815260040161069b90613c5f565b60026000556121378383836129c8565b5050600160005550565b6001546001600160a01b0316331461216b5760405162461bcd60e51b815260040161069b90613c3e565b60045460ff16156121aa5760405162461bcd60e51b8152602060048201526009602482015268046a0a49ea4746066760bb1b604482015260640161069b565b610979612c5d565b6001546000906001600160a01b0316158061066c57505060065460ff1690565b600260005414156121f55760405162461bcd60e51b815260040161069b90613c5f565b60026000556001600160a01b03811661223a5760405162461bcd60e51b815260206004820152600760248201526623524c3a30303760c81b604482015260640161069b565b600083116122745760405162461bcd60e51b815260206004820152600760248201526611a9261d18181960c91b604482015260640161069b565b3360009081526008602090815260408083206001600160a01b0386168452909152902054838110156122d25760405162461bcd60e51b8152602060048201526007602482015266046a498746060760cb1b604482015260640161069b565b3360009081526008602090815260408083206001600160a01b0387168452909152902084820390556123058383866128ed565b604080518581526001600160a01b03848116602083015285169133917f7da12116be8cb7af4b2d9e9b4a2ca2c3a3243ddd6fd3a94411902367b8eed568910160405180910390a3505060016000555050565b6006805460ff191682151590811790915560006007556040519081527f868d89ead22a5d10f456845ac0014901d9af7203e71cf0892d70d9dc262c2fb9906020015b60405180910390a150565b600180546001600160a01b038381166001600160a01b0319831681179093556000600381905560405191909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b4260078190556040519081527fa78fdca214e4619ef34a695316d423f5b0d8274bc919d29733bf8f92ec8cbb7a906020015b60405180910390a1565b604080516101a081019091526000908190806124586020860186613486565b6001600160a01b031681526020018460200160208101906124799190613486565b6001600160a01b031681526020016124976060860160408701613486565b6001600160a01b031681526020016124b56080860160608701613486565b6001600160a01b031681526020016124d360a0860160808701613486565b6001600160a01b031681526020016124f160c0860160a08701613486565b6001600160a01b0316815260200161250f60e0860160c08701613486565b6001600160a01b0316815260200161252e610100860160e08701613486565b6001600160a01b0316815260200161254e61012086016101008701613486565b6001600160a01b031681526020018461016001358152602001846101800135815260200184610120013581526020018461014001358152509050806040516020016125999190613dfd565b60405160208183030381529060405280519060200120915050919050565b604080516060808201835285825260208083018681529284018581528451808301899052935184860152518383015283518084039092018252608090920190925281519101205b9392505050565b6040805160a0810182528781526020808201889052825180840184526007815266199d5b199a5b1b60ca1b8183015282840152606082018790526001600160a01b038616608083015291516000926126799161266391849101613f64565b6040516020818303038152906040528585612c93565b9150505b9695505050505050565b60008060606101a087013586900386156126b5576126b56126ae60c08a0160a08b01613486565b33896128ed565b60006126c96101208a016101008b01613486565b6001600160a01b03161415612725578015612708576127086126f160c08a0160a08b01613486565b6127026101008b0160e08c01613486565b836128ed565b505060408051600080825260208201909252909250829150612895565b600061274761273a60c08b0160a08c01613486565b6001600160a01b03161590565b9050801580156127575750600082115b156127965761279661276f60c08b0160a08c01613486565b7f0000000000000000000000005b9e4d0dd21f4e071729a9eb522a2366abed149a84612d3a565b7f0000000000000000000000005b9e4d0dd21f4e071729a9eb522a2366abed149a6001600160a01b031663cf9a3604826127d15760006127d3565b835b6101408c01356127eb6101208e016101008f01613486565b8d60a00160208101906127fe9190613486565b8e60e00160208101906128119190613486565b888e8e6040518963ffffffff1660e01b81526004016128369796959493929190613bdc565b6000604051808303818588803b15801561284f57600080fd5b505af1158015612863573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f1916820160405261288c91908101906134f4565b94509450945050505b9450945094915050565b42600355600280546001600160a01b0319166001600160a01b0383169081179091556040517f6ab4d119f23076e8ad491bc65ce85f017fb0591dce08755ba8591059cc51737a90600090a250565b6001600160a01b0383161561290c57612907838383612d3a565b505050565b6129078282612d45565b60008060405180608001604052808881526020016040518060400160405280600681526020016518d85b98d95b60d21b8152508152602001878152602001866001600160a01b03168152509050612977816040516020016126639190613f13565b979650505050505050565b6004805460ff191682151590811790915560006005556040519081527f243ebbb2f905234bbf0556bb38e1f7c23b09ffd2e441a16e58b844eb2ab7a39790602001612399565b6001600160a01b038116612a085760405162461bcd60e51b815260206004820152600760248201526623414c3a30303160c81b604482015260640161069b565b60008311612a425760405162461bcd60e51b815260206004820152600760248201526611a0a61d18181960c91b604482015260640161069b565b612a4a61064f565b80612a6d57506001600160a01b03811660009081526009602052604090205460ff165b612aa35760405162461bcd60e51b815260206004820152600760248201526623414c3a30303360c81b604482015260640161069b565b612aab6121b2565b80612ace57506001600160a01b0382166000908152600a602052604090205460ff165b612b045760405162461bcd60e51b815260206004820152600760248201526608d0530e8c0c0d60ca1b604482015260640161069b565b612b0e8284612b9c565b6001600160a01b038083166000908152600860209081526040808320938716835292905290812080549295508592909190612b4a9084906141b5565b9091555050604080518481523360208201526001600160a01b0380851692908416917f4bd28ccd068c4853d24d35f727ef2a3fea11ce55e8d93461e45f785818e1e139910160405180910390a3505050565b6000816001600160a01b038416612beb57823414612be65760405162461bcd60e51b81526020600482015260076024820152662354413a30303560c81b604482015260640161069b565b612c54565b6000612bf685612d53565b90503415612c305760405162461bcd60e51b815260206004820152600760248201526611aa209d18181b60c91b604482015260640161069b565b612c3c85333087612de7565b80612c4686612d53565b612c5091906141cd565b9150505b90505b92915050565b4260058190556040519081527fa52048c5f468d21a62e4644ac4db19bcaa1a20f0cf37d163ba49c7217d35feb89060200161242f565b6000612d32612cf685805190602001206040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612df992505050565b949350505050565b612907838383612e9d565b612d4f8282612f00565b5050565b60006001600160a01b03821615612de0576040516370a0823160e01b81523060048201526001600160a01b038316906370a082319060240160206040518083038186803b158015612da357600080fd5b505afa158015612db7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ddb919061376e565b612c57565b4792915050565b612df384848484613019565b50505050565b6000815160411415612e2d5760208201516040830151606084015160001a612e2386828585613051565b9350505050612c57565b815160401415612e555760208201516040830151612e4c8583836131fa565b92505050612c57565b60405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015260640161069b565b6040516001600160a01b03831660248201526044810182905261290790849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261321a565b80471015612f505760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015260640161069b565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114612f9d576040519150601f19603f3d011682016040523d82523d6000602084013e612fa2565b606091505b50509050806129075760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d61792068617665207265766572746564000000000000606482015260840161069b565b6040516001600160a01b0380851660248301528316604482015260648101829052612df39085906323b872dd60e01b90608401612ec9565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156130ce5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b606482015260840161069b565b8360ff16601b14806130e357508360ff16601c145b61313a5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b606482015260840161069b565b6040805160008082526020820180845288905260ff871692820192909252606081018590526080810184905260019060a0016020604051602081039080840390855afa15801561318e573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166131f15760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015260640161069b565b95945050505050565b60006001600160ff1b03821660ff83901c601b0161267d86828785613051565b600061326f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166132ec9092919063ffffffff16565b805190915015612907578080602001905181019061328d91906134da565b6129075760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161069b565b6060612d32848460008585843b6133455760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161069b565b600080866001600160a01b031685876040516133619190613bc0565b60006040518083038185875af1925050503d806000811461339e576040519150601f19603f3d011682016040523d82523d6000602084013e6133a3565b606091505b5091509150612977828286606083156133bd5750816125fe565b8251156133cd5782518084602001fd5b8160405162461bcd60e51b815260040161069b9190613c2b565b6040805161020081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e081019190915290565b80356107b08161423c565b805180151581146107b057600080fd5b600060208284031215613497578081fd5b8135612c548161423c565b600080604083850312156134b4578081fd5b82356134bf8161423c565b915060208301356134cf8161423c565b809150509250929050565b6000602082840312156134eb578081fd5b6125fe82613476565b600080600060608486031215613508578081fd5b61351184613476565b925061351f60208501613476565b9150604084015167ffffffffffffffff8082111561353b578283fd5b818601915086601f83011261354e578283fd5b81518181111561356057613560614226565b613573601f8201601f191660200161413f565b9150808252876020828501011115613589578384fd5b61359a8160208401602086016141e4565b5080925050509250925092565b6000602082840312156135b8578081fd5b5035919050565b6000602082840312156135d0578081fd5b813567ffffffffffffffff8111156135e6578182fd5b82016102408185031215612c54578182fd5b600060208284031215613609578081fd5b813567ffffffffffffffff81111561361f578182fd5b82016102808185031215612c54578182fd5b600060208284031215613642578081fd5b813567ffffffffffffffff811115613658578182fd5b82016102608185031215612c54578182fd5b6000610200828403121561367c578081fd5b613684614115565b61368d8361346b565b815261369b6020840161346b565b60208201526136ac6040840161346b565b60408201526136bd6060840161346b565b60608201526136ce6080840161346b565b60808201526136df60a0840161346b565b60a08201526136f060c0840161346b565b60c082015261370160e0840161346b565b60e082015261010061371481850161346b565b9082015261012083810135908201526101408084013590820152610160808401359082015261018080840135908201526101a080840135908201526101c080840135908201526101e0928301359281019290925250919050565b60006020828403121561377f578081fd5b5051919050565b60008060408385031215613798578182fd5b8235915060208301356134cf8161423c565b6000806000606084860312156137be578081fd5b8335925060208401356137d08161423c565b915060408401356137e08161423c565b809150509250925092565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6000815180845261382c8160208601602086016141e4565b601f01601f19169290920160200192915050565b61385a8261384d8361346b565b6001600160a01b03169052565b6138666020820161346b565b6001600160a01b031660208301526138806040820161346b565b6001600160a01b0316604083015261389a6060820161346b565b6001600160a01b031660608301526138b46080820161346b565b6001600160a01b031660808301526138ce60a0820161346b565b6001600160a01b031660a08301526138e860c0820161346b565b6001600160a01b031660c083015261390260e0820161346b565b6001600160a01b031660e083015261010061391e82820161346b565b6001600160a01b03169083015261012081810135908301526101408082013590830152610160808201359083015261018090810135910152565b6139658261384d8361346b565b6139716020820161346b565b6001600160a01b0316602083015261398b6040820161346b565b6001600160a01b031660408301526139a56060820161346b565b6001600160a01b031660608301526139bf6080820161346b565b6001600160a01b031660808301526139d960a0820161346b565b6001600160a01b031660a08301526139f360c0820161346b565b6001600160a01b031660c0830152613a0d60e0820161346b565b6001600160a01b031660e0830152610100613a2982820161346b565b6001600160a01b03169083015261012081810135908301526101408082013590830152610160808201359083015261018080820135908301526101a080820135908301526101c080820135908301526101e090810135910152565b80516001600160a01b031682526020810151613aab60208401826001600160a01b03169052565b506040810151613ac660408401826001600160a01b03169052565b506060810151613ae160608401826001600160a01b03169052565b506080810151613afc60808401826001600160a01b03169052565b5060a0810151613b1760a08401826001600160a01b03169052565b5060c0810151613b3260c08401826001600160a01b03169052565b5060e0810151613b4d60e08401826001600160a01b03169052565b50610100818101516001600160a01b03169083015261012080820151908301526101408082015190830152610160808201519083015261018080820151908301526101a080820151908301526101c080820151908301526101e090810151910152565b8183823760009101908152919050565b60008251613bd28184602087016141e4565b9190910192915050565b8781526001600160a01b0387811660208301528681166040830152851660608201526080810184905260c060a08201819052600090613c1e90830184866137eb565b9998505050505050505050565b6020815260006125fe6020830184613814565b602080825260079082015266234f4f3a30323960c81b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60408152613ca76040820184613958565b6000613cb7610200850185614170565b61024084810152613ccd610280850182846137eb565b915050613cde610220860186614170565b848303603f1901610260860152613cf68382846137eb565b935050505060018060a01b03831660208301529392505050565b60a08152613d2160a0820187613958565b6102008601356102a08201526000613d3d610220880188614170565b6102806102c0850152613d55610320850182846137eb565b915050613d66610240890189614170565b609f1980868503016102e0870152613d7f8483856137eb565b9350613d8f6102608c018c614170565b93509150808685030161030087015250613daa8383836137eb565b92505050613dbc602084018815159052565b85151560408401528281036060840152613dd68186613814565b91505061267d60808301846001600160a01b03169052565b6101a08101612c578284613840565b81516001600160a01b031681526101a081016020830151613e2960208401826001600160a01b03169052565b506040830151613e4460408401826001600160a01b03169052565b506060830151613e5f60608401826001600160a01b03169052565b506080830151613e7a60808401826001600160a01b03169052565b5060a0830151613e9560a08401826001600160a01b03169052565b5060c0830151613eb060c08401826001600160a01b03169052565b5060e0830151613ecb60e08401826001600160a01b03169052565b50610100838101516001600160a01b03169083015261012080840151908301526101408084015190830152610160808401519083015261018092830151929091019190915290565b60208152815160208201526000602083015160806040840152613f3960a0840182613814565b6040850151606085810191909152909401516001600160a01b03166080909301929092525090919050565b6020815281516020820152602082015160408201526000604083015160a06060840152613f9460c0840182613814565b6060850151608085810191909152909401516001600160a01b031660a0909301929092525090919050565b6102008101612c578284613a84565b6000610240613fdd8387613a84565b61020060018060a01b03861681850152610220828186015261400183860187613840565b6101a08601356103e08601526101c08601356104008601526140276101e0870187614170565b61026061042088015261403f6104a0880182846137eb565b91505061404e83880188614170565b935061023f19808884030161044089015261406a8386846137eb565b9450614078848a018a614170565b9450925080888603016104608901526140928585856137eb565b94506140a0868a018a614170565b9650935080888603016104808901525050506140bd8284836137eb565b98975050505050505050565b6000808335601e198436030181126140df578283fd5b83018035915067ffffffffffffffff8211156140f9578283fd5b60200191503681900382131561410e57600080fd5b9250929050565b604051610200810167ffffffffffffffff8111828210171561413957614139614226565b60405290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561416857614168614226565b604052919050565b6000808335601e19843603018112614186578283fd5b830160208101925035905067ffffffffffffffff8111156141a657600080fd5b80360383131561410e57600080fd5b600082198211156141c8576141c8614210565b500190565b6000828210156141df576141df614210565b500390565b60005b838110156141ff5781810151838201526020016141e7565b83811115612df35750506000910152565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461123157600080fdfea2646970667358221220a05c87d31e3a6ea060c72e56be8ebb28bec7975311797ac9ae2c0cf4b2d3d5a264736f6c63430008040033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000000000000000000000000000000a
-----Decoded View---------------
Arg [0] : _chainId (uint256): 10
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000000000000000000000000000000000000000000a
Deployed Bytecode Sourcemap
92153:31789:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;78000:134;;;;;;;;;;;;;:::i;:::-;;;14348:14:1;;14341:22;14323:41;;14311:2;14296:18;78000:134:0;;;;;;;;94384:372;;;;;;;;;;-1:-1:-1;94384:372:0;;;;;:::i;:::-;;:::i;:::-;;94160:96;;;;;;;;;;-1:-1:-1;94243:7:0;94160:96;;;14521:25:1;;;14509:2;14494:18;94160:96:0;14476:76:1;93794:273:0;;;;;;;;;;;;;:::i;95424:293::-;;;;;;;;;;-1:-1:-1;95424:293:0;;;;;:::i;:::-;;:::i;79963:528::-;;;;;;;;;;;;;:::i;93479:48::-;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;13480:32:1;;;13462:51;;13450:2;13435:18;93479:48:0;13417:102:1;76764:114:0;;;;;;;;;;-1:-1:-1;76845:27:0;;76764:114;;92315:69;;;;;;;;;;-1:-1:-1;92315:69:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;92546:47;;;;;;;;;;-1:-1:-1;92546:47:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;93166:44;;;;;;;;;;;;93204:6;93166:44;;92863:57;;;;;;;;;;-1:-1:-1;92863:57:0;;;;;:::i;:::-;;;;;;;;;;;;;;77224:117;;;;;;;;;;-1:-1:-1;77311:24:0;;77224:117;;77438:81;;;;;;;;;;-1:-1:-1;75804:6:0;77438:81;;94890:376;;;;;;;;;;-1:-1:-1;94890:376:0;;;;;:::i;:::-;;:::i;81285:460::-;;;;;;;;;;;;;:::i;79553:297::-;;;;;;;;;;;;;:::i;76438:81::-;;;;;;;;;;-1:-1:-1;76507:6:0;;-1:-1:-1;;;;;76507:6:0;76438:81;;92681:46;;;;;;;;;;-1:-1:-1;92681:46:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;107202:3750;;;;;;;;;;-1:-1:-1;107202:3750:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;95881:300::-;;;;;;;;;;-1:-1:-1;95881:300:0;;;;;:::i;:::-;;:::i;80868:331::-;;;;;;;;;;-1:-1:-1;80868:331:0;;;;;:::i;:::-;;:::i;111511:3512::-;;;;;;;;;;-1:-1:-1;111511:3512:0;;;;;:::i;:::-;;:::i;78664:531::-;;;;;;;;;;;;;:::i;76992:119::-;;;;;;;;;;-1:-1:-1;77080:25:0;;76992:119;;81896:584;;;;;;;;;;;;;:::i;97091:158::-;;;;;;:::i;:::-;;:::i;76598:87::-;;;;;;;;;;-1:-1:-1;76670:9:0;;-1:-1:-1;;;;;76670:9:0;76598:87;;80626:88;;;;;;;;;;-1:-1:-1;80688:6:0;;-1:-1:-1;;;;;80688:6:0;:20;80626:88;;99360:7085;;;;;;:::i;:::-;;:::i;93315:45::-;;;;;;;;;;;;93353:7;93315:45;;96585:173;;;;;;:::i;:::-;;:::i;78248:303::-;;;;;;;;;;;;;:::i;79308:132::-;;;;;;;;;;;;;:::i;97669:819::-;;;;;;;;;;-1:-1:-1;97669:819:0;;;;;:::i;:::-;;:::i;78000:134::-;78079:6;;78059:4;;-1:-1:-1;;;;;78079:6:0;:20;;:49;;-1:-1:-1;78103:25:0;;;;78079:49;78072:56;;78000:134;:::o;94384:372::-;77647:6;;-1:-1:-1;;;;;77647:6:0;77657:10;77647:20;77639:40;;;;-1:-1:-1;;;77639:40:0;;;;;;;:::i;:::-;;;;;;;;;-1:-1:-1;;;;;94494:20:0;::::1;94486:40;;;::::0;-1:-1:-1;;;94486:40:0;;30754:2:1;94486:40:0::1;::::0;::::1;30736:21:1::0;30793:1;30773:18;;;30766:29;-1:-1:-1;;;30811:18:1;;;30804:37;30858:18;;94486:40:0::1;30726:156:1::0;94486:40:0::1;-1:-1:-1::0;;;;;94580:23:0;::::1;;::::0;;;:15:::1;:23;::::0;;;;;::::1;;:32;94572:52;;;::::0;-1:-1:-1;;;94572:52:0;;24995:2:1;94572:52:0::1;::::0;::::1;24977:21:1::0;25034:1;25014:18;;;25007:29;-1:-1:-1;;;25052:18:1;;;25045:37;25099:18;;94572:52:0::1;24967:156:1::0;94572:52:0::1;-1:-1:-1::0;;;;;94656:23:0;::::1;;::::0;;;:15:::1;:23;::::0;;;;;:30;;-1:-1:-1;;94656:30:0::1;94682:4;94656:30;::::0;;94719:31;94739:10:::1;::::0;94656:23;94719:31:::1;::::0;::::1;94384:372:::0;:::o;93794:273::-;93846:16;93932:7;93950:10;93946:97;;-1:-1:-1;94022:13:0;93946:97;94056:5;93794:273;-1:-1:-1;93794:273:0:o;95424:293::-;77647:6;;-1:-1:-1;;;;;77647:6:0;77657:10;77647:20;77639:40;;;;-1:-1:-1;;;77639:40:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;95541:23:0;::::1;;::::0;;;:14:::1;:23;::::0;;;;;::::1;;:32;95533:52;;;::::0;-1:-1:-1;;;95533:52:0;;37474:2:1;95533:52:0::1;::::0;::::1;37456:21:1::0;37513:1;37493:18;;;37486:29;-1:-1:-1;;;37531:18:1;;;37524:37;37578:18;;95533:52:0::1;37446:156:1::0;95533:52:0::1;-1:-1:-1::0;;;;;95617:23:0;::::1;;::::0;;;:14:::1;:23;::::0;;;;;:30;;-1:-1:-1;;95617:30:0::1;95643:4;95617:30;::::0;;95680:31;95700:10:::1;::::0;95617:23;95680:31:::1;::::0;::::1;95424:293:::0;:::o;79963:528::-;77647:6;;-1:-1:-1;;;;;77647:6:0;77657:10;77647:20;77639:40;;;;-1:-1:-1;;;77639:40:0;;;;;;;:::i;:::-;80135:24:::1;::::0;::::1;;80134:25;80126:46;;;::::0;-1:-1:-1;;;80126:46:0;;38554:2:1;80126:46:0::1;::::0;::::1;38536:21:1::0;38593:1;38573:18;;;38566:29;-1:-1:-1;;;38611:18:1;;;38604:38;38659:18;;80126:46:0::1;38526:157:1::0;80126:46:0::1;80271:1;80244:24;;:28;80236:49;;;::::0;-1:-1:-1;;;80236:49:0;;32095:2:1;80236:49:0::1;::::0;::::1;32077:21:1::0;32134:1;32114:18;;;32107:29;-1:-1:-1;;;32152:18:1;;;32145:38;32200:18;;80236:49:0::1;32067:157:1::0;80236:49:0::1;75804:6;80354:24;;80336:15;:42;;;;:::i;:::-;80335:53;80327:74;;;::::0;-1:-1:-1;;;80327:74:0;;34103:2:1;80327:74:0::1;::::0;::::1;34085:21:1::0;34142:1;34122:18;;;34115:29;-1:-1:-1;;;34160:18:1;;;34153:38;34208:18;;80327:74:0::1;34075:157:1::0;80327:74:0::1;80461:24;80480:4;80461:18;:24::i;:::-;79963:528::o:0;94890:376::-;77647:6;;-1:-1:-1;;;;;77647:6:0;77657:10;77647:20;77639:40;;;;-1:-1:-1;;;77639:40:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;95003:20:0;::::1;94995:40;;;::::0;-1:-1:-1;;;94995:40:0;;16680:2:1;94995:40:0::1;::::0;::::1;16662:21:1::0;16719:1;16699:18;;;16692:29;-1:-1:-1;;;16737:18:1;;;16730:37;16784:18;;94995:40:0::1;16652:156:1::0;94995:40:0::1;-1:-1:-1::0;;;;;95088:23:0;::::1;;::::0;;;:15:::1;:23;::::0;;;;;::::1;;:31;;:23:::0;:31:::1;95080:51;;;::::0;-1:-1:-1;;;95080:51:0;;18689:2:1;95080:51:0::1;::::0;::::1;18671:21:1::0;18728:1;18708:18;;;18701:29;-1:-1:-1;;;18746:18:1;;;18739:37;18793:18;;95080:51:0::1;18661:156:1::0;95080:51:0::1;-1:-1:-1::0;;;;;95163:23:0;::::1;95189:5;95163:23:::0;;;:15:::1;:23;::::0;;;;;:31;;-1:-1:-1;;95163:31:0::1;::::0;;95227:33;95249:10:::1;::::0;95163:23;95227:33:::1;::::0;::::1;94890:376:::0;:::o;81285:460::-;77647:6;;-1:-1:-1;;;;;77647:6:0;77657:10;77647:20;77639:40;;;;-1:-1:-1;;;77639:40:0;;;;;;;:::i;:::-;81439:1:::1;81409:27;;:31;81401:51;;;::::0;-1:-1:-1;;;81401:51:0;;33768:2:1;81401:51:0::1;::::0;::::1;33750:21:1::0;33807:1;33787:18;;;33780:29;-1:-1:-1;;;33825:18:1;;;33818:37;33872:18;;81401:51:0::1;33740:156:1::0;81401:51:0::1;75804:6;81521:27;;81503:15;:45;;;;:::i;:::-;81502:56;81494:76;;;::::0;-1:-1:-1;;;81494:76:0;;30419:2:1;81494:76:0::1;::::0;::::1;30401:21:1::0;30458:1;30438:18;;;30431:29;-1:-1:-1;;;30476:18:1;;;30469:37;30523:18;;81494:76:0::1;30391:156:1::0;81494:76:0::1;81624:9;::::0;-1:-1:-1;;;;;81624:9:0::1;:23:::0;81616:43:::1;;;::::0;-1:-1:-1;;;81616:43:0;;39918:2:1;81616:43:0::1;::::0;::::1;39900:21:1::0;39957:1;39937:18;;;39930:29;-1:-1:-1;;;39975:18:1;;;39968:37;40022:18;;81616:43:0::1;39890:156:1::0;81616:43:0::1;81729:9;::::0;81719:20:::1;::::0;-1:-1:-1;;;;;81729:9:0::1;81719;:20::i;79553:297::-:0;77647:6;;-1:-1:-1;;;;;77647:6:0;77657:10;77647:20;77639:40;;;;-1:-1:-1;;;77639:40:0;;;;;;;:::i;:::-;79736:24:::1;::::0;::::1;;79735:25;79727:47;;;::::0;-1:-1:-1;;;79727:47:0;;31089:2:1;79727:47:0::1;::::0;::::1;31071:21:1::0;31128:1;31108:18;;;31101:29;-1:-1:-1;;;31146:18:1;;;31139:39;31195:18;;79727:47:0::1;31061:158:1::0;79727:47:0::1;79815:29;:27;:29::i;107202:3750::-:0;107296:22;;:::i;:::-;41126:1;41722:7;;:19;;41714:63;;;;-1:-1:-1;;;41714:63:0;;;;;;;:::i;:::-;41126:1;41855:7;:18;;;107599:41:::1;107628:4:::0;107599:28:::1;:41::i;:::-;107582:58:::0;-1:-1:-1;107759:135:0::1;107796:18;::::0;::::1;;107825;::::0;::::1;;107854:31;::::0;::::1;;107759:26;:135::i;:::-;107725:30;::::0;;;:22:::1;:30;::::0;;;;;:169:::1;107717:188;;;::::0;-1:-1:-1;;;107717:188:0;;25330:2:1;107717:188:0::1;::::0;::::1;25312:21:1::0;25369:1;25349:18;;;25342:29;-1:-1:-1;;;25387:18:1;;;25380:36;25433:18;;107717:188:0::1;25302:155:1::0;107717:188:0::1;107993:15;107971:18;::::0;::::1;;:37;;107963:56;;;::::0;-1:-1:-1;;;107963:56:0;;24661:2:1;107963:56:0::1;::::0;::::1;24643:21:1::0;24700:1;24680:18;;;24673:29;-1:-1:-1;;;24718:18:1;;;24711:36;24764:18;;107963:56:0::1;24633:155:1::0;107963:56:0::1;108099:31;::::0;::::1;;108091:54;;;::::0;-1:-1:-1;;;108091:54:0;;39584:2:1;108091:54:0::1;::::0;::::1;39566:21:1::0;39623:1;39603:18;;;39596:29;-1:-1:-1;;;39641:18:1;;;39634:36;39687:18;;108091:54:0::1;39556:155:1::0;108091:54:0::1;108246:24;::::0;::::1;;108228:13;;::::0;::::1;108246:4:::0;108228:13:::1;:::i;:::-;108218:24;;;;;;;:::i;:::-;;;;;;;;:52;108210:71;;;::::0;-1:-1:-1;;;108210:71:0;;23227:2:1;108210:71:0::1;::::0;::::1;23209:21:1::0;23266:1;23246:18;;;23239:29;-1:-1:-1;;;23284:18:1;;;23277:36;23330:18;;108210:71:0::1;23199:155:1::0;108210:71:0::1;108747:105;108784:18;::::0;::::1;;108813;::::0;::::1;;108784:11;108747:26;:105::i;:::-;108714:30;::::0;;;:22:::1;:30;::::0;;;;:138;:30;109044:23:::1;108714:30:::0;109095:12:::1;:10;:12::i;:::-;109076:31:::0;-1:-1:-1;109120:26:0::1;::::0;::::1;;:38:::0;::::1;109116:1572;;;109466:18;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;109452:32:0::1;:10;-1:-1:-1::0;;;;;109452:32:0::1;;109444:51;;;::::0;-1:-1:-1;;;109444:51:0;;29078:2:1;109444:51:0::1;::::0;::::1;29060:21:1::0;29117:1;29097:18;;;29090:29;-1:-1:-1;;;29135:18:1;;;29128:36;29181:18;;109444:51:0::1;29050:155:1::0;109444:51:0::1;109790:16;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;109563:243:0::1;:223;109599:25;::::0;::::1;;109637:15;::::0;::::1;;109665:28;::::0;::::1;;109706:42;;::::0;::::1;109599:4:::0;109706:42:::1;:::i;:::-;109761:14;;::::0;::::1;:4:::0;:14:::1;:::i;:::-;109563:23;:223::i;:::-;-1:-1:-1::0;;;;;109563:243:0::1;;109545:280;;;::::0;-1:-1:-1;;;109545:280:0;;20725:2:1;109545:280:0::1;::::0;::::1;20707:21:1::0;20764:1;20744:18;;;20737:29;-1:-1:-1;;;20782:18:1;;;20775:36;20828:18;;109545:280:0::1;20697:155:1::0;109545:280:0::1;109962:18;::::0;::::1;;109896:14;109962:11;109911:18;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;109896:34:0::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;109896:34:0;;;;109931:26:::1;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;109896:62:0::1;-1:-1:-1::0;;;;;109896:62:0::1;;;;;;;;;;;;;:84;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;109116:1572:0::1;::::0;-1:-1:-1;109116:1572:0::1;;110266:16;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;110088:194:0::1;:174;110124:25;::::0;::::1;;110162:15;::::0;::::1;;110190:8:::0;110219:4:::1;110237:14;;::::0;::::1;110124:4:::0;110237:14:::1;:::i;110088:174::-;-1:-1:-1::0;;;;;110088:194:0::1;;110070:231;;;::::0;-1:-1:-1;;;110070:231:0;;20725:2:1;110070:231:0::1;::::0;::::1;20707:21:1::0;20764:1;20744:18;;;20737:29;-1:-1:-1;;;20782:18:1;;;20775:36;20828:18;;110070:231:0::1;20697:155:1::0;110070:231:0::1;110501:18;::::0;::::1;;110482:15;::::0;::::1;;:37;;110474:56;;;::::0;-1:-1:-1;;;110474:56:0;;32431:2:1;110474:56:0::1;::::0;::::1;32413:21:1::0;32470:1;32450:18;;;32443:29;-1:-1:-1;;;32488:18:1;;;32481:36;32534:18;;110474:56:0::1;32403:155:1::0;110474:56:0::1;110577:103;110610:4:::0;110632:15:::1;::::0;::::1;;110658:13;;::::0;::::1;110610:4:::0;110658:13:::1;:::i;:::-;110577:22;:103::i;:::-;110541:139:::0;;-1:-1:-1;110541:139:0;-1:-1:-1;110541:139:0;-1:-1:-1;109116:1572:0::1;110801:25;::::0;::::1;;110774:18;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;110720:199:0::1;110749:16;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;110720:199:0::1;;110835:4;110848:7;110864:10;110883;110902;110720:199;;;;;;;;;;:::i;:::-;;;;;;;;110928:18;;::::0;;::::1;::::0;::::1;110935:4:::0;110928:18:::1;:::i;:::-;41082:1:::0;42034:7;:22;110928:18;107202:3750;-1:-1:-1;;;;;;107202:3750:0:o;95881:300::-;77647:6;;-1:-1:-1;;;;;77647:6:0;77657:10;77647:20;77639:40;;;;-1:-1:-1;;;77639:40:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;96003:23:0;::::1;;::::0;;;:14:::1;:23;::::0;;;;;::::1;;:31;;:23:::0;:31:::1;95995:51;;;::::0;-1:-1:-1;;;95995:51:0;;36805:2:1;95995:51:0::1;::::0;::::1;36787:21:1::0;36844:1;36824:18;;;36817:29;-1:-1:-1;;;36862:18:1;;;36855:37;36909:18;;95995:51:0::1;36777:156:1::0;95995:51:0::1;-1:-1:-1::0;;;;;96078:23:0;::::1;96104:5;96078:23:::0;;;:14:::1;:23;::::0;;;;;:31;;-1:-1:-1;;96078:31:0::1;::::0;;96142:33;96164:10:::1;::::0;96078:23;96142:33:::1;::::0;::::1;95881:300:::0;:::o;80868:331::-;77647:6;;-1:-1:-1;;;;;77647:6:0;77657:10;77647:20;77639:40;;;;-1:-1:-1;;;77639:40:0;;;;;;;:::i;:::-;80992:9:::1;::::0;-1:-1:-1;;;;;80992:26:0;;::::1;:9:::0;::::1;:26;;::::0;:57:::1;;-1:-1:-1::0;;;;;;81022:27:0;::::1;::::0;80992:57:::1;80984:78;;;::::0;-1:-1:-1;;;80984:78:0;;19024:2:1;80984:78:0::1;::::0;::::1;19006:21:1::0;19063:1;19043:18;;;19036:29;-1:-1:-1;;;19081:18:1;;;19074:38;19129:18;;80984:78:0::1;18996:157:1::0;80984:78:0::1;81121:6;::::0;-1:-1:-1;;;;;81121:23:0;;::::1;:6:::0;::::1;:23;;81113:44;;;::::0;-1:-1:-1;;;81113:44:0;;18353:2:1;81113:44:0::1;::::0;::::1;18335:21:1::0;18392:1;18372:18;;;18365:29;-1:-1:-1;;;18410:18:1;;;18403:38;18458:18;;81113:44:0::1;18325:157:1::0;81113:44:0::1;81166:27;81179:13;81166:12;:27::i;:::-;80868:331:::0;:::o;111511:3512::-;111613:22;;:::i;:::-;41126:1;41722:7;;:19;;41714:63;;;;-1:-1:-1;;;41714:63:0;;;;;;;:::i;:::-;41126:1;41855:7;:18;;;112084:41:::1;112113:4:::0;112084:28:::1;:41::i;:::-;112067:58:::0;-1:-1:-1;112219:99:0::1;112246:18;::::0;::::1;;112266;::::0;::::1;;112286:31;::::0;::::1;;112219:26;:99::i;:::-;112185:30;::::0;;;:22:::1;:30;::::0;;;;;:133:::1;112177:152;;;::::0;-1:-1:-1;;;112177:152:0;;31426:2:1;112177:152:0::1;::::0;::::1;31408:21:1::0;31465:1;31445:18;;;31438:29;-1:-1:-1;;;31483:18:1;;;31476:36;31529:18;;112177:152:0::1;31398:155:1::0;112177:152:0::1;112405:31;::::0;::::1;;112397:54;;;::::0;-1:-1:-1;;;112397:54:0;;34439:2:1;112397:54:0::1;::::0;::::1;34421:21:1::0;34478:1;34458:18;;;34451:29;-1:-1:-1;;;34496:18:1;;;34489:36;34542:18;;112397:54:0::1;34411:155:1::0;112397:54:0::1;112903:69;112930:18;::::0;::::1;;112950;::::0;::::1;;112930:11;112903:26;:69::i;:::-;112870:30;::::0;;;:22:::1;:30;::::0;;;;:102;;;;113028:12:::1;:10;:12::i;:::-;113009:31:::0;-1:-1:-1;113097:26:0::1;::::0;::::1;;:38:::0;::::1;113093:1705;;;113230:15;113208:18;::::0;::::1;;:37;113204:382;;113547:18;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;113533:32:0::1;:10;-1:-1:-1::0;;;;;113533:32:0::1;;113525:51;;;::::0;-1:-1:-1;;;113525:51:0;;38220:2:1;113525:51:0::1;::::0;::::1;38202:21:1::0;38259:1;38239:18;;;38232:29;-1:-1:-1;;;38277:18:1;;;38270:36;38323:18;;113525:51:0::1;38192:155:1::0;113525:51:0::1;113744:149;113777:26;::::0;;;::::1;::::0;::::1;;:::i;:::-;113822:32;::::0;;;::::1;::::0;::::1;;:::i;:::-;113866:18;::::0;::::1;;113744:22;:149::i;:::-;113093:1705;;;113998:15;113976:18;::::0;::::1;;:37;113972:685;;114152:16;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;114138:30:0::1;:10;-1:-1:-1::0;;;;;114138:30:0::1;;:144;;;-1:-1:-1::0;114266:16:0::1;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;114172:110:0::1;:90;114195:25;::::0;::::1;;114222:8:::0;114240:4:::1;114247:14;;::::0;::::1;114195:4:::0;114247:14:::1;:::i;:::-;114172:22;:90::i;:::-;-1:-1:-1::0;;;;;114172:110:0::1;;114138:144;114130:163;;;::::0;-1:-1:-1;;;114130:163:0;;28744:2:1;114130:163:0::1;::::0;::::1;28726:21:1::0;28783:1;28763:18;;;28756:29;-1:-1:-1;;;28801:18:1;;;28794:36;28847:18;;114130:163:0::1;28716:155:1::0;114130:163:0::1;114772:18;::::0;::::1;;114704:14;114772:11;114719:18;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;114704:34:0::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;114704:34:0;;;;114739:28:::1;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;114704:64:0::1;-1:-1:-1::0;;;;;114704:64:0::1;;;;;;;;;;;;;:86;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;113093:1705:0::1;114911:25;::::0;::::1;;114884:18;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;114830:145:0::1;114859:16;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;114830:145:0::1;;114945:4;114958:10;114830:145;;;;;;;:::i;:::-;;;;;;;;114999:18;;::::0;;::::1;::::0;::::1;115006:4:::0;114999:18:::1;:::i;:::-;41082:1:::0;42034:7;:22;114999:18;111511:3512;-1:-1:-1;;;;111511:3512:0:o;78664:531::-;77647:6;;-1:-1:-1;;;;;77647:6:0;77657:10;77647:20;77639:40;;;;-1:-1:-1;;;77639:40:0;;;;;;;:::i;:::-;78837:25:::1;::::0;::::1;;78836:26;78828:47;;;::::0;-1:-1:-1;;;78828:47:0;;27671:2:1;78828:47:0::1;::::0;::::1;27653:21:1::0;27710:1;27690:18;;;27683:29;-1:-1:-1;;;27728:18:1;;;27721:38;27776:18;;78828:47:0::1;27643:157:1::0;78828:47:0::1;78975:1;78947:25;;:29;78939:50;;;::::0;-1:-1:-1;;;78939:50:0;;20389:2:1;78939:50:0::1;::::0;::::1;20371:21:1::0;20428:1;20408:18;;;20401:29;-1:-1:-1;;;20446:18:1;;;20439:38;20494:18;;78939:50:0::1;20361:157:1::0;78939:50:0::1;75804:6;79051:25;;79033:15;:43;;;;:::i;:::-;79032:54;79024:75;;;::::0;-1:-1:-1;;;79024:75:0;;30083:2:1;79024:75:0::1;::::0;::::1;30065:21:1::0;30122:1;30102:18;;;30095:29;-1:-1:-1;;;30140:18:1;;;30133:38;30188:18;;79024:75:0::1;30055:157:1::0;79024:75:0::1;79164:25;79184:4;79164:19;:25::i;81896:584::-:0;77835:9;;-1:-1:-1;;;;;77835:9:0;77848:10;77835:23;77827:43;;;;-1:-1:-1;;;77827:43:0;;19720:2:1;77827:43:0;;;19702:21:1;19759:1;19739:18;;;19732:29;-1:-1:-1;;;19777:18:1;;;19770:37;19824:18;;77827:43:0;19692:156:1;77827:43:0;82016:9:::1;::::0;;82006:6;-1:-1:-1;;;;;82006:6:0;;::::1;82016:9:::0;::::1;82006:19;;81998:40;;;::::0;-1:-1:-1;;;81998:40:0;;27001:2:1;81998:40:0::1;::::0;::::1;26983:21:1::0;27040:1;27020:18;;;27013:29;-1:-1:-1;;;27058:18:1;;;27051:38;27106:18;;81998:40:0::1;26973:157:1::0;81998:40:0::1;75804:6;82344:27;;82326:15;:45;;;;:::i;:::-;82325:56;82317:77;;;::::0;-1:-1:-1;;;82317:77:0;;35466:2:1;82317:77:0::1;::::0;::::1;35448:21:1::0;35505:1;35485:18;;;35478:29;-1:-1:-1;;;35523:18:1;;;35516:38;35571:18;;82317:77:0::1;35438:157:1::0;97091:158:0;41126:1;41722:7;;:19;;41714:63;;;;-1:-1:-1;;;41714:63:0;;;;;;;:::i;:::-;41126:1;41855:7;:18;97192:51:::1;97215:6:::0;97223:7;97232:10:::1;97192:22;:51::i;:::-;-1:-1:-1::0;;41082:1:0;42034:7;:22;97091:158::o;99360:7085::-;99462:22;;:::i;:::-;41126:1;41722:7;;:19;;41714:63;;;;-1:-1:-1;;;41714:63:0;;;;;;;:::i;:::-;41126:1;41855:7;:18;;;99540:23:::1;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;99540:37:0::1;;;99532:56;;;::::0;-1:-1:-1;;;99532:56:0;;35802:2:1;99532:56:0::1;::::0;::::1;35784:21:1::0;35841:1;35821:18;;;35814:29;-1:-1:-1;;;35859:18:1;;;35852:36;35905:18;;99532:56:0::1;35774:155:1::0;99532:56:0::1;99683:1;99646:25;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;99646:39:0::1;;;99638:58;;;::::0;-1:-1:-1;;;99638:58:0;;28007:2:1;99638:58:0::1;::::0;::::1;27989:21:1::0;28046:1;28026:18;;;28019:29;-1:-1:-1;;;28064:18:1;;;28057:36;28110:18;;99638:58:0::1;27979:155:1::0;99638:58:0::1;99757:28;:26;:28::i;:::-;:74;;;-1:-1:-1::0;99789:15:0::1;:42;99805:25;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;99789:42:0::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;99789:42:0;;::::1;;99757:74;99749:93;;;::::0;-1:-1:-1;;;99749:93:0;;20055:2:1;99749:93:0::1;::::0;::::1;20037:21:1::0;20094:1;20074:18;;;20067:29;-1:-1:-1;;;20112:18:1;;;20105:36;20158:18;;99749:93:0::1;20027:155:1::0;99749:93:0::1;99965:1;99914:39;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;99914:53:0::1;;;99906:72;;;::::0;-1:-1:-1;;;99906:72:0;;27337:2:1;99906:72:0::1;::::0;::::1;27319:21:1::0;27376:1;27356:18;;;27349:29;-1:-1:-1;;;27394:18:1;;;27387:36;27440:18;;99906:72:0::1;27309:155:1::0;99906:72:0::1;100079:1;100032:35;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;100032:49:0::1;;;100024:68;;;::::0;-1:-1:-1;;;100024:68:0;;18019:2:1;100024:68:0::1;::::0;::::1;18001:21:1::0;18058:1;18038:18;;;18031:29;-1:-1:-1;;;18076:18:1;;;18069:36;18122:18;;100024:68:0::1;17991:155:1::0;100024:68:0::1;100152:33;::::0;::::1;;100189:35;::::0;::::1;;100152:72;;100144:91;;;::::0;-1:-1:-1;;;100144:91:0;;37140:2:1;100144:91:0::1;::::0;::::1;37122:21:1::0;37179:1;37159:18;;;37152:29;-1:-1:-1;;;37197:18:1;;;37190:36;37243:18;;100144:91:0::1;37112:155:1::0;100144:91:0::1;100286:16;100305:12;:10;:12::i;:::-;100286:31:::0;-1:-1:-1;100332:33:0::1;::::0;::::1;;:45:::0;::::1;::::0;:96:::1;;-1:-1:-1::0;100381:35:0::1;::::0;::::1;;:47:::0;::::1;100332:96;100324:115;;;::::0;-1:-1:-1;;;100324:115:0;;38890:2:1;100324:115:0::1;::::0;::::1;38872:21:1::0;38929:1;38909:18;;;38902:29;-1:-1:-1;;;38947:18:1;;;38940:36;38993:18;;100324:115:0::1;38862:155:1::0;100324:115:0::1;100524:14;100541:29;100555:15;100541:11;::::0;::::1;;:29;:::i;:::-;100524:46;;93204:6;100587;:21;;100579:40;;;::::0;-1:-1:-1;;;100579:40:0;;21394:2:1;100579:40:0::1;::::0;::::1;21376:21:1::0;21433:1;21413:18;;;21406:29;-1:-1:-1;;;21451:18:1;;;21444:36;21497:18;;100579:40:0::1;21366:155:1::0;100579:40:0::1;93353:7;100687:6;:21;;100679:40;;;::::0;-1:-1:-1;;;100679:40:0;;26333:2:1;100679:40:0::1;::::0;::::1;26315:21:1::0;26372:1;26352:18;;;26345:29;-1:-1:-1;;;26390:18:1;;;26383:36;26436:18;;100679:40:0::1;26305:155:1::0;100679:40:0::1;-1:-1:-1::0;100808:30:0::1;::::0;100781:14:::1;::::0;100808:30:::1;::::0;100819:4;;100808:30:::1;;;:::i;:::-;;::::0;;-1:-1:-1;;100808:30:0;;::::1;::::0;;;;;;100798:41;;100808:30:::1;100798:41:::0;;::::1;::::0;100896:1:::1;100854:30:::0;;;:22:::1;:30:::0;;;;;;100798:41;;-1:-1:-1;100854:44:0;100846:63:::1;;;::::0;-1:-1:-1;;;100846:63:0;;29412:2:1;100846:63:0::1;::::0;::::1;29394:21:1::0;29451:1;29431:18;;;29424:29;-1:-1:-1;;;29469:18:1;;;29462:36;29515:18;;100846:63:0::1;29384:155:1::0;100846:63:0::1;101475:11;::::0;::::1;;101563:33;::::0;::::1;;:45:::0;::::1;101559:3782;;;101679:28;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;101665:42:0::1;:10;-1:-1:-1::0;;;;;101665:42:0::1;;101657:61;;;::::0;-1:-1:-1;;;101657:61:0;;25664:2:1;101657:61:0::1;::::0;::::1;25646:21:1::0;25703:1;25683:18;;;25676:29;-1:-1:-1;;;25721:18:1;;;25714:36;25767:18;;101657:61:0::1;25636:155:1::0;101657:61:0::1;101983:1;101969:4;:11;;;:15;101961:34;;;::::0;-1:-1:-1;;;101961:34:0;;26667:2:1;101961:34:0::1;::::0;::::1;26649:21:1::0;26706:1;26686:18;;;26679:29;-1:-1:-1;;;26724:18:1;;;26717:36;26770:18;;101961:34:0::1;26639:155:1::0;101961:34:0::1;102143:27;:25;:27::i;:::-;:80;;;-1:-1:-1::0;102174:14:0::1;:49;102189:33;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;102174:49:0::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;102174:49:0;;::::1;;102143:80;102135:99;;;::::0;-1:-1:-1;;;102135:99:0;;21728:2:1;102135:99:0::1;::::0;::::1;21710:21:1::0;21767:1;21747:18;;;21740:29;-1:-1:-1;;;21785:18:1;;;21778:36;21831:18;;102135:99:0::1;21700:155:1::0;102135:99:0::1;102688:98;102722:33;::::0;;;::::1;::::0;::::1;;:::i;:::-;102766:4;:11;;;102688:23;:98::i;:::-;102679:107;;102952:97;102989:6;103006:4;:11;;;103028:12;102952:26;:97::i;:::-;102919:30;::::0;;;:22:::1;:30;::::0;;;;:130;101559:3782:::1;;;104044:1;104007:25;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;104007:39:0::1;;:88;;;-1:-1:-1::0;104050:45:0::1;104069:25;::::0;;;::::1;::::0;::::1;;:::i;:::-;11534:20:::0;11582:8;;;11211:387;104050:45:::1;103999:107;;;::::0;-1:-1:-1;;;103999:107:0;;33100:2:1;103999:107:0::1;::::0;::::1;33082:21:1::0;33139:1;33119:18;;;33112:29;-1:-1:-1;;;33157:18:1;;;33150:36;33203:18;;103999:107:0::1;33072:155:1::0;103999:107:0::1;104371:27;:25;:27::i;:::-;:82;;;-1:-1:-1::0;104402:14:0::1;:51;104417:35;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;104402:51:0::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;104402:51:0;;::::1;;104371:82;104363:101;;;::::0;-1:-1:-1;;;104363:101:0;;21728:2:1;104363:101:0::1;::::0;::::1;21710:21:1::0;21767:1;21747:18;;;21740:29;-1:-1:-1;;;21785:18:1;;;21778:36;21831:18;;104363:101:0::1;21700:155:1::0;104363:101:0::1;104543:25;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;104529:39:0::1;:10;-1:-1:-1::0;;;;;104529:39:0::1;;104521:58;;;::::0;-1:-1:-1;;;104521:58:0;;33434:2:1;104521:58:0::1;::::0;::::1;33416:21:1::0;33473:1;33453:18;;;33446:29;-1:-1:-1;;;33491:18:1;;;33484:36;33537:18;;104521:58:0::1;33406:155:1::0;104521:58:0::1;104678:9;:14:::0;104670:33:::1;;;::::0;-1:-1:-1;;;104670:33:0;;17015:2:1;104670:33:0::1;::::0;::::1;16997:21:1::0;17054:1;17034:18;;;17027:29;-1:-1:-1;;;17072:18:1;;;17065:36;17118:18;;104670:33:0::1;16987:155:1::0;104670:33:0::1;104756:15;104774:14;104756:15:::0;104789:25:::1;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;104774:41:0::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;104774:41:0;;;;104816:35:::1;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;104774:78:0::1;-1:-1:-1::0;;;;;104774:78:0::1;;;;;;;;;;;;;104756:96;;104880:6;104869:7;:17;;104861:36;;;::::0;-1:-1:-1;;;104861:36:0;;36136:2:1;104861:36:0::1;::::0;::::1;36118:21:1::0;36175:1;36155:18;;;36148:29;-1:-1:-1;;;36193:18:1;;;36186:36;36239:18;;104861:36:0::1;36108:155:1::0;104861:36:0::1;104982:97;105019:6;105036:4;:11;;;105058:12;104982:26;:97::i;:::-;104949:30;::::0;;;:22:::1;:30;::::0;;;;;:130;;;;105308:16;;::::1;::::0;105227:14:::1;::::0;104949:30;105242:25:::1;::::0;;;;;;::::1;;:::i;:::-;-1:-1:-1::0;;;;;105227:41:0::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;105227:41:0;;;;105269:35:::1;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;105227:78:0::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;105227:78:0;:97;-1:-1:-1;101559:3782:0::1;105400:859;::::0;;::::1;::::0;::::1;::::0;;;105368:29:::1;::::0;105400:859;105457:49:::1;;::::0;::::1;:4:::0;:49:::1;:::i;:::-;-1:-1:-1::0;;;;;105400:859:0::1;::::0;;::::1;::::0;;::::1;::::0;105521:23:::1;::::0;;;;;;::::1;;:::i;:::-;-1:-1:-1::0;;;;;105400:859:0::1;::::0;;::::1;;105561:25;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;105400:859:0::1;::::0;;::::1;;105606:28;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;105400:859:0::1;::::0;;::::1;;105659:33;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;105400:859:0::1;::::0;;::::1;;105719:35;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;105400:859:0::1;::::0;;::::1;;105785:39;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;105400:859:0::1;::::0;;::::1;;105893:35;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;105400:859:0::1;::::0;;::::1;;105841:25;::::0;;;::::1;::::0;::::1;;:::i;:::-;-1:-1:-1::0;;;;;105400:859:0::1;;;;;105951:4;:18;;:31;;;105400:859;;;;106006:4;:18;;:32;;;105400:859;;;;106063:4;:18;;:33;;;105400:859;;;;106123:4;:18;;:35;;;105400:859;;;;106175:6;105400:859;;;;106198:4;:11;;;105400:859;;;;106239:12;105400:859;;::::0;105368:891:::1;;106343:6;:20;;;106321:6;:13;;;-1:-1:-1::0;;;;;106273:144:0::1;106301:6;:11;;;-1:-1:-1::0;;;;;106273:144:0::1;;106372:6;106387:10;106406:4;106273:144;;;;;;;;:::i;:::-;;;;;;;;41082:1:::0;42034:7;:22;106433:6;99360:7085;-1:-1:-1;;;;;99360:7085:0:o;96585:173::-;41126:1;41722:7;;:19;;41714:63;;;;-1:-1:-1;;;41714:63:0;;;;;;;:::i;:::-;41126:1;41855:7;:18;96705:47:::1;96728:6:::0;96736:7;96745:6;96705:22:::1;:47::i;:::-;-1:-1:-1::0;;41082:1:0;42034:7;:22;-1:-1:-1;96585:173:0:o;78248:303::-;77647:6;;-1:-1:-1;;;;;77647:6:0;77657:10;77647:20;77639:40;;;;-1:-1:-1;;;77639:40:0;;;;;;;:::i;:::-;78435:25:::1;::::0;::::1;;78434:26;78426:48;;;::::0;-1:-1:-1;;;78426:48:0;;29746:2:1;78426:48:0::1;::::0;::::1;29728:21:1::0;29785:1;29765:18;;;29758:29;-1:-1:-1;;;29803:18:1;;;29796:39;29852:18;;78426:48:0::1;29718:158:1::0;78426:48:0::1;78515:30;:28;:30::i;79308:132::-:0;79386:6;;79366:4;;-1:-1:-1;;;;;79386:6:0;:20;;:48;;-1:-1:-1;;79410:24:0;;;;;79308:132::o;97669:819::-;41126:1;41722:7;;:19;;41714:63;;;;-1:-1:-1;;;41714:63:0;;;;;;;:::i;:::-;41126:1;41855:7;:18;-1:-1:-1;;;;;97864:23:0;::::1;97856:43;;;::::0;-1:-1:-1;;;97856:43:0;;23561:2:1;97856:43:0::1;::::0;::::1;23543:21:1::0;23600:1;23580:18;;;23573:29;-1:-1:-1;;;23618:18:1;;;23611:37;23665:18;;97856:43:0::1;23533:156:1::0;97856:43:0::1;97963:1;97954:6;:10;97946:30;;;::::0;-1:-1:-1;;;97946:30:0;;17684:2:1;97946:30:0::1;::::0;::::1;17666:21:1::0;17723:1;17703:18;;;17696:29;-1:-1:-1;;;17741:18:1;;;17734:37;17788:18;;97946:30:0::1;17656:156:1::0;97946:30:0::1;98024:10;97985:21;98009:26:::0;;;:14:::1;:26;::::0;;;;;;;-1:-1:-1;;;;;98009:35:0;::::1;::::0;;;;;;;;98119:23;;::::1;;98111:43;;;::::0;-1:-1:-1;;;98111:43:0;;22062:2:1;98111:43:0::1;::::0;::::1;22044:21:1::0;22101:1;22081:18;;;22074:29;-1:-1:-1;;;22119:18:1;;;22112:37;22166:18;;98111:43:0::1;22034:156:1::0;98111:43:0::1;98228:10;98213:26;::::0;;;:14:::1;:26;::::0;;;;;;;-1:-1:-1;;;;;98213:35:0;::::1;::::0;;;;;;;98251:22;;::::1;98213:60:::0;;98343:50:::1;98240:7:::0;98375:9;98267:6;98343:22:::1;:50::i;:::-;98426:56;::::0;;48563:25:1;;;-1:-1:-1;;;;;48624:32:1;;;48619:2;48604:18;;48597:60;98426:56:0;::::1;::::0;98443:10:::1;::::0;98426:56:::1;::::0;48536:18:1;98426:56:0::1;;;;;;;-1:-1:-1::0;;41082:1:0;42034:7;:22;-1:-1:-1;;97669:819:0:o;83058:170::-;83113:24;:32;;-1:-1:-1;;83113:32:0;;;;;;;;;;-1:-1:-1;83152:24:0;:28;83192:30;;14323:41:1;;;83192:30:0;;14311:2:1;14296:18;83192:30:0;;;;;;;;83058:170;:::o;83234:197::-;83305:6;;;-1:-1:-1;;;;;83318:17:0;;;-1:-1:-1;;;;;;83318:17:0;;;;;;;83286:16;83342:27;:31;;;83385:40;;83305:6;;;;;83318:17;83305:6;;83385:40;;83286:16;83385:40;83234:197;;:::o;82878:174::-;82959:15;82932:24;:42;;;82986:60;;14521:25:1;;;82986:60:0;;14509:2:1;14494:18;82986:60:0;;;;;;;;82878:174::o;119917:825::-;120071:619;;;;;;;;;120011:7;;;;120071:619;120137:37;;;;:6;:37;:::i;:::-;-1:-1:-1;;;;;120071:619:0;;;;;120189:6;:11;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;120071:619:0;;;;;120217:13;;;;;;;;:::i;:::-;-1:-1:-1;;;;;120071:619:0;;;;;120250:16;;;;;;;;:::i;:::-;-1:-1:-1;;;;;120071:619:0;;;;;120291:21;;;;;;;;:::i;:::-;-1:-1:-1;;;;;120071:619:0;;;;;120339:23;;;;;;;;:::i;:::-;-1:-1:-1;;;;;120071:619:0;;;;;120393:27;;;;;;;;:::i;:::-;-1:-1:-1;;;;;120071:619:0;;;;;120477:23;;;;;;;;:::i;:::-;-1:-1:-1;;;;;120071:619:0;;;;;120437:13;;;;;;;;:::i;:::-;-1:-1:-1;;;;;120071:619:0;;;;;120525:6;:21;;;120071:619;;;;120573:6;:23;;;120071:619;;;;120619:6;:19;;;120071:619;;;;120662:6;:20;;;120071:619;;;120027:663;;120725:9;120714:21;;;;;;;;:::i;:::-;;;;;;;;;;;;;120704:32;;;;;;120697:39;;;119917:825;;;:::o;121054:352::-;121230:126;;;;;;;;;;;;;;;;;;;;;;;;;121380:19;;;;;48038:32:1;;;48108:24;;48086:20;;;48079:54;48171:24;48149:20;;;48142:54;121380:19:0;;;;;;;;;;48011:18:1;;;;121380:19:0;;;121370:30;;;;;121054:352;;;;;;:::o;118557:638::-;118863:246;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;118863:246:0;;;;;;;;;;;;;;-1:-1:-1;;;;;118863:246:0;;;;;;119158:19;;118778:7;;119141:48;;119158:19;;118863:246;;119158:19;;:::i;:::-;;;;;;;;;;;;;119179:9;;119141:16;:48::i;:::-;119134:55;;;118557:638;;;;;;;;;:::o;122101:1838::-;122249:4;;122261:12;122496:13;;;;:26;;;122575:14;;122571:117;;122600:80;122623:23;;;;;;;;:::i;:::-;122656:10;122669;122600:22;:80::i;:::-;122780:1;122755:13;;;;;;;;:::i;:::-;-1:-1:-1;;;;;122755:27:0;;122751:1183;;;122861:10;;122857:126;;122884:89;122907:23;;;;;;;;:::i;:::-;122940;;;;;;;;:::i;:::-;122966:6;122884:22;:89::i;:::-;-1:-1:-1;;123013:12:0;;;122999:5;123013:12;;;;;;;;;122999:5;;-1:-1:-1;122999:5:0;;-1:-1:-1;122991:35:0;;122751:1183;123200:18;123221:47;123244:23;;;;;;;;:::i;:::-;-1:-1:-1;;;;;32821:25:0;;;32738:114;123221:47;123200:68;;123344:13;123343:14;:28;;;;;123370:1;123361:6;:10;123343:28;123339:132;;;123384:77;123407:23;;;;;;;;:::i;:::-;123440:11;123454:6;123384:22;:77::i;:::-;123685:11;-1:-1:-1;;;;;123685:19:0;;123713:13;:26;;123738:1;123713:26;;;123729:6;123713:26;123751:20;;;;123790:13;;;;;;;;:::i;:::-;123815:6;:23;;;;;;;;;;:::i;:::-;123857:6;:23;;;;;;;;;;:::i;:::-;123892:6;123909:8;;123685:241;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;123685:241:0;;;;;;;;;;;;:::i;:::-;123678:248;;;;;;;;122101:1838;;;;;;;;;:::o;83437:183::-;83527:15;83497:27;:45;83549:9;:25;;-1:-1:-1;;;;;;83549:25:0;-1:-1:-1;;;;;83549:25:0;;;;;;;;83586:28;;;;-1:-1:-1;;83586:28:0;83437:183;:::o;35994:252::-;-1:-1:-1;;;;;32821:25:0;;;36119:121;;36199:41;36213:7;36222:9;36233:6;36199:13;:41::i;:::-;35994:252;;;:::o;36119:121::-;36151:38;36171:9;36182:6;36151:19;:38::i;117614:578::-;117809:7;117859:31;117893:213;;;;;;;;117934:13;117893:213;;;;;;;;;;;;;;;;;-1:-1:-1;;;117893:213:0;;;;;;;118011:16;117893:213;;;;118068:30;-1:-1:-1;;;;;117893:213:0;;;;117859:247;;118138:48;118166:7;118155:19;;;;;;;;:::i;118138:48::-;118131:55;117614:578;-1:-1:-1;;;;;;;117614:578:0:o;82698:174::-;82754:25;:33;;-1:-1:-1;;82754:33:0;;;;;;;;;;-1:-1:-1;82794:25:0;:29;82835:31;;14323:41:1;;;82835:31:0;;14311:2:1;14296:18;82835:31:0;14278:92:1;115485:842:0;-1:-1:-1;;;;;115651:20:0;;115643:40;;;;-1:-1:-1;;;115643:40:0;;25998:2:1;115643:40:0;;;25980:21:1;26037:1;26017:18;;;26010:29;-1:-1:-1;;;26055:18:1;;;26048:37;26102:18;;115643:40:0;25970:156:1;115643:40:0;115747:1;115738:6;:10;115730:30;;;;-1:-1:-1;;;115730:30:0;;31760:2:1;115730:30:0;;;31742:21:1;31799:1;31779:18;;;31772:29;-1:-1:-1;;;31817:18:1;;;31810:37;31864:18;;115730:30:0;31732:156:1;115730:30:0;115804:28;:26;:28::i;:::-;:55;;;-1:-1:-1;;;;;;115836:23:0;;;;;;:15;:23;;;;;;;;115804:55;115796:75;;;;-1:-1:-1;;;115796:75:0;;21059:2:1;115796:75:0;;;21041:21:1;21098:1;21078:18;;;21071:29;-1:-1:-1;;;21116:18:1;;;21109:37;21163:18;;115796:75:0;21031:156:1;115796:75:0;115914:27;:25;:27::i;:::-;:54;;;-1:-1:-1;;;;;;115945:23:0;;;;;;:14;:23;;;;;;;;115914:54;115906:74;;;;-1:-1:-1;;;115906:74:0;;32765:2:1;115906:74:0;;;32747:21:1;32804:1;32784:18;;;32777:29;-1:-1:-1;;;32822:18:1;;;32815:37;32869:18;;115906:74:0;32737:156:1;115906:74:0;116033:40;116057:7;116066:6;116033:23;:40::i;:::-;-1:-1:-1;;;;;116196:22:0;;;;;;;:14;:22;;;;;;;;:31;;;;;;;;;;;:41;;116024:49;;-1:-1:-1;116024:49:0;;116196:31;;:22;:41;;116024:49;;116196:41;:::i;:::-;;;;-1:-1:-1;;116270:51:0;;;48563:25:1;;;116310:10:0;48619:2:1;48604:18;;48597:60;-1:-1:-1;;;;;116270:51:0;;;;;;;;;;48536:18:1;116270:51:0;;;;;;;115485:842;;;:::o;116724:663::-;116817:7;116854:15;-1:-1:-1;;;;;32821:25:0;;116927:429;;116994:15;116981:9;:28;116973:48;;;;-1:-1:-1;;;116973:48:0;;34773:2:1;116973:48:0;;;34755:21:1;34812:1;34792:18;;;34785:29;-1:-1:-1;;;34830:18:1;;;34823:37;34877:18;;116973:48:0;34745:156:1;116973:48:0;116927:429;;;117044:16;117063:31;117086:7;117063:22;:31::i;:::-;117044:50;-1:-1:-1;117111:9:0;:14;117103:34;;;;-1:-1:-1;;;117103:34:0;;17349:2:1;117103:34:0;;;17331:21:1;17388:1;17368:18;;;17361:29;-1:-1:-1;;;17406:18:1;;;17399:37;17453:18;;117103:34:0;17321:156:1;117103:34:0;117146:79;117173:7;117182:10;117202:4;117209:15;117146:26;:79::i;:::-;117340:8;117306:31;117329:7;117306:22;:31::i;:::-;:42;;;;:::i;:::-;117293:55;;116927:429;;117371:10;-1:-1:-1;116724:663:0;;;;;:::o;82514:178::-;82597:15;82569:25;:43;;;82624:62;;14521:25:1;;;82624:62:0;;14509:2:1;14494:18;82624:62:0;14476:76:1;119487:252:0;119592:7;119631:102;119653:55;119692:14;119682:25;;;;;;89028:58;;12963:66:1;89028:58:0;;;12951:79:1;13046:12;;;13039:28;;;88895:7:0;;13083:12:1;;89028:58:0;;;;;;;;;;;;89018:69;;;;;;89011:76;;88826:269;;;;119653:55;119717:9;;119631:102;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;119631:13:0;;-1:-1:-1;;;119631:102:0:i;:::-;119624:109;119487:252;-1:-1:-1;;;;119487:252:0:o;33887:181::-;34004:58;34034:7;34044:9;34055:6;34004:22;:58::i;33488:140::-;33586:36;33604:9;33615:6;33586:17;:36::i;:::-;33488:140;;:::o;33070:206::-;33133:7;-1:-1:-1;;;;;32821:25:0;;;33163:107;;33230:40;;-1:-1:-1;;;33230:40:0;;33264:4;33230:40;;;13462:51:1;-1:-1:-1;;;;;33230:25:0;;;;;13435:18:1;;33230:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;33163:107;;;33197:21;33149:121;33070:206;-1:-1:-1;;33070:206:0:o;34344:194::-;34471:61;34505:7;34515:4;34521:2;34525:6;34471:26;:61::i;:::-;34344:194;;;;:::o;84982:1270::-;85060:7;85280:9;:16;85300:2;85280:22;85276:969;;;85576:4;85561:20;;85555:27;85626:4;85611:20;;85605:27;85684:4;85669:20;;85663:27;85319:9;85655:36;85727:22;85735:4;85655:36;85555:27;85605;85727:7;:22::i;:::-;85720:29;;;;;;;85276:969;85771:9;:16;85791:2;85771:22;85767:478;;;86046:4;86031:20;;86025:27;86097:4;86082:20;;86076:27;86139:20;86147:4;86025:27;86076;86139:7;:20::i;:::-;86132:27;;;;;;85767:478;86192:41;;-1:-1:-1;;;86192:41:0;;19360:2:1;86192:41:0;;;19342:21:1;19399:2;19379:18;;;19372:30;19438:33;19418:18;;;19411:61;19489:18;;86192:41:0;19332:181:1;18956:211:0;19100:58;;-1:-1:-1;;;;;14096:32:1;;19100:58:0;;;14078:51:1;14145:18;;;14138:34;;;19073:86:0;;19093:5;;-1:-1:-1;;;19123:23:0;14051:18:1;;19100:58:0;;;;-1:-1:-1;;19100:58:0;;;;;;;;;;;;;;-1:-1:-1;;;;;19100:58:0;-1:-1:-1;;;;;;19100:58:0;;;;;;;;;;19073:19;:86::i;12533:317::-;12648:6;12623:21;:31;;12615:73;;;;-1:-1:-1;;;12615:73:0;;23896:2:1;12615:73:0;;;23878:21:1;23935:2;23915:18;;;23908:30;23974:31;23954:18;;;23947:59;24023:18;;12615:73:0;23868:179:1;12615:73:0;12702:12;12720:9;-1:-1:-1;;;;;12720:14:0;12742:6;12720:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12701:52;;;12772:7;12764:78;;;;-1:-1:-1;;;12764:78:0;;22397:2:1;12764:78:0;;;22379:21:1;22436:2;22416:18;;;22409:30;22475:34;22455:18;;;22448:62;22546:28;22526:18;;;22519:56;22592:19;;12764:78:0;22369:248:1;19175::0;19346:68;;-1:-1:-1;;;;;13782:15:1;;;19346:68:0;;;13764:34:1;13834:15;;13814:18;;;13807:43;13866:18;;;13859:34;;;19319:96:0;;19339:5;;-1:-1:-1;;;19369:27:0;13699:18:1;;19346:68:0;13681:218:1;87014:1512:0;87142:7;88081:66;88067:80;;;88045:164;;;;-1:-1:-1;;;88045:164:0;;22824:2:1;88045:164:0;;;22806:21:1;22863:2;22843:18;;;22836:30;22902:34;22882:18;;;22875:62;-1:-1:-1;;;22953:18:1;;;22946:32;22995:19;;88045:164:0;22796:224:1;88045:164:0;88228:1;:7;;88233:2;88228:7;:18;;;;88239:1;:7;;88244:2;88239:7;88228:18;88220:65;;;;-1:-1:-1;;;88220:65:0;;28341:2:1;88220:65:0;;;28323:21:1;28380:2;28360:18;;;28353:30;28419:34;28399:18;;;28392:62;-1:-1:-1;;;28470:18:1;;;28463:32;28512:19;;88220:65:0;28313:224:1;88220:65:0;88400:24;;;88383:14;88400:24;;;;;;;;;15489:25:1;;;15562:4;15550:17;;15530:18;;;15523:45;;;;15584:18;;;15577:34;;;15627:18;;;15620:34;;;88400:24:0;;15461:19:1;;88400:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;88400:24:0;;-1:-1:-1;;88400:24:0;;;-1:-1:-1;;;;;;;88443:20:0;;88435:57;;;;-1:-1:-1;;;88435:57:0;;16327:2:1;88435:57:0;;;16309:21:1;16366:2;16346:18;;;16339:30;16405:26;16385:18;;;16378:54;16449:18;;88435:57:0;16299:174:1;88435:57:0;88512:6;87014:1512;-1:-1:-1;;;;;87014:1512:0:o;86512:371::-;86623:7;-1:-1:-1;;;;;86710:75:0;;86812:3;86808:12;;;86822:2;86804:21;86853:22;86861:4;86804:21;86870:1;86710:75;86853:7;:22::i;21529:716::-;21953:23;21979:69;22007:4;21979:69;;;;;;;;;;;;;;;;;21987:5;-1:-1:-1;;;;;21979:27:0;;;:69;;;;;:::i;:::-;22063:17;;21953:95;;-1:-1:-1;22063:21:0;22059:179;;22160:10;22149:30;;;;;;;;;;;;:::i;:::-;22141:85;;;;-1:-1:-1;;;22141:85:0;;37809:2:1;22141:85:0;;;37791:21:1;37848:2;37828:18;;;37821:30;37887:34;37867:18;;;37860:62;-1:-1:-1;;;37938:18:1;;;37931:40;37988:19;;22141:85:0;37781:232:1;14017:229:0;14154:12;14186:52;14208:6;14216:4;14222:1;14225:12;14154;11534:20;;15424:60;;;;-1:-1:-1;;;15424:60:0;;35108:2:1;15424:60:0;;;35090:21:1;35147:2;35127:18;;;35120:30;35186:31;35166:18;;;35159:59;35235:18;;15424:60:0;35080:179:1;15424:60:0;15498:12;15512:23;15539:6;-1:-1:-1;;;;;15539:11:0;15558:5;15565:4;15539:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15497:73;;;;15588:52;15606:7;15615:10;15627:12;17756;17785:7;17781:530;;;-1:-1:-1;17816:10:0;17809:17;;17781:530;17930:17;;:21;17926:374;;18128:10;18122:17;18189:15;18176:10;18172:2;18168:19;18161:44;18076:148;18271:12;18264:20;;-1:-1:-1;;;18264:20:0;;;;;;;;:::i;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:134:1:-;82:20;;111:31;82:20;111:31;:::i;153:164::-;229:13;;278;;271:21;261:32;;251:2;;307:1;304;297:12;322:257;381:6;434:2;422:9;413:7;409:23;405:32;402:2;;;455:6;447;440:22;402:2;499:9;486:23;518:31;543:5;518:31;:::i;584:398::-;652:6;660;713:2;701:9;692:7;688:23;684:32;681:2;;;734:6;726;719:22;681:2;778:9;765:23;797:31;822:5;797:31;:::i;:::-;847:5;-1:-1:-1;904:2:1;889:18;;876:32;917:33;876:32;917:33;:::i;:::-;969:7;959:17;;;671:311;;;;;:::o;987:212::-;1054:6;1107:2;1095:9;1086:7;1082:23;1078:32;1075:2;;;1128:6;1120;1113:22;1075:2;1156:37;1183:9;1156:37;:::i;1204:903::-;1295:6;1303;1311;1364:2;1352:9;1343:7;1339:23;1335:32;1332:2;;;1385:6;1377;1370:22;1332:2;1413:37;1440:9;1413:37;:::i;:::-;1403:47;;1469:46;1511:2;1500:9;1496:18;1469:46;:::i;:::-;1459:56;;1559:2;1548:9;1544:18;1538:25;1582:18;1623:2;1615:6;1612:14;1609:2;;;1644:6;1636;1629:22;1609:2;1687:6;1676:9;1672:22;1662:32;;1732:7;1725:4;1721:2;1717:13;1713:27;1703:2;;1759:6;1751;1744:22;1703:2;1793;1787:9;1815:2;1811;1808:10;1805:2;;;1821:18;;:::i;:::-;1863:53;1906:2;1887:13;;-1:-1:-1;;1883:27:1;1912:2;1879:36;1863:53;:::i;:::-;1850:66;;1939:2;1932:5;1925:17;1979:7;1974:2;1969;1965;1961:11;1957:20;1954:33;1951:2;;;2005:6;1997;1990:22;1951:2;2023:54;2074:2;2069;2062:5;2058:14;2053:2;2049;2045:11;2023:54;:::i;:::-;;2096:5;2086:15;;;;1322:785;;;;;:::o;2112:190::-;2171:6;2224:2;2212:9;2203:7;2199:23;2195:32;2192:2;;;2245:6;2237;2230:22;2192:2;-1:-1:-1;2273:23:1;;2182:120;-1:-1:-1;2182:120:1:o;2307:420::-;2396:6;2449:2;2437:9;2428:7;2424:23;2420:32;2417:2;;;2470:6;2462;2455:22;2417:2;2515:9;2502:23;2548:18;2540:6;2537:30;2534:2;;;2585:6;2577;2570:22;2534:2;2613:22;;2669:3;2651:16;;;2647:26;2644:2;;;2691:6;2683;2676:22;2732:421;2822:6;2875:2;2863:9;2854:7;2850:23;2846:32;2843:2;;;2896:6;2888;2881:22;2843:2;2941:9;2928:23;2974:18;2966:6;2963:30;2960:2;;;3011:6;3003;2996:22;2960:2;3039:22;;3095:3;3077:16;;;3073:26;3070:2;;;3117:6;3109;3102:22;3158:421;3248:6;3301:2;3289:9;3280:7;3276:23;3272:32;3269:2;;;3322:6;3314;3307:22;3269:2;3367:9;3354:23;3400:18;3392:6;3389:30;3386:2;;;3437:6;3429;3422:22;3386:2;3465:22;;3521:3;3503:16;;;3499:26;3496:2;;;3543:6;3535;3528:22;3584:1510;3676:6;3729:3;3717:9;3708:7;3704:23;3700:33;3697:2;;;3751:6;3743;3736:22;3697:2;3782:22;;:::i;:::-;3827:29;3846:9;3827:29;:::i;:::-;3820:5;3813:44;3889:38;3923:2;3912:9;3908:18;3889:38;:::i;:::-;3884:2;3877:5;3873:14;3866:62;3960:38;3994:2;3983:9;3979:18;3960:38;:::i;:::-;3955:2;3948:5;3944:14;3937:62;4031:38;4065:2;4054:9;4050:18;4031:38;:::i;:::-;4026:2;4019:5;4015:14;4008:62;4103:39;4137:3;4126:9;4122:19;4103:39;:::i;:::-;4097:3;4090:5;4086:15;4079:64;4176:39;4210:3;4199:9;4195:19;4176:39;:::i;:::-;4170:3;4163:5;4159:15;4152:64;4249:39;4283:3;4272:9;4268:19;4249:39;:::i;:::-;4243:3;4236:5;4232:15;4225:64;4322:39;4356:3;4345:9;4341:19;4322:39;:::i;:::-;4316:3;4309:5;4305:15;4298:64;4381:3;4416:38;4450:2;4439:9;4435:18;4416:38;:::i;:::-;4400:14;;;4393:62;4474:3;4522:18;;;4509:32;4493:14;;;4486:56;4561:3;4609:18;;;4596:32;4580:14;;;4573:56;4648:3;4696:18;;;4683:32;4667:14;;;4660:56;4735:3;4783:18;;;4770:32;4754:14;;;4747:56;4822:3;4870:18;;;4857:32;4841:14;;;4834:56;4909:3;4957:18;;;4944:32;4928:14;;;4921:56;4996:3;5044:18;;;5031:32;5015:14;;;5008:56;;;;-1:-1:-1;4404:5:1;3687:1407;-1:-1:-1;3687:1407:1:o;5099:194::-;5169:6;5222:2;5210:9;5201:7;5197:23;5193:32;5190:2;;;5243:6;5235;5228:22;5190:2;-1:-1:-1;5271:16:1;;5180:113;-1:-1:-1;5180:113:1:o;5298:325::-;5366:6;5374;5427:2;5415:9;5406:7;5402:23;5398:32;5395:2;;;5448:6;5440;5433:22;5395:2;5489:9;5476:23;5466:33;;5549:2;5538:9;5534:18;5521:32;5562:31;5587:5;5562:31;:::i;5628:466::-;5705:6;5713;5721;5774:2;5762:9;5753:7;5749:23;5745:32;5742:2;;;5795:6;5787;5780:22;5742:2;5836:9;5823:23;5813:33;;5896:2;5885:9;5881:18;5868:32;5909:31;5934:5;5909:31;:::i;:::-;5959:5;-1:-1:-1;6016:2:1;6001:18;;5988:32;6029:33;5988:32;6029:33;:::i;:::-;6081:7;6071:17;;;5732:362;;;;;:::o;6791:268::-;6879:6;6874:3;6867:19;6931:6;6924:5;6917:4;6912:3;6908:14;6895:43;-1:-1:-1;6849:3:1;6958:16;;;6976:4;6954:27;;;6947:40;;;;7041:2;7020:15;;;-1:-1:-1;;7016:29:1;7007:39;;;7003:50;;6857:202::o;7064:257::-;7105:3;7143:5;7137:12;7170:6;7165:3;7158:19;7186:63;7242:6;7235:4;7230:3;7226:14;7219:4;7212:5;7208:16;7186:63;:::i;:::-;7303:2;7282:15;-1:-1:-1;;7278:29:1;7269:39;;;;7310:4;7265:50;;7113:208;-1:-1:-1;;7113:208:1:o;7326:1468::-;7413:58;7467:3;7440:25;7459:5;7440:25;:::i;:::-;-1:-1:-1;;;;;6652:31:1;6640:44;;6630:60;7413:58;7495:36;7525:4;7518:5;7514:16;7495:36;:::i;:::-;-1:-1:-1;;;;;6652:31:1;7585:4;7576:14;;6640:44;7615:36;7645:4;7634:16;;7615:36;:::i;:::-;-1:-1:-1;;;;;6652:31:1;7705:4;7696:14;;6640:44;7735:36;7765:4;7754:16;;7735:36;:::i;:::-;-1:-1:-1;;;;;6652:31:1;7825:4;7816:14;;6640:44;7855:36;7885:4;7874:16;;7855:36;:::i;:::-;-1:-1:-1;;;;;6652:31:1;7945:4;7936:14;;6640:44;7975:36;8005:4;7994:16;;7975:36;:::i;:::-;-1:-1:-1;;;;;6652:31:1;8065:4;8056:14;;6640:44;8095:36;8125:4;8114:16;;8095:36;:::i;:::-;-1:-1:-1;;;;;6652:31:1;8185:4;8176:14;;6640:44;8215:36;8245:4;8234:16;;8215:36;:::i;:::-;-1:-1:-1;;;;;6652:31:1;8305:4;8296:14;;6640:44;8330:6;8360:34;8379:14;;;8360:34;:::i;:::-;-1:-1:-1;;;;;6652:31:1;8439:12;;;6640:44;8471:6;8520:14;;;8507:28;8493:12;;;8486:50;8555:6;8604:14;;;8591:28;8577:12;;;8570:50;8639:6;8688:14;;;8675:28;8661:12;;;8654:50;8723:6;8772:14;;;8759:28;8745:12;;8738:50;7403:1391::o;8799:1711::-;8877:58;8931:3;8904:25;8923:5;8904:25;:::i;8877:58::-;8959:36;8989:4;8982:5;8978:16;8959:36;:::i;:::-;-1:-1:-1;;;;;6652:31:1;9049:4;9040:14;;6640:44;9079:36;9109:4;9098:16;;9079:36;:::i;:::-;-1:-1:-1;;;;;6652:31:1;9169:4;9160:14;;6640:44;9199:36;9229:4;9218:16;;9199:36;:::i;:::-;-1:-1:-1;;;;;6652:31:1;9289:4;9280:14;;6640:44;9319:36;9349:4;9338:16;;9319:36;:::i;:::-;-1:-1:-1;;;;;6652:31:1;9409:4;9400:14;;6640:44;9439:36;9469:4;9458:16;;9439:36;:::i;:::-;-1:-1:-1;;;;;6652:31:1;9529:4;9520:14;;6640:44;9559:36;9589:4;9578:16;;9559:36;:::i;:::-;-1:-1:-1;;;;;6652:31:1;9649:4;9640:14;;6640:44;9679:36;9709:4;9698:16;;9679:36;:::i;:::-;-1:-1:-1;;;;;6652:31:1;9769:4;9760:14;;6640:44;9794:6;9824:34;9843:14;;;9824:34;:::i;:::-;-1:-1:-1;;;;;6652:31:1;9903:12;;;6640:44;9935:6;9984:14;;;9971:28;9957:12;;;9950:50;10019:6;10068:14;;;10055:28;10041:12;;;10034:50;10103:6;10152:14;;;10139:28;10125:12;;;10118:50;10187:6;10236:14;;;10223:28;10209:12;;;10202:50;10271:6;10320:14;;;10307:28;10293:12;;;10286:50;10355:6;10404:14;;;10391:28;10377:12;;;10370:50;10439:6;10488:14;;;10475:28;10461:12;;10454:50;8867:1643::o;10515:1644::-;10611:12;;-1:-1:-1;;;;;6652:31:1;6640:44;;10675:4;10668:5;10664:16;10658:23;10690:56;10740:4;10735:3;10731:14;10717:12;-1:-1:-1;;;;;6652:31:1;6640:44;;6630:60;10690:56;;10794:4;10787:5;10783:16;10777:23;10809:58;10861:4;10856:3;10852:14;10836;-1:-1:-1;;;;;6652:31:1;6640:44;;6630:60;10809:58;;10915:4;10908:5;10904:16;10898:23;10930:58;10982:4;10977:3;10973:14;10957;-1:-1:-1;;;;;6652:31:1;6640:44;;6630:60;10930:58;;11036:4;11029:5;11025:16;11019:23;11051:58;11103:4;11098:3;11094:14;11078;-1:-1:-1;;;;;6652:31:1;6640:44;;6630:60;11051:58;;11157:4;11150:5;11146:16;11140:23;11172:58;11224:4;11219:3;11215:14;11199;-1:-1:-1;;;;;6652:31:1;6640:44;;6630:60;11172:58;;11278:4;11271:5;11267:16;11261:23;11293:58;11345:4;11340:3;11336:14;11320;-1:-1:-1;;;;;6652:31:1;6640:44;;6630:60;11293:58;;11399:4;11392:5;11388:16;11382:23;11414:58;11466:4;11461:3;11457:14;11441;-1:-1:-1;;;;;6652:31:1;6640:44;;6630:60;11414:58;-1:-1:-1;11491:6:1;11534:14;;;11528:21;-1:-1:-1;;;;;6652:31:1;11601:12;;;6640:44;11633:6;11675:14;;;11669:21;11655:12;;;11648:43;11710:6;11752:14;;;11746:21;11732:12;;;11725:43;11787:6;11829:14;;;11823:21;11809:12;;;11802:43;11864:6;11906:14;;;11900:21;11886:12;;;11879:43;11941:6;11983:14;;;11977:21;11963:12;;;11956:43;12018:6;12060:14;;;12054:21;12040:12;;;12033:43;12095:6;12137:14;;;12131:21;12117:12;;12110:43;10574:1585::o;12164:273::-;12347:6;12339;12334:3;12321:33;12303:3;12373:16;;12398:15;;;12373:16;12311:126;-1:-1:-1;12311:126:1:o;12442:274::-;12571:3;12609:6;12603:13;12625:53;12671:6;12666:3;12659:4;12651:6;12647:17;12625:53;:::i;:::-;12694:16;;;;;12579:137;-1:-1:-1;;12579:137:1:o;14557:700::-;14868:25;;;-1:-1:-1;;;;;14967:15:1;;;14962:2;14947:18;;14940:43;15019:15;;;15014:2;14999:18;;14992:43;15071:15;;15066:2;15051:18;;15044:43;15118:3;15103:19;;15096:35;;;15168:3;14920;15147:19;;15140:32;;;14849:4;;15189:62;;15231:19;;15223:6;15215;15189:62;:::i;:::-;15181:70;14858:399;-1:-1:-1;;;;;;;;;14858:399:1:o;15901:219::-;16050:2;16039:9;16032:21;16013:4;16070:44;16110:2;16099:9;16095:18;16087:6;16070:44;:::i;36268:330::-;36470:2;36452:21;;;36509:1;36489:18;;;36482:29;-1:-1:-1;;;36542:2:1;36527:18;;36520:37;36589:2;36574:18;;36442:156::o;39022:355::-;39224:2;39206:21;;;39263:2;39243:18;;;39236:30;39302:33;39297:2;39282:18;;39275:61;39368:2;39353:18;;39196:181::o;40051:897::-;40266:2;40255:9;40248:21;40278:70;40344:2;40333:9;40329:18;40321:6;40278:70;:::i;:::-;40229:4;40391:59;40442:6;40434;40430:19;40422:6;40391:59;:::i;:::-;40469:6;40491:18;;;40484:30;40537:74;40606:3;40591:19;;40577:12;40563;40537:74;:::i;:::-;40523:88;;;40658:59;40709:6;40701;40697:19;40689:6;40658:59;:::i;:::-;40758:22;;;-1:-1:-1;;40754:36:1;40748:3;40733:19;;40726:65;40808;40762:6;40850:14;40834;40808:65;:::i;:::-;40800:73;;;;;40938:1;40934;40929:3;40925:11;40921:19;40913:6;40909:32;40904:2;40893:9;40889:18;40882:60;40238:710;;;;;:::o;40953:1531::-;41260:3;41249:9;41242:22;41273:71;41339:3;41328:9;41324:19;41316:6;41273:71;:::i;:::-;41406:6;41398;41394:19;41381:33;41375:3;41364:9;41360:19;41353:62;41223:4;41458:59;41509:6;41501;41497:19;41489:6;41458:59;:::i;:::-;41554:6;41548:3;41537:9;41533:19;41526:35;41584:74;41653:3;41642:9;41638:19;41624:12;41610;41584:74;:::i;:::-;41570:88;;;41705:59;41756:6;41748;41744:19;41736:6;41705:59;:::i;:::-;41787:3;41783:8;41856:2;41844:9;41836:6;41832:22;41828:31;41822:3;41811:9;41807:19;41800:60;41883:65;41941:6;41925:14;41909;41883:65;:::i;:::-;41869:79;;41995:59;42046:6;42038;42034:19;42026:6;41995:59;:::i;:::-;41957:97;;;;42119:2;42107:9;42099:6;42095:22;42091:31;42085:3;42074:9;42070:19;42063:60;;42143:65;42201:6;42185:14;42169;42143:65;:::i;:::-;42132:76;;;;42217:43;42256:2;42245:9;42241:18;42233:6;6765:13;6758:21;6746:34;;6736:50;42217:43;6765:13;;6758:21;42308:2;42293:18;;6746:34;42357:9;42352:3;42348:19;42343:2;42332:9;42328:18;42321:47;42385:29;42410:3;42402:6;42385:29;:::i;:::-;42377:37;;;42423:55;42473:3;42462:9;42458:19;42450:6;-1:-1:-1;;;;;6652:31:1;6640:44;;6630:60;42489:309;42709:3;42694:19;;42722:70;42698:9;42774:6;42722:70;:::i;42803:1666::-;43061:13;;-1:-1:-1;;;;;6652:31:1;6640:44;;43021:3;43006:19;;43133:4;43125:6;43121:17;43115:24;43148:62;43204:4;43193:9;43189:20;43175:12;-1:-1:-1;;;;;6652:31:1;6640:44;;6630:60;43148:62;;43259:4;43251:6;43247:17;43241:24;43274:64;43332:4;43321:9;43317:20;43301:14;-1:-1:-1;;;;;6652:31:1;6640:44;;6630:60;43274:64;;43387:4;43379:6;43375:17;43369:24;43402:64;43460:4;43449:9;43445:20;43429:14;-1:-1:-1;;;;;6652:31:1;6640:44;;6630:60;43402:64;;43515:4;43507:6;43503:17;43497:24;43530:64;43588:4;43577:9;43573:20;43557:14;-1:-1:-1;;;;;6652:31:1;6640:44;;6630:60;43530:64;;43643:4;43635:6;43631:17;43625:24;43658:64;43716:4;43705:9;43701:20;43685:14;-1:-1:-1;;;;;6652:31:1;6640:44;;6630:60;43658:64;;43771:4;43763:6;43759:17;43753:24;43786:64;43844:4;43833:9;43829:20;43813:14;-1:-1:-1;;;;;6652:31:1;6640:44;;6630:60;43786:64;;43899:4;43891:6;43887:17;43881:24;43914:64;43972:4;43961:9;43957:20;43941:14;-1:-1:-1;;;;;6652:31:1;6640:44;;6630:60;43914:64;-1:-1:-1;43997:6:1;44040:15;;;44034:22;-1:-1:-1;;;;;6652:31:1;44108:18;;;6640:44;44146:6;44194:15;;;44188:22;44168:18;;;44161:50;44230:6;44278:15;;;44272:22;44252:18;;;44245:50;44314:6;44362:15;;;44356:22;44336:18;;;44329:50;44398:6;44446:15;;;44440:22;44420:18;;;;44413:50;;;;44420:18;42988:1481::o;44474:591::-;44671:2;44660:9;44653:21;44716:6;44710:13;44705:2;44694:9;44690:18;44683:41;44634:4;44771:2;44763:6;44759:15;44753:22;44811:4;44806:2;44795:9;44791:18;44784:32;44839:51;44885:3;44874:9;44870:19;44856:12;44839:51;:::i;:::-;44944:2;44932:15;;44926:22;44921:2;44906:18;;;44899:50;;;;44997:15;;;44991:22;-1:-1:-1;;;;;44987:48:1;44980:4;44965:20;;;44958:78;;;;-1:-1:-1;44825:65:1;;44643:422;-1:-1:-1;44643:422:1:o;45070:654::-;45269:2;45258:9;45251:21;45314:6;45308:13;45303:2;45292:9;45288:18;45281:41;45376:2;45368:6;45364:15;45358:22;45353:2;45342:9;45338:18;45331:50;45232:4;45428:2;45420:6;45416:15;45410:22;45468:4;45463:2;45452:9;45448:18;45441:32;45496:51;45542:3;45531:9;45527:19;45513:12;45496:51;:::i;:::-;45602:2;45590:15;;45584:22;45578:3;45563:19;;;45556:51;;;;45655:16;;;45649:23;-1:-1:-1;;;;;45645:49:1;45682:3;45623:20;;;45616:79;;;;-1:-1:-1;45482:65:1;;45241:483;-1:-1:-1;45241:483:1:o;45729:271::-;45929:3;45914:19;;45942:52;45918:9;45976:6;45942:52;:::i;46005:1802::-;46279:4;46308:3;46320:52;46362:9;46354:6;46320:52;:::i;:::-;46391:3;46459:1;46455;46450:3;46446:11;46442:19;46434:6;46430:32;46425:2;46414:9;46410:18;46403:60;46482:3;46521:2;46516;46505:9;46501:18;46494:30;46533:79;46608:2;46597:9;46593:18;46585:6;46533:79;:::i;:::-;46674:6;46666;46662:19;46649:33;46643:3;46632:9;46628:19;46621:62;46746:6;46738;46734:19;46721:33;46714:4;46703:9;46699:20;46692:63;46798:59;46849:6;46841;46837:19;46829:6;46798:59;:::i;:::-;46895:6;46888:4;46877:9;46873:20;46866:36;46925:75;46994:4;46983:9;46979:20;46965:12;46951;46925:75;:::i;:::-;46911:89;;;47047:55;47098:2;47090:6;47086:15;47078:6;47047:55;:::i;:::-;47009:93;;47125:3;47121:8;47195:2;47183:9;47175:6;47171:22;47167:31;47160:4;47149:9;47145:20;47138:61;47222:65;47280:6;47264:14;47248;47222:65;:::i;:::-;47208:79;;47334:55;47385:2;47377:6;47373:15;47365:6;47334:55;:::i;:::-;47296:93;;;;47455:2;47443:9;47435:6;47431:22;47427:31;47420:4;47409:9;47405:20;47398:61;47482:65;47540:6;47524:14;47508;47482:65;:::i;:::-;47468:79;;47594:55;47645:2;47637:6;47633:15;47625:6;47594:55;:::i;:::-;47556:93;;;;47715:2;47703:9;47695:6;47691:22;47687:31;47680:4;47669:9;47665:20;47658:61;;;;47736:65;47794:6;47778:14;47762;47736:65;:::i;:::-;47728:73;46288:1519;-1:-1:-1;;;;;;;;46288:1519:1:o;48955:533::-;49032:4;49038:6;49098:11;49085:25;49192:2;49188:7;49177:8;49161:14;49157:29;49153:43;49133:18;49129:68;49119:2;;49214:4;49208;49201:18;49119:2;49244:33;;49296:20;;;-1:-1:-1;49339:18:1;49328:30;;49325:2;;;49374:4;49368;49361:18;49325:2;49410:4;49398:17;;-1:-1:-1;49441:14:1;49437:27;;;49427:38;;49424:2;;;49478:1;49475;49468:12;49424:2;49049:439;;;;;:::o;49493:252::-;49565:2;49559:9;49607:3;49595:16;;49641:18;49626:34;;49662:22;;;49623:62;49620:2;;;49688:18;;:::i;:::-;49724:2;49717:22;49539:206;:::o;49750:275::-;49821:2;49815:9;49886:2;49867:13;;-1:-1:-1;;49863:27:1;49851:40;;49921:18;49906:34;;49942:22;;;49903:62;49900:2;;;49968:18;;:::i;:::-;50004:2;49997:22;49795:230;;-1:-1:-1;49795:230:1:o;50030:511::-;50088:5;50095:6;50155:3;50142:17;50241:2;50237:7;50226:8;50210:14;50206:29;50202:43;50182:18;50178:68;50168:2;;50264:5;50257;50250:20;50168:2;50296:33;;50400:4;50387:18;;;-1:-1:-1;50348:21:1;;-1:-1:-1;50428:18:1;50417:30;;50414:2;;;50460:1;50457;50450:12;50414:2;50510:6;50494:14;50490:27;50480:8;50476:42;50473:2;;;50531:1;50528;50521:12;50546:128;50586:3;50617:1;50613:6;50610:1;50607:13;50604:2;;;50623:18;;:::i;:::-;-1:-1:-1;50659:9:1;;50594:80::o;50679:125::-;50719:4;50747:1;50744;50741:8;50738:2;;;50752:18;;:::i;:::-;-1:-1:-1;50789:9:1;;50728:76::o;50809:258::-;50881:1;50891:113;50905:6;50902:1;50899:13;50891:113;;;50981:11;;;50975:18;50962:11;;;50955:39;50927:2;50920:10;50891:113;;;51022:6;51019:1;51016:13;51013:2;;;-1:-1:-1;;51057:1:1;51039:16;;51032:27;50862:205::o;51072:127::-;51133:10;51128:3;51124:20;51121:1;51114:31;51164:4;51161:1;51154:15;51188:4;51185:1;51178:15;51204:127;51265:10;51260:3;51256:20;51253:1;51246:31;51296:4;51293:1;51286:15;51320:4;51317:1;51310:15;51336:131;-1:-1:-1;;;;;51411:31:1;;51401:42;;51391:2;;51457:1;51454;51447:12
Swarm Source
ipfs://2269da452bba446914352b77d48fb1282f9d93d6579e7d5164e4949a94396438
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
BSC | 21.48% | $0.999786 | 55,808.5157 | $55,796.57 | |
BSC | 13.44% | $1 | 34,902.8332 | $34,902.83 | |
BSC | 1.00% | $0.999614 | 2,597.4993 | $2,596.5 | |
POL | 17.39% | $0.99989 | 45,176.1622 | $45,171.19 | |
POL | 7.77% | $0.999827 | 20,182.8066 | $20,179.31 | |
POL | 0.03% | $1 | 78.2743 | $78.27 | |
ETH | 13.77% | $0.002725 | 13,128,801.6154 | $35,776.05 | |
ETH | 1.42% | $1 | 3,681.9952 | $3,685.68 | |
ETH | 0.46% | $1 | 1,193.1516 | $1,194.34 | |
ETH | 0.38% | $1 | 996.5793 | $996.58 | |
ETH | 0.25% | $3,842.1 | 0.1659 | $637.39 | |
ETH | <0.01% | $21.9 | 0.5 | $10.95 | |
GLMR | 7.72% | $0.999919 | 20,058.7148 | $20,057.09 | |
GLMR | 5.92% | $0.999827 | 15,377.3088 | $15,374.65 | |
GLMR | 0.41% | $1 | 1,063.5323 | $1,063.53 | |
OP | 6.30% | $0.99989 | 16,377.7804 | $16,375.98 | |
OP | 0.25% | $1 | 636.7425 | $636.74 | |
OP | 0.12% | $0.999827 | 304.9051 | $304.85 | |
OP | Ether (ETH) | 0.08% | $3,843.95 | 0.0566 | $217.6 |
ARBNOVA | 1.09% | $0.999319 | 2,822.1283 | $2,820.21 | |
ARBNOVA | 0.04% | $3,843.91 | 0.024 | $92.25 | |
AVAX | 0.22% | $0.99967 | 576.2205 | $576.03 | |
AVAX | 0.21% | $0.99989 | 533.2928 | $533.23 | |
AVAX | 0.11% | $0.999756 | 296.8145 | $296.74 | |
AVAX | <0.01% | $3,846.02 | 0.0052857 | $20.33 | |
GNO | 0.08% | $0.999424 | 197.3071 | $197.19 | |
GNO | 0.06% | $1 | 151.6946 | $151.69 | |
GNO | <0.01% | $0.999879 | 3.999 | $4 | |
CRONOS | 0.01% | $0.999319 | 30.0628 | $30.04 |
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.