Sonic Blaze Testnet

Contract

0x689eCFa6772fE9B74d230600603e752a4b9CcC18

Overview

S Balance

Sonic Blaze LogoSonic Blaze LogoSonic Blaze Logo0 S

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Deposit129507552025-01-16 2:51:4712 days ago1736995907IN
0x689eCFa6...a4b9CcC18
0 S0.000301821.32
Deposit125570652025-01-14 16:19:2513 days ago1736871565IN
0x689eCFa6...a4b9CcC18
0 S0.000339291.32
Redeem123970142025-01-14 2:15:4714 days ago1736820947IN
0x689eCFa6...a4b9CcC18
0 S0.000120481.32
Redeem123969482025-01-14 2:15:2714 days ago1736820927IN
0x689eCFa6...a4b9CcC18
0 S0.000093231.32
Deposit123967132025-01-14 2:14:1414 days ago1736820854IN
0x689eCFa6...a4b9CcC18
0 S0.000393881.32
Deposit117794632025-01-11 20:05:5616 days ago1736625956IN
0x689eCFa6...a4b9CcC18
0 S0.000364361.32
Redeem117746672025-01-11 19:41:0616 days ago1736624466IN
0x689eCFa6...a4b9CcC18
0 S0.000037521.32
Redeem117745652025-01-11 19:40:3516 days ago1736624435IN
0x689eCFa6...a4b9CcC18
0 S0.000037521.32
Deposit117696022025-01-11 19:15:4816 days ago1736622948IN
0x689eCFa6...a4b9CcC18
0 S0.000364361.32
Deposit117695542025-01-11 19:15:3416 days ago1736622934IN
0x689eCFa6...a4b9CcC18
0 S0.000313671.32
Deposit117694912025-01-11 19:15:1616 days ago1736622916IN
0x689eCFa6...a4b9CcC18
0 S0.000316211.32
Deposit117693732025-01-11 19:14:4216 days ago1736622882IN
0x689eCFa6...a4b9CcC18
0 S0.000316211.32
Deposit115690622025-01-11 2:26:0517 days ago1736562365IN
0x689eCFa6...a4b9CcC18
0 S0.000316221.32
Deposit115690302025-01-11 2:25:5517 days ago1736562355IN
0x689eCFa6...a4b9CcC18
0 S0.000316211.32
Deposit115689222025-01-11 2:25:2117 days ago1736562321IN
0x689eCFa6...a4b9CcC18
0 S0.000316211.32
Deposit114926962025-01-10 20:00:0117 days ago1736539201IN
0x689eCFa6...a4b9CcC18
0 S0.000364361.32
Deposit114921372025-01-10 19:57:0517 days ago1736539025IN
0x689eCFa6...a4b9CcC18
0 S0.000301811.32
New Bond114820082025-01-10 19:07:3017 days ago1736536050IN
0x689eCFa6...a4b9CcC18
0 S0.000553241.32
Whitelist Token114808782025-01-10 19:01:4317 days ago1736535703IN
0x689eCFa6...a4b9CcC18
0 S0.000106661.32
New Bond114806762025-01-10 19:00:4017 days ago1736535640IN
0x689eCFa6...a4b9CcC18
0 S0.000298511.32
New Bond114800322025-01-10 18:57:3217 days ago1736535452IN
0x689eCFa6...a4b9CcC18
0 S0.000309411.32
Redeem114733502025-01-10 18:23:4217 days ago1736533422IN
0x689eCFa6...a4b9CcC18
0 S0.000089731.32
Withdraw Quote T...114707662025-01-10 18:10:4817 days ago1736532648IN
0x689eCFa6...a4b9CcC18
0 S0.000073291.32
Close Bond114706942025-01-10 18:10:2817 days ago1736532628IN
0x689eCFa6...a4b9CcC18
0 S0.000082591.32
Deposit114687152025-01-10 18:00:4117 days ago1736532041IN
0x689eCFa6...a4b9CcC18
0 S0.000339281.32
View all transactions

Latest 25 internal transactions (View All)

Parent Transaction Hash Block From To
125570652025-01-14 16:19:2513 days ago1736871565
0x689eCFa6...a4b9CcC18
0 S
123970142025-01-14 2:15:4714 days ago1736820947
0x689eCFa6...a4b9CcC18
0 S
123967132025-01-14 2:14:1414 days ago1736820854
0x689eCFa6...a4b9CcC18
0 S
123967132025-01-14 2:14:1414 days ago1736820854
0x689eCFa6...a4b9CcC18
0 S
123967132025-01-14 2:14:1414 days ago1736820854
0x689eCFa6...a4b9CcC18
0 S
123967132025-01-14 2:14:1414 days ago1736820854
0x689eCFa6...a4b9CcC18
0 S
123967132025-01-14 2:14:1414 days ago1736820854
0x689eCFa6...a4b9CcC18
0 S
123967132025-01-14 2:14:1414 days ago1736820854
0x689eCFa6...a4b9CcC18
0 S
123967132025-01-14 2:14:1414 days ago1736820854
0x689eCFa6...a4b9CcC18
0 S
123967132025-01-14 2:14:1414 days ago1736820854
0x689eCFa6...a4b9CcC18
0 S
123967132025-01-14 2:14:1414 days ago1736820854
0x689eCFa6...a4b9CcC18
0 S
123967132025-01-14 2:14:1414 days ago1736820854
0x689eCFa6...a4b9CcC18
0 S
117794632025-01-11 20:05:5616 days ago1736625956
0x689eCFa6...a4b9CcC18
0 S
117794632025-01-11 20:05:5616 days ago1736625956
0x689eCFa6...a4b9CcC18
0 S
117794632025-01-11 20:05:5616 days ago1736625956
0x689eCFa6...a4b9CcC18
0 S
117696022025-01-11 19:15:4816 days ago1736622948
0x689eCFa6...a4b9CcC18
0 S
117696022025-01-11 19:15:4816 days ago1736622948
0x689eCFa6...a4b9CcC18
0 S
117696022025-01-11 19:15:4816 days ago1736622948
0x689eCFa6...a4b9CcC18
0 S
117695542025-01-11 19:15:3416 days ago1736622934
0x689eCFa6...a4b9CcC18
0 S
117694912025-01-11 19:15:1616 days ago1736622916
0x689eCFa6...a4b9CcC18
0 S
117693732025-01-11 19:14:4216 days ago1736622882
0x689eCFa6...a4b9CcC18
0 S
115690622025-01-11 2:26:0517 days ago1736562365
0x689eCFa6...a4b9CcC18
0 S
115690302025-01-11 2:25:5517 days ago1736562355
0x689eCFa6...a4b9CcC18
0 S
115689222025-01-11 2:25:2117 days ago1736562321
0x689eCFa6...a4b9CcC18
0 S
114926962025-01-10 20:00:0117 days ago1736539201
0x689eCFa6...a4b9CcC18
0 S
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
BondDepository

Compiler Version
v0.8.27+commit.40a35a09

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at testnet.sonicscan.org on 2025-01-08
*/

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-20 standard as defined in the ERC.
 */
interface IERC20 {
    /**
     * @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);

    /**
     * @dev Returns the value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the value of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 value) 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 a `value` amount of tokens 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 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}



pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[ERC].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}



pragma solidity ^0.8.20;



/**
 * @title IERC1363
 * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
 *
 * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
 * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
 */
interface IERC1363 is IERC20, IERC165 {
    /*
     * Note: the ERC-165 identifier for this interface is 0xb0202a11.
     * 0xb0202a11 ===
     *   bytes4(keccak256('transferAndCall(address,uint256)')) ^
     *   bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
     *   bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
     *   bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
     *   bytes4(keccak256('approveAndCall(address,uint256)')) ^
     *   bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
     */

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferAndCall(address to, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @param data Additional data with no specified format, sent in call to `to`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param from The address which you want to send tokens from.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferFromAndCall(address from, address to, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param from The address which you want to send tokens from.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @param data Additional data with no specified format, sent in call to `to`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function approveAndCall(address spender, uint256 value) external returns (bool);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     * @param data Additional data with no specified format, sent in call to `spender`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}


pragma solidity ^0.8.20;

/**
 * @dev Collection of common custom errors used in multiple contracts
 *
 * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.
 * It is recommended to avoid relying on the error API for critical functionality.
 *
 * _Available since v5.1._
 */
library Errors {
    /**
     * @dev The ETH balance of the account is not enough to perform the operation.
     */
    error InsufficientBalance(uint256 balance, uint256 needed);

    /**
     * @dev A call to an address target failed. The target may have reverted.
     */
    error FailedCall();

    /**
     * @dev The deployment failed.
     */
    error FailedDeployment();

    /**
     * @dev A necessary precompile is missing.
     */
    error MissingPrecompile(address);
}


pragma solidity ^0.8.20;


/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev There's no code at `target` (it is not a contract).
     */
    error AddressEmptyCode(address target);

    /**
     * @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://consensys.net/diligence/blog/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.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        if (address(this).balance < amount) {
            revert Errors.InsufficientBalance(address(this).balance, amount);
        }

        (bool success, ) = recipient.call{value: amount}("");
        if (!success) {
            revert Errors.FailedCall();
        }
    }

    /**
     * @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 or custom error, it is bubbled
     * up by this function (like regular Solidity function calls). However, if
     * the call reverted with no returned reason, this function reverts with a
     * {Errors.FailedCall} error.
     *
     * 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.
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0);
    }

    /**
     * @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`.
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        if (address(this).balance < value) {
            revert Errors.InsufficientBalance(address(this).balance, value);
        }
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
     * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case
     * of an unsuccessful call.
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata
    ) internal view returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            // only check if target is a contract if the call was successful and the return data is empty
            // otherwise we already know that it was a contract
            if (returndata.length == 0 && target.code.length == 0) {
                revert AddressEmptyCode(target);
            }
            return returndata;
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
     * revert reason or with a default {Errors.FailedCall} error.
     */
    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            return returndata;
        }
    }

    /**
     * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}.
     */
    function _revert(bytes memory returndata) private pure {
        // 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 ("memory-safe") {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert Errors.FailedCall();
        }
    }
}


pragma solidity ^0.8.20;




/**
 * @title SafeERC20
 * @dev Wrappers around ERC-20 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 {
    /**
     * @dev An operation with an ERC-20 token failed.
     */
    error SafeERC20FailedOperation(address token);

    /**
     * @dev Indicates a failed `decreaseAllowance` request.
     */
    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);

    /**
     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
    }

    /**
     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
     */
    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
    }

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     *
     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
     * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
     */
    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        forceApprove(token, spender, oldAllowance + value);
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
     * value, non-reverting calls are assumed to be successful.
     *
     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
     * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
     */
    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
        unchecked {
            uint256 currentAllowance = token.allowance(address(this), spender);
            if (currentAllowance < requestedDecrease) {
                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
            }
            forceApprove(token, spender, currentAllowance - requestedDecrease);
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
     * to be set to zero before setting it to a non-zero value, such as USDT.
     *
     * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
     * only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
     * set here.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));

        if (!_callOptionalReturnBool(token, approvalCall)) {
            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
            _callOptionalReturn(token, approvalCall);
        }
    }

    /**
     * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * Reverts if the returned value is other than `true`.
     */
    function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
        if (to.code.length == 0) {
            safeTransfer(token, to, value);
        } else if (!token.transferAndCall(to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
     * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * Reverts if the returned value is other than `true`.
     */
    function transferFromAndCallRelaxed(
        IERC1363 token,
        address from,
        address to,
        uint256 value,
        bytes memory data
    ) internal {
        if (to.code.length == 0) {
            safeTransferFrom(token, from, to, value);
        } else if (!token.transferFromAndCall(from, to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
     * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
     * once without retrying, and relies on the returned value to be true.
     *
     * Reverts if the returned value is other than `true`.
     */
    function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
        if (to.code.length == 0) {
            forceApprove(token, to, value);
        } else if (!token.approveAndCall(to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @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).
     *
     * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        uint256 returnSize;
        uint256 returnValue;
        assembly ("memory-safe") {
            let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
            // bubble errors
            if iszero(success) {
                let ptr := mload(0x40)
                returndatacopy(ptr, 0, returndatasize())
                revert(ptr, returndatasize())
            }
            returnSize := returndatasize()
            returnValue := mload(0)
        }

        if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @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).
     *
     * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        bool success;
        uint256 returnSize;
        uint256 returnValue;
        assembly ("memory-safe") {
            success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
            returnSize := returndatasize()
            returnValue := mload(0)
        }
        return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
    }
}


pragma solidity ^0.8.20;

/**
 * @dev External interface of AccessControl declared to support ERC-165 detection.
 */
interface IAccessControl {
    /**
     * @dev The `account` is missing a role.
     */
    error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);

    /**
     * @dev The caller of a function is not the expected one.
     *
     * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
     */
    error AccessControlBadConfirmation();

    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call. This account bears the admin role (for the granted role).
     * Expected in cases where the role was granted using the internal {AccessControl-_grantRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) external view returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `callerConfirmation`.
     */
    function renounceRole(bytes32 role, address callerConfirmation) external;
}


pragma solidity ^0.8.20;


/**
 * @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.
 */
interface IAccessControlEnumerable is IAccessControl {
    /**
     * @dev Returns one of the accounts that have `role`. `index` must be a
     * value between 0 and {getRoleMemberCount}, non-inclusive.
     *
     * Role bearers are not sorted in any particular way, and their ordering may
     * change at any point.
     *
     * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
     * you perform all queries on the same block. See the following
     * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
     * for more information.
     */
    function getRoleMember(bytes32 role, uint256 index) external view returns (address);

    /**
     * @dev Returns the number of accounts that have `role`. Can be used
     * together with {getRoleMember} to enumerate all bearers of a role.
     */
    function getRoleMemberCount(bytes32 role) external view returns (uint256);
}


pragma solidity ^0.8.20;

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

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}


pragma solidity ^0.8.20;


/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

pragma solidity ^0.8.20;




/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms. This is a lightweight version that doesn't allow enumerating role
 * members except through off-chain means by accessing the contract event logs. Some
 * applications may benefit from on-chain enumerability, for those cases see
 * {AccessControlEnumerable}.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```solidity
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```solidity
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
 * to enforce additional security measures for this role.
 */
abstract contract AccessControl is Context, IAccessControl, ERC165 {
    struct RoleData {
        mapping(address account => bool) hasRole;
        bytes32 adminRole;
    }

    mapping(bytes32 role => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with an {AccessControlUnauthorizedAccount} error including the required role.
     */
    modifier onlyRole(bytes32 role) {
        _checkRole(role);
        _;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) public view virtual returns (bool) {
        return _roles[role].hasRole[account];
    }

    /**
     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
     * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
     */
    function _checkRole(bytes32 role) internal view virtual {
        _checkRole(role, _msgSender());
    }

    /**
     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
     * is missing `role`.
     */
    function _checkRole(bytes32 role, address account) internal view virtual {
        if (!hasRole(role, account)) {
            revert AccessControlUnauthorizedAccount(account, role);
        }
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {
        return _roles[role].adminRole;
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     *
     * May emit a {RoleGranted} event.
     */
    function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
        _grantRole(role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     *
     * May emit a {RoleRevoked} event.
     */
    function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
        _revokeRole(role, account);
    }

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been revoked `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `callerConfirmation`.
     *
     * May emit a {RoleRevoked} event.
     */
    function renounceRole(bytes32 role, address callerConfirmation) public virtual {
        if (callerConfirmation != _msgSender()) {
            revert AccessControlBadConfirmation();
        }

        _revokeRole(role, callerConfirmation);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.
     *
     * Emits a {RoleAdminChanged} event.
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        bytes32 previousAdminRole = getRoleAdmin(role);
        _roles[role].adminRole = adminRole;
        emit RoleAdminChanged(role, previousAdminRole, adminRole);
    }

    /**
     * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleGranted} event.
     */
    function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
        if (!hasRole(role, account)) {
            _roles[role].hasRole[account] = true;
            emit RoleGranted(role, account, _msgSender());
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleRevoked} event.
     */
    function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
        if (hasRole(role, account)) {
            _roles[role].hasRole[account] = false;
            emit RoleRevoked(role, account, _msgSender());
            return true;
        } else {
            return false;
        }
    }
}


// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.

pragma solidity ^0.8.20;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```solidity
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 *
 * [WARNING]
 * ====
 * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
 * unusable.
 * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
 *
 * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
 * array of EnumerableSet.
 * ====
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;
        // Position is the index of the value in the `values` array plus 1.
        // Position 0 is used to mean a value is not in the set.
        mapping(bytes32 value => uint256) _positions;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._positions[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We cache the value's position to prevent multiple reads from the same storage slot
        uint256 position = set._positions[value];

        if (position != 0) {
            // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 valueIndex = position - 1;
            uint256 lastIndex = set._values.length - 1;

            if (valueIndex != lastIndex) {
                bytes32 lastValue = set._values[lastIndex];

                // Move the lastValue to the index where the value to delete is
                set._values[valueIndex] = lastValue;
                // Update the tracked position of the lastValue (that was just moved)
                set._positions[lastValue] = position;
            }

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the tracked position for the deleted slot
            delete set._positions[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._positions[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        return set._values[index];
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function _values(Set storage set) private view returns (bytes32[] memory) {
        return set._values;
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, index);
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
        bytes32[] memory store = _values(set._inner);
        bytes32[] memory result;

        assembly ("memory-safe") {
            result := store
        }

        return result;
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint160(uint256(_at(set._inner, index))));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(AddressSet storage set) internal view returns (address[] memory) {
        bytes32[] memory store = _values(set._inner);
        address[] memory result;

        assembly ("memory-safe") {
            result := store
        }

        return result;
    }

    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(UintSet storage set) internal view returns (uint256[] memory) {
        bytes32[] memory store = _values(set._inner);
        uint256[] memory result;

        assembly ("memory-safe") {
            result := store
        }

        return result;
    }
}


pragma solidity ^0.8.20;




/**
 * @dev Extension of {AccessControl} that allows enumerating the members of each role.
 */
abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {
    using EnumerableSet for EnumerableSet.AddressSet;

    mapping(bytes32 role => EnumerableSet.AddressSet) private _roleMembers;

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @dev Returns one of the accounts that have `role`. `index` must be a
     * value between 0 and {getRoleMemberCount}, non-inclusive.
     *
     * Role bearers are not sorted in any particular way, and their ordering may
     * change at any point.
     *
     * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
     * you perform all queries on the same block. See the following
     * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
     * for more information.
     */
    function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {
        return _roleMembers[role].at(index);
    }

    /**
     * @dev Returns the number of accounts that have `role`. Can be used
     * together with {getRoleMember} to enumerate all bearers of a role.
     */
    function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {
        return _roleMembers[role].length();
    }

    /**
     * @dev Return all accounts that have `role`
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function getRoleMembers(bytes32 role) public view virtual returns (address[] memory) {
        return _roleMembers[role].values();
    }

    /**
     * @dev Overload {AccessControl-_grantRole} to track enumerable memberships
     */
    function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {
        bool granted = super._grantRole(role, account);
        if (granted) {
            _roleMembers[role].add(account);
        }
        return granted;
    }

    /**
     * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships
     */
    function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {
        bool revoked = super._revokeRole(role, account);
        if (revoked) {
            _roleMembers[role].remove(account);
        }
        return revoked;
    }
}


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 making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

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

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

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == _ENTERED;
    }
}


pragma solidity ^0.8.20;


/**
 * @dev Interface for the optional metadata functions from the ERC-20 standard.
 */
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);
}





//@author 0xPhant0m based on Ohm Bond Depository and Bond Protocol

pragma solidity ^0.8.27;  





contract BondDepository is AccessControlEnumerable, ReentrancyGuard {
  using SafeERC20 for IERC20;

    bytes32 public constant AUCTIONEER_ROLE = keccak256("AUCTIONEER_ROLE");
    bytes32 public constant TOKEN_WHITELISTER_ROLE = keccak256("TOKEN_WHITELISTER_ROLE");
    bytes32 public constant EMERGENCY_ADMIN_ROLE = keccak256("EMERGENCY_ADMIN_ROLE");

    bool public paused;


    event ContractPaused(address indexed by);
    event ContractUnpaused(address indexed by);
    event newBondCreated(uint256 indexed id, address indexed payoutToken, address indexed quoteToken, uint256 initialPrice );
    event BondEnded(uint256 indexed id);
    event addedAuctioneer(address _auctioneer, address payoutToken);
    event removeAuctioneer(address auctioneer);
    event MarketTransferred( uint256 marketId, address owner, address newAuctioneer);
    event BondDeposited( address indexed user,  uint256 indexed marketId,  uint256 depositAmount, uint256 totalOwed, uint256 bondPrice );
    event QuoteTokensWithdrawn( uint256 indexed marketId, address indexed auctioneer, uint256 amount, uint256 daoFee );
    event FeeUpdated (uint256 oldFee, uint256 basePoints);
    event TokenUnwhitelisted( address _token);
    event TokenWhitelisted( address _token);
 


    uint256 public marketCounter;
    address [] public _payoutTokens;
    Terms[] public terms;
    mapping(uint256 => Adjust) public adjustments;
    mapping (address => bool) _whitelistedAuctioneer;
    mapping (address => bool) _whitelistedToken;
    mapping(uint256 => address) public marketsToAuctioneers;
    mapping(address => uint256[]) public marketsForQuote;
    mapping(address => uint256[]) public marketsForPayout;
    mapping( address => Bond[]) public bondInfo; 
    address public immutable mSig;
    uint256 public feeToDao;
    uint256 public constant MAX_FEE = 1000; 


 // Info for creating new bonds
    struct Terms {
        address quoteToken; //token requested 
        address payoutToken; //token to be redeemed
        uint256 amountToBond; //Amount of payout Tokens dedicated to this request
        uint256 totalDebt;
        uint256 controlVariable; // scaling variable for price
        uint256 minimumPrice; // vs principle value
        uint256 maxDebt; // 9 decimal debt ratio, max % total supply created as debt
        uint256 maxPayout; // in thousandths of a %. i.e. 500 = 0.5%
        uint256 quoteTokensRaised; 
        uint256 lastDecay; //block.timestamp of last decay (i.e last deposit)
        uint32 bondEnds; //Unix Timestamp of when the offer ends.
        uint32 vestingTerm; // How long each bond should vest for in seconds
    }

    struct Bond {
        address tokenBonded; //token to be distributed
        uint256 amountOwed; //amount of tokens owed to Bonder
        uint256 pricePaid; //price paid in PayoutToken
        uint256 marketId; //Which market does this belong
        uint32 startTime; // block timestamp
        uint32 endTime; //timestamp


    }

      struct Adjust {
        bool add; // addition or subtraction
        uint rate; // increment
        uint target; // BCV when adjustment finished
        uint buffer; // minimum length (in blocks) between adjustments
        uint lastBlock; // block when last adjustment made
      }

        //Strictly for front-end optimization
     struct BondMarketInfo {
        address quoteToken;
        address payoutToken;
        uint256 price;
        uint256 maxPayout;
        uint256 vestingTerm;
        uint256 amountToBond;
        address auctioneer;
        bool isLive;
        uint256 totalDebt;
}

    constructor(address _mSig){
      if (_mSig == address (0)) revert ("Invalid address");
        mSig = _mSig;
     _grantRole(DEFAULT_ADMIN_ROLE, mSig);
       _grantRole(EMERGENCY_ADMIN_ROLE, mSig);
        _grantRole(TOKEN_WHITELISTER_ROLE, mSig);

    }

                                         /*================================= Auctioneer FUNCTIONS =================================*/

    function newBond( 
    address payoutToken_, 
    IERC20 _quoteToken,
    uint256 [4] memory _terms,  // [amountToBond, controlVariable, minimumPrice, maxDebt]
    uint32 [2] memory _vestingTerms  // [bondEnds, vestingTerm]
) external onlyRole(AUCTIONEER_ROLE) whenNotPaused returns (uint256 marketID) {
    // Address validations
    require(payoutToken_ != address(0), "Invalid payout token");
    require(address(_quoteToken) != address(0), "Invalid quote token");
    require(address(_quoteToken) != payoutToken_, "Tokens must be different");
    require(_whitelistedToken[payoutToken_], "Token not whitelisted");
    require(!auctioneerHasMarketForQuote(msg.sender, address(_quoteToken)), "Already has market for quote token");
    
    // Time validations
    require(_vestingTerms[0] > block.timestamp, "Bond end too early");
    
    // Parameter validations
    require(_terms[0] > 0, "Amount must be > 0");
    require(_terms[1] > 0, "Control variable must be > 0");
    require(_terms[2] > 0, "Minimum price must be > 0");
    require(_terms[3] > 0, "Max debt must be > 0");
    
    uint256 secondsToConclusion = _vestingTerms[0] - block.timestamp;
    require(secondsToConclusion > 0, "Invalid vesting period");
    
    // Calculate max payout with better precision
    uint256 _maxPayout = (_terms[3] * 1800) / 10000;  // 18% of max debt
    _maxPayout = (_maxPayout * 1e18) / secondsToConclusion;  // Scale by time
    
    // Transfer payout tokens (use amountToBond, not controlVariable)
    IERC20(payoutToken_).safeTransferFrom(msg.sender, address(this), _terms[0]);
    
    // Create market
    terms.push(Terms({
        quoteToken: address(_quoteToken),
        payoutToken: payoutToken_,
        amountToBond: _terms[0],
        controlVariable: _terms[1],
        minimumPrice: _terms[2],
        maxDebt: _terms[3],
        maxPayout: _maxPayout,
        quoteTokensRaised: 0,
        lastDecay: block.timestamp,
        bondEnds: _vestingTerms[0],
        vestingTerm: _vestingTerms[1],
        totalDebt: 0
    }));
    
    // Market tracking
    uint256 marketId = marketCounter;
    marketsForPayout[payoutToken_].push(marketId);
    marketsForQuote[address(_quoteToken)].push(marketId);
    marketsToAuctioneers[marketId] = msg.sender;
    
    ++marketCounter;
    emit newBondCreated(marketId, payoutToken_, address(_quoteToken), _terms[1]);
    
    return marketId;
}
  
    function closeBond(uint256 _id) external   onlyRole(AUCTIONEER_ROLE) 
        whenNotPaused  {
        if (marketsToAuctioneers[_id] != msg.sender) revert ("Not your Bond");
        terms[_id].bondEnds = uint32(block.timestamp);

        uint256 amountLeft = terms[_id].amountToBond - terms[_id].totalDebt;

         IERC20(terms[_id].payoutToken).safeTransfer(msg.sender, amountLeft);
 
        emit BondEnded(_id);
        }

        function withdrawQuoteTokens(uint256 _id) external onlyRole(AUCTIONEER_ROLE) whenNotPaused {
    // Ensure only the original auctioneer for this market can withdraw
    require(marketsToAuctioneers[_id] == msg.sender, "Not market's auctioneer");

    // Ensure bond has ended
    require(block.timestamp > terms[_id].bondEnds, "Bond not yet concluded");

    // Get the quote token and its balance
    address quoteToken = terms[_id].quoteToken;
    uint256 balance = terms[_id].quoteTokensRaised;

    // Calculate DAO fee if applicable
    uint256 daoFee = 0;
    if (feeToDao > 0) {
        daoFee = (balance * feeToDao) / 10000; // Assuming feeToDao is in basis points
        balance -= daoFee;
    }

    // safeTransfer quote tokens to auctioneer
    IERC20(quoteToken).safeTransfer(msg.sender, balance);

    // safeTransfer DAO fee if applicable
    if (daoFee > 0) {
        IERC20(quoteToken).safeTransfer(mSig, daoFee);
    }

    emit QuoteTokensWithdrawn(_id, msg.sender, balance, daoFee);
}
    
    function transferMarket(uint256 marketId, address newAuctioneer) external {
    require(marketsToAuctioneers[marketId] == msg.sender, "Not market owner");
    require(hasRole(AUCTIONEER_ROLE, newAuctioneer), "Not auctioneer");
    marketsToAuctioneers[marketId] = newAuctioneer;
    emit MarketTransferred(marketId, msg.sender, newAuctioneer);
}

                             /*================================= User FUNCTIONS =================================*/
    function deposit(uint256 _id, uint256 amount, address user) public nonReentrant {
        // Early validation checks
        require(user != address(0), "Invalid user address");
        require(_id < terms.length, "Invalid market ID");
    
        // Retrieve the specific bond terms
        Terms storage term = terms[_id];

        // Comprehensive bond availability checks
        require(block.timestamp <= term.bondEnds, "Bond has ended");
        require(term.totalDebt < term.maxDebt, "Maximum bond capacity reached");

        // Decimal-aware minimum deposit calculation
        uint8 quoteDecimals = IERC20Metadata(address(term.quoteToken)).decimals();
        uint256 minimumDeposit = calculateMinimumDeposit(quoteDecimals);

        // Deposit amount validations
        require(amount >= minimumDeposit, "Deposit below minimum threshold");
        require(amount <= term.maxPayout, "Deposit exceeds maximum allowed");

        // Reentrancy protection pattern
        // Decay debt before any state changes
        _tune(_id);
        _decayDebt(_id);

        // Transfer tokens with safety checks
        IERC20 quoteToken = IERC20(term.quoteToken);
        uint256 balanceBefore = quoteToken.balanceOf(address(this));
        quoteToken.safeTransferFrom(msg.sender, address(this), amount); 
        uint256 balanceAfter = quoteToken.balanceOf(address(this));
        require(balanceAfter - balanceBefore == amount, "Incorrect transfer amount");
        terms[_id].quoteTokensRaised += amount;
        // Calculate bond price with internal function
        uint256 price = _marketPrice(_id);

        // Precise total owed calculation
        uint256 totalOwed = calculateTotalOwed(amount, price);
        address payoutToken = term.payoutToken;

        // Validate total owed against remaining bond capacity
        require(term.totalDebt + totalOwed <= term.maxDebt, "Exceeds maximum bond debt");

        // Create bond record with comprehensive details
        bondInfo[user].push(Bond({
            tokenBonded: payoutToken,
            amountOwed: totalOwed, 
            pricePaid: price,
            marketId: _id,
            startTime: uint32(block.timestamp),
            endTime: uint32(term.vestingTerm + block.timestamp)
        }));

        // Update total debt
        term.totalDebt += totalOwed;

        emit BondDeposited(user, _id, amount, totalOwed, price);
    }

  function redeem(uint256 _id, address user) external nonReentrant returns (uint256 amountRedeemed) {
    uint256 length = bondInfo[user].length; 
    uint256 totalRedeemed = 0;

    // Iterate backwards to safely remove elements
    for (uint256 i = length; i > 0;) {
        i--;  // decrement here to avoid underflow
        
        Bond storage currentBond = bondInfo[user][i];
        if (currentBond.marketId == _id) {
            uint256 amount = calculateLinearPayout(user, i);
            
            if (amount > 0) {
                // Update state before transfer
                currentBond.amountOwed -= amount;
                totalRedeemed += amount;
                
                // Perform transfer
                IERC20(terms[_id].payoutToken).safeTransfer(user, amount);
                
                // If fully redeemed, remove bond
                if (currentBond.amountOwed == 0) {
                    // Move the last element to current position and pop
                    if (i != bondInfo[user].length - 1) {
                        bondInfo[user][i] = bondInfo[user][bondInfo[user].length - 1];
                    }
                    bondInfo[user].pop();
                }
            }
        }
    }
    
    return totalRedeemed;
}



    
  
                           /*================================= ADMIN FUNCTIONS =================================*/

    function grantAuctioneerRole(address _auctioneer) 
        external 
        onlyRole(DEFAULT_ADMIN_ROLE) 
    {
        // Additional validation
        require(_auctioneer != address(0), "Invalid auctioneer address");
        require(!hasRole(AUCTIONEER_ROLE, _auctioneer), "Already an auctioneer");

        _grantRole(AUCTIONEER_ROLE, _auctioneer);
        _whitelistedAuctioneer[_auctioneer] = true;
        emit RoleGranted(AUCTIONEER_ROLE, _auctioneer, msg.sender);
    }

    function revokeAuctioneerRole(address _auctioneer) 
        external 
        onlyRole(DEFAULT_ADMIN_ROLE) 
    {
        _revokeRole(AUCTIONEER_ROLE, _auctioneer);
        _whitelistedAuctioneer[_auctioneer] = false;
        emit RoleRevoked(AUCTIONEER_ROLE, _auctioneer, msg.sender);
    }

     function whitelistToken(address _token) 
        external 
        onlyRole(TOKEN_WHITELISTER_ROLE) 
    {
        require(_token != address(0), "Invalid token address");
        require(!_whitelistedToken[_token], "Token already whitelisted");

        // Additional token validation
        try IERC20Metadata(_token).decimals() returns (uint8) {
            _whitelistedToken[_token] = true;
            _payoutTokens.push(_token);
        } catch {
            revert("Invalid ERC20 token");
        }
    }

    function unwhitelistToken(address _token) external onlyRole(TOKEN_WHITELISTER_ROLE) {
    require(_whitelistedToken[_token], "Token not whitelisted");
    _whitelistedToken[_token] = false;
    emit TokenUnwhitelisted(_token);
}
    

     function pauseContract() 
        external 
        onlyRole(EMERGENCY_ADMIN_ROLE) 
    {
        paused = true;
        emit ContractPaused(msg.sender);
    }

    function unpauseContract() 
        external 
        onlyRole(EMERGENCY_ADMIN_ROLE) 
    {
        paused = false;
        emit ContractUnpaused(msg.sender);
    }

   function setFeetoDao(uint32 basePoints) external onlyRole(DEFAULT_ADMIN_ROLE) {
    require(basePoints <= MAX_FEE, "Fee too high");
    uint256 oldFee = feeToDao;
    feeToDao = basePoints;
    emit FeeUpdated(oldFee, basePoints);
}

                            /*================================= View Functions =================================*/

    function getMarketsForQuote(address quoteToken) external view returns(uint256[] memory) {
         return marketsForQuote[quoteToken];
    }

    function getMarketsForPayout(address payout) external view returns(uint256[] memory) {
           return marketsForPayout[payout];
    }

    function getMarketsForUser(address user) external view returns(uint256[] memory) {
            uint256[] memory userMarkets = new uint256[](bondInfo[user].length);
    for (uint256 i = 0; i < bondInfo[user].length; i++) {
        userMarkets[i] = bondInfo[user][i].marketId;
    }
    return userMarkets;
    }
    
     function isLive(uint256 id_) public view returns (bool) {
         return block.timestamp <= terms[id_].bondEnds && terms[id_].totalDebt < terms[id_].maxDebt;
}
     
    
    function bondPrice(uint256 id_) public view returns(uint256) {
         return _trueBondPrice(id_);

  }

  
    function isAuctioneer(address account) external view returns (bool) {
        return hasRole(AUCTIONEER_ROLE, account);
    }

    function calculateLinearPayout(address user, uint256 _bondId) public view returns (uint256) {
    Bond memory bond = bondInfo[user][_bondId];
    Terms memory term = terms[bond.marketId];

    // Check if bond is active
    if (block.timestamp < bond.startTime) {
        return 0;
    }

    // Calculate total vesting duration
    uint256 vestingTerm = term.vestingTerm;

    // Calculate time elapsed since bond start
    uint256 timeElapsed = block.timestamp > bond.endTime 
        ? vestingTerm 
        : block.timestamp - bond.startTime;

    // Calculate tokens per second
    uint256 tokensPerSecond = bond.amountOwed / vestingTerm;

    // Calculate current claimable amount
    uint256 currentClaimable = tokensPerSecond * timeElapsed;

    // Ensure we don't claim more than the total owed
    if (currentClaimable > bond.amountOwed) {
        currentClaimable = bond.amountOwed;
    }

    return currentClaimable;
}


    function getBondMarketInfo(uint256 marketId) public view returns (BondMarketInfo memory) {
        Terms storage term = terms[marketId];
        
        return BondMarketInfo({
            quoteToken: term.quoteToken,
            payoutToken: term.payoutToken,
            price: _trueBondPrice(marketId),
            maxPayout: term.maxPayout,
            vestingTerm: term.vestingTerm, 
            amountToBond: term.amountToBond,
            auctioneer: marketsToAuctioneers[marketId],
            isLive: isLive(marketId),
            totalDebt: term.totalDebt
        });
    }

    function getBondMarketInfoBatch(uint256[] calldata marketIds) external view returns (BondMarketInfo[] memory) {
    BondMarketInfo[] memory markets = new BondMarketInfo[](marketIds.length);
    
    for (uint256 i = 0; i < marketIds.length; i++) {
        markets[i] = getBondMarketInfo(marketIds[i]);
    }
    
    return markets;
}

  function payoutFor(address user, uint256 _bondId) public view returns (uint256 amount) {
    return calculateLinearPayout(user, _bondId);
}

   function isMature(address user, uint256 _bondId) public view returns (bool) {
    Bond memory bond = bondInfo[user][_bondId];
    return block.timestamp >= bond.endTime;
}
                             /*================================= Internal Functions =================================*/


    function _decayDebt(uint256 _id) internal {
    Terms storage term = terms[_id];

    // Get current debt and control variable
    uint256 currentDebt = term.totalDebt;
    if (currentDebt == 0) return;

    // Get seconds since market was created (block.timestamp - (bondEnds - length))
    uint256 secondsSinceLastDecay = block.timestamp - term.lastDecay;
    
    // Return if market not active
    if (secondsSinceLastDecay == 0) return;

    // Calculate decay rate based on target vesting time
    uint256 decay = currentDebt * secondsSinceLastDecay / term.vestingTerm;
    
    // Update stored debt
    term.totalDebt = currentDebt - decay;
    term.lastDecay = uint32(block.timestamp);
}


        function _tune(uint256 _id) internal{
            if (block.timestamp > adjustments[_id].lastBlock + adjustments[_id].buffer) {
        Terms storage term = terms[_id];
        
        if (adjustments[_id].add) {
            term.controlVariable += adjustments[_id].rate;
            
            if (term.controlVariable >= adjustments[_id].target) {
                term.controlVariable = adjustments[_id].target;
            }
        } else {
            term.controlVariable -= adjustments[_id].rate;
            
            if (term.controlVariable <= adjustments[_id].target) {
                term.controlVariable = adjustments[_id].target;
            }
        }
        
        adjustments[_id].lastBlock = uint32(block.timestamp);
    }

        }

    function _marketPrice(uint256 _id) internal view returns (uint256 price) {
    Terms memory term = terms[_id];
    
    // Get decimals for both tokens for precise calculations
    uint8 payoutDecimals = IERC20Metadata(address(term.payoutToken)).decimals();
    uint8 quoteDecimals = IERC20Metadata(address(term.quoteToken)).decimals();
    
    // Get current control variable and debt ratio
    uint256 currentCV = _currentControlVariable(_id);
    uint256 debtRatio = _debtRatio(_id);
    
    // Scale up before division to maintain precision
    // Use a higher precision factor (1e36) to prevent overflow while maintaining precision
    uint256 scaledPrice = (currentCV * debtRatio) * (10 ** (36 - payoutDecimals - quoteDecimals));
    
    // Perform division last to minimize precision loss
    // Divide by 1e18 twice because debtRatio is scaled by 1e18 and we want final precision of 1e18
    price = scaledPrice / 1e18 / 1e18;
    
    // Apply minimum price check after all calculations
    if (price < term.minimumPrice) {
        price = term.minimumPrice;
    }
    
    // Add safety check for maximum price to prevent unreasonable values
    // This value should be adjusted based on your specific needs
    require(price <= type(uint256).max / 1e18, "Price overflow");
}

        
        function _trueBondPrice(uint256 _id) internal view returns(uint256 price){
            
            price = _marketPrice(_id);
        }

     function _debtRatio(uint256 _id) internal view returns (uint256) {
  
    Terms memory term = terms[_id];

    if (term.quoteTokensRaised == 0) { 
        return 0;
    }
    
    // Get decimals for precise calculation
    uint8 quoteDecimals = uint8(IERC20Metadata(address(term.quoteToken)).decimals());
    uint8 payoutDecimals = uint8(IERC20Metadata(address(term.payoutToken)).decimals());

    // Normalize totalDebt to 18 decimals (totalDebt is in payoutToken)
    uint256 totalDebt = term.totalDebt * (10**(18 - payoutDecimals));
    
    // Normalize quote tokens raised to 18 decimals
    uint256 quoteBalance = term.quoteTokensRaised * (10 ** (18 - quoteDecimals));
    
    // Prevent division by zero
    if (quoteBalance == 0) {
        return type(uint256).max; // Maximum possible debt ratio
    }

    // Calculate debt ratio with high precision
    // Result is scaled to 1e18
    uint256 debtRatio = (totalDebt * 1e18) / quoteBalance;
    
    return debtRatio;
}

         function _currentControlVariable(uint256 _id) internal view returns (uint256) {
    Terms memory term = terms[_id];
    Adjust memory adjustment = adjustments[_id];

    // Base control variable
    uint256 baseCV = term.controlVariable;

    // Market-adaptive decay calculation
    uint256 currentDebtRatio = _debtRatio(_id);
    uint256 timeSinceBondStart = block.timestamp > term.bondEnds 
        ? block.timestamp - term.bondEnds 
        : 0;
    
    // Adaptive decay rate based on debt ratio
    // Higher debt ratio accelerates decay
    uint256 adaptiveDecayRate = (currentDebtRatio * 1e18) / term.maxDebt;
    
    // Calculate decay amount
    uint256 decayAmount = (baseCV * adaptiveDecayRate) / (timeSinceBondStart + 1);

    // Apply ongoing adjustment if within adjustment window
    if (block.timestamp <= adjustment.lastBlock + adjustment.buffer) {
        if (adjustment.add) {
            // Increasing control variable
            baseCV += adjustment.rate;
            
            // Cap at target if exceeded
            if (baseCV > adjustment.target) {
                baseCV = adjustment.target;
            }
        } else {
            // Decreasing control variable
            baseCV -= adjustment.rate;
            
            // Floor at target if fallen below
            if (baseCV < adjustment.target) {
                baseCV = adjustment.target;
            }
        }
    }

    // Apply decay
    if (baseCV > decayAmount) {
        return baseCV - decayAmount;
    }
    
    return 0;
}

    // Helper function for minimum deposit calculation
        function calculateMinimumDeposit(uint8 decimals) internal pure returns (uint256) {
    // Ensures meaningful deposit across different token decimal configurations
          if (decimals > 2) {
          return 10 ** (decimals - 2);  // 1% of smallest token unit
    }
        return 1;  // Fallback for tokens with very few decimals
}

        // Helper function for precise owed calculation
        function calculateTotalOwed(uint256 amount, uint256 price) internal pure returns (uint256) {

         return (amount * price) / 1e18;
}

    function auctioneerHasMarketForQuote(address auctioneer, address quoteToken) public view returns (bool) {
    uint256[] memory markets = marketsForQuote[quoteToken];
    for(uint256 i = 0; i < markets.length; i++) {
        if(marketsToAuctioneers[markets[i]] == auctioneer) {
            return true;
        }
    }
    return false;
}

          modifier whenNotPaused() {
        require(!paused, "Contract is paused");
        _;
    }
 
}

Contract ABI

[{"inputs":[{"internalType":"address","name":"_mSig","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"marketId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"depositAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalOwed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"bondPrice","type":"uint256"}],"name":"BondDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"BondEnded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"by","type":"address"}],"name":"ContractPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"by","type":"address"}],"name":"ContractUnpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"basePoints","type":"uint256"}],"name":"FeeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"marketId","type":"uint256"},{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"address","name":"newAuctioneer","type":"address"}],"name":"MarketTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"marketId","type":"uint256"},{"indexed":true,"internalType":"address","name":"auctioneer","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"daoFee","type":"uint256"}],"name":"QuoteTokensWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_token","type":"address"}],"name":"TokenUnwhitelisted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_token","type":"address"}],"name":"TokenWhitelisted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_auctioneer","type":"address"},{"indexed":false,"internalType":"address","name":"payoutToken","type":"address"}],"name":"addedAuctioneer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"payoutToken","type":"address"},{"indexed":true,"internalType":"address","name":"quoteToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"initialPrice","type":"uint256"}],"name":"newBondCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"auctioneer","type":"address"}],"name":"removeAuctioneer","type":"event"},{"inputs":[],"name":"AUCTIONEER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EMERGENCY_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOKEN_WHITELISTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"_payoutTokens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"adjustments","outputs":[{"internalType":"bool","name":"add","type":"bool"},{"internalType":"uint256","name":"rate","type":"uint256"},{"internalType":"uint256","name":"target","type":"uint256"},{"internalType":"uint256","name":"buffer","type":"uint256"},{"internalType":"uint256","name":"lastBlock","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"auctioneer","type":"address"},{"internalType":"address","name":"quoteToken","type":"address"}],"name":"auctioneerHasMarketForQuote","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"bondInfo","outputs":[{"internalType":"address","name":"tokenBonded","type":"address"},{"internalType":"uint256","name":"amountOwed","type":"uint256"},{"internalType":"uint256","name":"pricePaid","type":"uint256"},{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"bondPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"_bondId","type":"uint256"}],"name":"calculateLinearPayout","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"closeBond","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"user","type":"address"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeToDao","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"}],"name":"getBondMarketInfo","outputs":[{"components":[{"internalType":"address","name":"quoteToken","type":"address"},{"internalType":"address","name":"payoutToken","type":"address"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"maxPayout","type":"uint256"},{"internalType":"uint256","name":"vestingTerm","type":"uint256"},{"internalType":"uint256","name":"amountToBond","type":"uint256"},{"internalType":"address","name":"auctioneer","type":"address"},{"internalType":"bool","name":"isLive","type":"bool"},{"internalType":"uint256","name":"totalDebt","type":"uint256"}],"internalType":"struct BondDepository.BondMarketInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"marketIds","type":"uint256[]"}],"name":"getBondMarketInfoBatch","outputs":[{"components":[{"internalType":"address","name":"quoteToken","type":"address"},{"internalType":"address","name":"payoutToken","type":"address"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"maxPayout","type":"uint256"},{"internalType":"uint256","name":"vestingTerm","type":"uint256"},{"internalType":"uint256","name":"amountToBond","type":"uint256"},{"internalType":"address","name":"auctioneer","type":"address"},{"internalType":"bool","name":"isLive","type":"bool"},{"internalType":"uint256","name":"totalDebt","type":"uint256"}],"internalType":"struct BondDepository.BondMarketInfo[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"payout","type":"address"}],"name":"getMarketsForPayout","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"quoteToken","type":"address"}],"name":"getMarketsForQuote","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getMarketsForUser","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMembers","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_auctioneer","type":"address"}],"name":"grantAuctioneerRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isAuctioneer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"isLive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"_bondId","type":"uint256"}],"name":"isMature","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mSig","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"marketCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"marketsForPayout","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"marketsForQuote","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"marketsToAuctioneers","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"payoutToken_","type":"address"},{"internalType":"contract IERC20","name":"_quoteToken","type":"address"},{"internalType":"uint256[4]","name":"_terms","type":"uint256[4]"},{"internalType":"uint32[2]","name":"_vestingTerms","type":"uint32[2]"}],"name":"newBond","outputs":[{"internalType":"uint256","name":"marketID","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pauseContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"_bondId","type":"uint256"}],"name":"payoutFor","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"},{"internalType":"address","name":"user","type":"address"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"amountRedeemed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_auctioneer","type":"address"}],"name":"revokeAuctioneerRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"basePoints","type":"uint32"}],"name":"setFeetoDao","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"terms","outputs":[{"internalType":"address","name":"quoteToken","type":"address"},{"internalType":"address","name":"payoutToken","type":"address"},{"internalType":"uint256","name":"amountToBond","type":"uint256"},{"internalType":"uint256","name":"totalDebt","type":"uint256"},{"internalType":"uint256","name":"controlVariable","type":"uint256"},{"internalType":"uint256","name":"minimumPrice","type":"uint256"},{"internalType":"uint256","name":"maxDebt","type":"uint256"},{"internalType":"uint256","name":"maxPayout","type":"uint256"},{"internalType":"uint256","name":"quoteTokensRaised","type":"uint256"},{"internalType":"uint256","name":"lastDecay","type":"uint256"},{"internalType":"uint32","name":"bondEnds","type":"uint32"},{"internalType":"uint32","name":"vestingTerm","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"marketId","type":"uint256"},{"internalType":"address","name":"newAuctioneer","type":"address"}],"name":"transferMarket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpauseContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"unwhitelistToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"whitelistToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"withdrawQuoteTokens","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60a060405234801561000f575f5ffd5b5060405161445338038061445383398101604081905261002e91610237565b60016002556001600160a01b03811661007f5760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015260640160405180910390fd5b6001600160a01b0381166080819052610099905f90610106565b506100cc7f5358bcfd81d1ef3da152b1755e1c3c6739686fa7e83dbcad0071568cc4b73a6360805161010660201b60201c565b506100ff7fd5b31c46cc75555bed852936261f4e95cbe813f3d32342d2d830a8fb4561ff8e60805161010660201b60201c565b505061025d565b5f80610112848461013c565b90508015610133575f84815260016020526040902061013190846101e3565b505b90505b92915050565b5f828152602081815260408083206001600160a01b038516845290915281205460ff166101dc575f838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556101943390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610136565b505f610136565b5f610133836001600160a01b0384165f8181526001830160205260408120546101dc57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610136565b5f60208284031215610247575f5ffd5b81516001600160a01b0381168114610133575f5ffd5b6080516141d761027c5f395f81816107e00152611eb901526141d75ff3fe608060405234801561000f575f5ffd5b50600436106102cb575f3560e01c806391de4d071161017b578063c5f0d05c116100e4578063d547741f1161009e578063ddb2924711610079578063ddb29247146107a0578063ea5e0c60146107b3578063ed421a9c146107db578063f9a6466414610802575f5ffd5b8063d547741f14610771578063d627d25e14610784578063d918a16e14610797575f5ffd5b8063c5f0d05c146106fe578063c8558f1b14610711578063ca15c87314610724578063cfe9232b14610737578063d04cffeb1461074b578063d1af1fbc1461075e575f5ffd5b8063b33712c511610135578063b33712c5146105dd578063bc063e1a146105e5578063bc3b2b12146105ee578063be32ee2614610658578063c0680e201461066b578063c0aa0e8a1461067e575f5ffd5b806391de4d071461056a5780639b299d9a1461057d5780639cd85b5b14610590578063a217fddf146105a3578063a3246ad3146105aa578063b2f5de94146105ca575f5ffd5b806336568abe116102375780637b30564e116101f15780638dbdbe6d116101cc5780638dbdbe6d146104f25780639010d07c14610505578063909b2bb81461053057806391d1485414610557575f5ffd5b80637b30564e146104795780637bde82f21461048c5780638ad59c701461049f575f5ffd5b806336568abe14610404578063439766ce146104175780635c975abb1461041f5780636247f6f21461042c5780636e76fc8f1461043f578063725dafe014610466575f5ffd5b8063172c44ec11610288578063172c44ec1461038d5780631b014e85146103a057806324760807146103b3578063248a9ca3146103bc57806327507458146103de5780632f2ff15d146103f1575f5ffd5b806301ffc9a7146102cf57806306b40ea3146102f75780630868335e146103185780630fb81eb4146103385780631227b4021461034d578063154347b51461036d575b5f5ffd5b6102e26102dd366004613af2565b610815565b60405190151581526020015b60405180910390f35b61030a610305366004613b2d565b61083f565b6040519081526020016102ee565b61032b610326366004613b57565b61086a565b6040516102ee9190613c39565b61034b610346366004613c87565b61091a565b005b61036061035b366004613c87565b610aaf565b6040516102ee9190613c9e565b61038061037b366004613cad565b610b84565b6040516102ee9190613cc8565b61030a61039b366004613c87565b610bed565b6103806103ae366004613cad565b610bf7565b61030a60045481565b61030a6103ca366004613c87565b5f9081526020819052604090206001015490565b6102e26103ec366004613c87565b610c5e565b61034b6103ff366004613cff565b610ce2565b61034b610412366004613cff565b610d0c565b61034b610d44565b6003546102e29060ff1681565b61034b61043a366004613cad565b610da8565b61030a7f5358bcfd81d1ef3da152b1755e1c3c6739686fa7e83dbcad0071568cc4b73a6381565b61034b610474366004613cff565b610f8e565b6102e2610487366004613b2d565b6110ad565b61030a61049a366004613cff565b611151565b6104b26104ad366004613b2d565b6113e6565b604080516001600160a01b039097168752602087019590955293850192909252606084015263ffffffff90811660808401521660a082015260c0016102ee565b61034b610500366004613d2d565b61144b565b610518610513366004613d63565b611a77565b6040516001600160a01b0390911681526020016102ee565b61030a7fd5b31c46cc75555bed852936261f4e95cbe813f3d32342d2d830a8fb4561ff8e81565b6102e2610565366004613cff565b611a95565b6102e2610578366004613d83565b611abd565b61034b61058b366004613cad565b611b8f565b6102e261059e366004613cad565b611cc1565b61030a5f81565b6105bd6105b8366004613c87565b611cd9565b6040516102ee9190613daf565b61034b6105d8366004613c87565b611cf2565b61034b611f22565b61030a6103e881565b61062e6105fc366004613c87565b60076020525f90815260409020805460018201546002830154600384015460049094015460ff90931693919290919085565b6040805195151586526020860194909452928401919091526060830152608082015260a0016102ee565b61034b610666366004613cad565b611f83565b61030a610679366004613b2d565b612000565b61069161068c366004613c87565b612019565b604080516001600160a01b039d8e1681529c909b1660208d0152998b019890985260608a0196909652608089019490945260a088019290925260c087015260e086015261010085015261012084015263ffffffff90811661014084015216610160820152610180016102ee565b61034b61070c366004613e07565b61209f565b61030a61071f366004613b2d565b612140565b61030a610732366004613c87565b612335565b61030a5f5160206141825f395f51905f5281565b610380610759366004613cad565b61234b565b61051861076c366004613c87565b612431565b61034b61077f366004613cff565b612459565b61034b610792366004613cad565b61247d565b61030a600e5481565b61030a6107ae366004613ebc565b612556565b6105186107c1366004613c87565b600a6020525f90815260409020546001600160a01b031681565b6105187f000000000000000000000000000000000000000000000000000000000000000081565b61030a610810366004613b2d565b612c81565b5f6001600160e01b03198216635a05180f60e01b1480610839575061083982612c8c565b92915050565b600c602052815f5260405f208181548110610858575f80fd5b905f5260205f20015f91509150505481565b60605f8267ffffffffffffffff81111561088657610886613e20565b6040519080825280602002602001820160405280156108bf57816020015b6108ac613a92565b8152602001906001900390816108a45790505b5090505f5b83811015610912576108ed8585838181106108e1576108e1613f4f565b90506020020135610aaf565b8282815181106108ff576108ff613f4f565b60209081029190910101526001016108c4565b509392505050565b5f5160206141825f395f51905f5261093181612cc0565b60035460ff161561095d5760405162461bcd60e51b815260040161095490613f63565b60405180910390fd5b5f828152600a60205260409020546001600160a01b031633146109b25760405162461bcd60e51b815260206004820152600d60248201526c139bdd081e5bdd5c88109bdb99609a1b6044820152606401610954565b42600683815481106109c6576109c6613f4f565b905f5260205f2090600b0201600a015f6101000a81548163ffffffff021916908363ffffffff1602179055505f60068381548110610a0657610a06613f4f565b905f5260205f2090600b02016003015460068481548110610a2957610a29613f4f565b905f5260205f2090600b020160020154610a439190613fa3565b9050610a80338260068681548110610a5d57610a5d613f4f565b5f91825260209091206001600b9092020101546001600160a01b03169190612ccd565b60405183907fc22a1d700260b389bc0ce34ad5cd517ce48733d9f3bf0f188725711b0f53940c905f90a2505050565b610ab7613a92565b5f60068381548110610acb57610acb613f4f565b5f9182526020918290206040805161012081018252600b90930290910180546001600160a01b03908116845260018201541693830193909352919250908101610b1385612d2c565b81526007830154602080830191909152600a80850154600160201b900463ffffffff16604080850191909152600286015460608501525f8881529190925220546001600160a01b0316608082015260a001610b6d85610c5e565b151581526020018260030154815250915050919050565b6001600160a01b0381165f908152600b6020908152604091829020805483518184028101840190945280845260609392830182828015610be157602002820191905f5260205f20905b815481526020019060010190808311610bcd575b50505050509050919050565b5f61083982612d2c565b6001600160a01b0381165f908152600c6020908152604091829020805483518184028101840190945280845260609392830182828015610be157602002820191905f5260205f2090815481526020019060010190808311610bcd5750505050509050919050565b5f60068281548110610c7257610c72613f4f565b5f9182526020909120600a600b90920201015463ffffffff164211801590610839575060068281548110610ca857610ca8613f4f565b905f5260205f2090600b02016006015460068381548110610ccb57610ccb613f4f565b905f5260205f2090600b0201600301541092915050565b5f82815260208190526040902060010154610cfc81612cc0565b610d068383612d36565b50505050565b6001600160a01b0381163314610d355760405163334bd91960e11b815260040160405180910390fd5b610d3f8282612d61565b505050565b7f5358bcfd81d1ef3da152b1755e1c3c6739686fa7e83dbcad0071568cc4b73a63610d6e81612cc0565b6003805460ff1916600117905560405133907f81990fd9a5c552b8e3677917d8a03c07678f0d2cb68f88b634aca2022e9bd19f905f90a250565b7fd5b31c46cc75555bed852936261f4e95cbe813f3d32342d2d830a8fb4561ff8e610dd281612cc0565b6001600160a01b038216610e205760405162461bcd60e51b8152602060048201526015602482015274496e76616c696420746f6b656e206164647265737360581b6044820152606401610954565b6001600160a01b0382165f9081526009602052604090205460ff1615610e885760405162461bcd60e51b815260206004820152601960248201527f546f6b656e20616c72656164792077686974656c6973746564000000000000006044820152606401610954565b816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610ee2575060408051601f3d908101601f19168201909252610edf91810190613fb6565b60015b610f245760405162461bcd60e51b815260206004820152601360248201527224b73b30b634b21022a9219918103a37b5b2b760691b6044820152606401610954565b506001600160a01b0382165f818152600960205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b5050565b5f828152600a60205260409020546001600160a01b03163314610fe65760405162461bcd60e51b815260206004820152601060248201526f2737ba1036b0b935b2ba1037bbb732b960811b6044820152606401610954565b610ffd5f5160206141825f395f51905f5282611a95565b61103a5760405162461bcd60e51b815260206004820152600e60248201526d2737ba1030bab1ba34b7b732b2b960911b6044820152606401610954565b5f828152600a602090815260409182902080546001600160a01b0319166001600160a01b03851690811790915582518581523392810192909252918101919091527f2ce31ebb7c731534ab7267f7655a662e4a2bce5ffbf2c5ac9c197c0f5c554e79906060015b60405180910390a15050565b6001600160a01b0382165f908152600d602052604081208054829190849081106110d9576110d9613f4f565b5f9182526020918290206040805160c081018252600590930290910180546001600160a01b031683526001810154938301939093526002830154908201526003820154606082015260049091015463ffffffff8082166080840152600160201b9091041660a090910181905242101591505092915050565b5f61115a612d8c565b6001600160a01b0382165f908152600d602052604081205490815b80156113d8578061118581613fd6565b6001600160a01b0387165f908152600d60205260408120805492945090925090839081106111b5576111b5613f4f565b905f5260205f2090600502019050868160030154036113d2575f6111d98784612140565b905080156113d05780826001015f8282546111f49190613fa3565b9091555061120490508185613feb565b935061121e878260068b81548110610a5d57610a5d613f4f565b81600101545f036113d0576001600160a01b0387165f908152600d602052604090205461124d90600190613fa3565b831461135e576001600160a01b0387165f908152600d60205260409020805461127890600190613fa3565b8154811061128857611288613f4f565b905f5260205f209060050201600d5f896001600160a01b03166001600160a01b031681526020019081526020015f2084815481106112c8576112c8613f4f565b5f9182526020909120825460059092020180546001600160a01b0319166001600160a01b039092169190911781556001808301549082015560028083015490820155600380830154908201556004918201805492909101805463ffffffff19811663ffffffff94851690811783559254600160201b9081900490941690930267ffffffffffffffff199093169091179190911790555b6001600160a01b0387165f908152600d6020526040902080548061138457611384613ffe565b5f8281526020812060055f199093019283020180546001600160a01b031916815560018101829055600281018290556003810191909155600401805467ffffffffffffffff1916905590555b505b50611175565b509150506108396001600255565b600d602052815f5260405f2081815481106113ff575f80fd5b5f918252602090912060059091020180546001820154600283015460038401546004909401546001600160a01b039093169550909350919063ffffffff80821691600160201b90041686565b611453612d8c565b6001600160a01b0381166114a05760405162461bcd60e51b8152602060048201526014602482015273496e76616c69642075736572206164647265737360601b6044820152606401610954565b60065483106114e55760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081b585c9ad95d081251607a1b6044820152606401610954565b5f600684815481106114f9576114f9613f4f565b5f9182526020909120600b90910201600a81015490915063ffffffff164211156115565760405162461bcd60e51b815260206004820152600e60248201526d109bdb99081a185cc8195b99195960921b6044820152606401610954565b80600601548160030154106115ad5760405162461bcd60e51b815260206004820152601d60248201527f4d6178696d756d20626f6e6420636170616369747920726561636865640000006044820152606401610954565b80546040805163313ce56760e01b815290515f926001600160a01b03169163313ce5679160048083019260209291908290030181865afa1580156115f3573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116179190613fb6565b90505f61162382612de3565b9050808510156116755760405162461bcd60e51b815260206004820152601f60248201527f4465706f7369742062656c6f77206d696e696d756d207468726573686f6c64006044820152606401610954565b82600701548511156116c95760405162461bcd60e51b815260206004820152601f60248201527f4465706f7369742065786365656473206d6178696d756d20616c6c6f776564006044820152606401610954565b6116d286612e0e565b6116db86612f50565b82546040516370a0823160e01b81523060048201526001600160a01b03909116905f9082906370a0823190602401602060405180830381865afa158015611724573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117489190614012565b905061175f6001600160a01b03831633308a612ff2565b6040516370a0823160e01b81523060048201525f906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117a3573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117c79190614012565b9050876117d48383613fa3565b146118215760405162461bcd60e51b815260206004820152601960248201527f496e636f7272656374207472616e7366657220616d6f756e74000000000000006044820152606401610954565b8760068a8154811061183557611835613f4f565b905f5260205f2090600b02016008015f8282546118529190613feb565b909155505f90506118628a61302b565b90505f61186f8a8361328f565b600189015460068a015460038b01549293506001600160a01b0390911691611898908490613feb565b11156118e65760405162461bcd60e51b815260206004820152601960248201527f45786365656473206d6178696d756d20626f6e642064656274000000000000006044820152606401610954565b600d5f8b6001600160a01b03166001600160a01b031681526020019081526020015f206040518060c00160405280836001600160a01b031681526020018481526020018581526020018e81526020014263ffffffff168152602001428c600a0160049054906101000a900463ffffffff1663ffffffff166119679190613feb565b63ffffffff9081169091528254600181810185555f9485526020808620855160059094020180546001600160a01b039094166001600160a01b03199094169390931783558401519082015560408301516002820155606083015160038083019190915560808401516004909201805460a0909501518416600160201b0267ffffffffffffffff1990951692909316919091179290921790558a018054849290611a11908490613feb565b9091555050604080518c8152602081018490529081018490528c906001600160a01b038c16907f105066e10d7040f371761942e4dcb5b97c51daf3acfe0295b7d4c42d32af86f29060600160405180910390a3505050505050505050610d3f6001600255565b5f828152600160205260408120611a8e90836132ad565b9392505050565b5f918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b6001600160a01b0381165f908152600b6020908152604080832080548251818502810185019093528083528493830182828015611b1757602002820191905f5260205f20905b815481526020019060010190808311611b03575b509394505f93505050505b8151811015611b8557846001600160a01b0316600a5f848481518110611b4a57611b4a613f4f565b60209081029190910181015182528101919091526040015f20546001600160a01b031603611b7d57600192505050610839565b600101611b22565b505f949350505050565b5f611b9981612cc0565b6001600160a01b038216611bef5760405162461bcd60e51b815260206004820152601a60248201527f496e76616c69642061756374696f6e65657220616464726573730000000000006044820152606401610954565b611c065f5160206141825f395f51905f5283611a95565b15611c4b5760405162461bcd60e51b815260206004820152601560248201527420b63932b0b23c9030b71030bab1ba34b7b732b2b960591b6044820152606401610954565b611c625f5160206141825f395f51905f5283612d36565b506001600160a01b0382165f81815260086020526040808220805460ff19166001179055513392915f5160206141825f395f51905f52917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b5f6108395f5160206141825f395f51905f5283611a95565b5f818152600160205260409020606090610839906132b8565b5f5160206141825f395f51905f52611d0981612cc0565b60035460ff1615611d2c5760405162461bcd60e51b815260040161095490613f63565b5f828152600a60205260409020546001600160a01b03163314611d915760405162461bcd60e51b815260206004820152601760248201527f4e6f74206d61726b657427732061756374696f6e6565720000000000000000006044820152606401610954565b60068281548110611da457611da4613f4f565b5f9182526020909120600a600b90920201015463ffffffff164211611e045760405162461bcd60e51b8152602060048201526016602482015275109bdb99081b9bdd081e595d0818dbdb98db1d59195960521b6044820152606401610954565b5f60068381548110611e1857611e18613f4f565b5f91825260208220600b9091020154600680546001600160a01b0390921693509085908110611e4957611e49613f4f565b5f918252602082206008600b909202010154600e5490925015611e9057612710600e5483611e779190614029565b611e819190614040565b9050611e8d8183613fa3565b91505b611ea46001600160a01b0384163384612ccd565b8015611ede57611ede6001600160a01b0384167f000000000000000000000000000000000000000000000000000000000000000083612ccd565b6040805183815260208101839052339187917f6cdd4eeaadbfd702bff31856ddd6a8ac93f3e7683aed304c11ac132081146a1f910160405180910390a35050505050565b7f5358bcfd81d1ef3da152b1755e1c3c6739686fa7e83dbcad0071568cc4b73a63611f4c81612cc0565b6003805460ff1916905560405133907f5b65b0c1363b3003db9bcc5e1fd8805a6d6bf5bf6dc9d3431ee4494cd7d11766905f90a250565b5f611f8d81612cc0565b611fa45f5160206141825f395f51905f5283612d61565b506001600160a01b0382165f81815260086020526040808220805460ff19169055513392915f5160206141825f395f51905f52917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b600b602052815f5260405f208181548110610858575f80fd5b60068181548110612028575f80fd5b5f9182526020909120600b9091020180546001820154600283015460038401546004850154600586015460068701546007880154600889015460098a0154600a909a01546001600160a01b03998a169b5097909816989597949693959294919390929063ffffffff80821691600160201b9004168c565b5f6120a981612cc0565b6103e88263ffffffff1611156120f05760405162461bcd60e51b815260206004820152600c60248201526b08ccaca40e8dede40d0d2ced60a31b6044820152606401610954565b600e805463ffffffff84169182905560408051828152602081019390935290917f528d9479e9f9889a87a3c30c7f7ba537e5e59c4c85a37733b16e57c62df61302910160405180910390a1505050565b6001600160a01b0382165f908152600d6020526040812080548291908490811061216c5761216c613f4f565b5f91825260208083206040805160c081018252600590940290910180546001600160a01b0316845260018101549284019290925260028201549083015260038101546060830181905260049091015463ffffffff8082166080850152600160201b9091041660a0830152600680549294509181106121ec576121ec613f4f565b5f9182526020918290206040805161018081018252600b90930290910180546001600160a01b03908116845260018201541693830193909352600283015490820152600382015460608201526004820154608080830191909152600583015460a0830152600683015460c0830152600783015460e083015260088301546101008301526009830154610120830152600a9092015463ffffffff808216610140840152600160201b909104811661016083015291840151909250164210156122b7575f92505050610839565b5f81610160015163ffffffff1690505f8360a0015163ffffffff1642116122f25760808401516122ed9063ffffffff1642613fa3565b6122f4565b815b90505f8285602001516123079190614040565b90505f6123148383614029565b90508560200151811115612329575060208501515b98975050505050505050565b5f818152600160205260408120610839906132c4565b6001600160a01b0381165f908152600d60205260408120546060919067ffffffffffffffff81111561237f5761237f613e20565b6040519080825280602002602001820160405280156123a8578160200160208202803683370190505b5090505f5b6001600160a01b0384165f908152600d602052604090205481101561242a576001600160a01b0384165f908152600d602052604090208054829081106123f5576123f5613f4f565b905f5260205f2090600502016003015482828151811061241757612417613f4f565b60209081029190910101526001016123ad565b5092915050565b60058181548110612440575f80fd5b5f918252602090912001546001600160a01b0316905081565b5f8281526020819052604090206001015461247381612cc0565b610d068383612d61565b7fd5b31c46cc75555bed852936261f4e95cbe813f3d32342d2d830a8fb4561ff8e6124a781612cc0565b6001600160a01b0382165f9081526009602052604090205460ff166125065760405162461bcd60e51b8152602060048201526015602482015274151bdad95b881b9bdd081dda1a5d195b1a5cdd1959605a1b6044820152606401610954565b6001600160a01b0382165f81815260096020908152604091829020805460ff1916905590519182527f108cc7e243d7eb6c2052789466e0961bb24cd62395e2c99e704001b48107a06191016110a1565b5f5f5160206141825f395f51905f5261256e81612cc0565b60035460ff16156125915760405162461bcd60e51b815260040161095490613f63565b6001600160a01b0386166125de5760405162461bcd60e51b815260206004820152601460248201527324b73b30b634b2103830bcb7baba103a37b5b2b760611b6044820152606401610954565b6001600160a01b03851661262a5760405162461bcd60e51b815260206004820152601360248201527224b73b30b634b21038bab7ba32903a37b5b2b760691b6044820152606401610954565b856001600160a01b0316856001600160a01b03160361268b5760405162461bcd60e51b815260206004820152601860248201527f546f6b656e73206d75737420626520646966666572656e7400000000000000006044820152606401610954565b6001600160a01b0386165f9081526009602052604090205460ff166126ea5760405162461bcd60e51b8152602060048201526015602482015274151bdad95b881b9bdd081dda1a5d195b1a5cdd1959605a1b6044820152606401610954565b6126f43386611abd565b1561274c5760405162461bcd60e51b815260206004820152602260248201527f416c726561647920686173206d61726b657420666f722071756f746520746f6b60448201526132b760f11b6064820152608401610954565b82514263ffffffff909116116127995760405162461bcd60e51b8152602060048201526012602482015271426f6e6420656e6420746f6f206561726c7960701b6044820152606401610954565b83516127dc5760405162461bcd60e51b81526020600482015260126024820152710416d6f756e74206d757374206265203e20360741b6044820152606401610954565b602084015161282d5760405162461bcd60e51b815260206004820152601c60248201527f436f6e74726f6c207661726961626c65206d757374206265203e2030000000006044820152606401610954565b604084015161287e5760405162461bcd60e51b815260206004820152601960248201527f4d696e696d756d207072696365206d757374206265203e2030000000000000006044820152606401610954565b60608401516128c65760405162461bcd60e51b815260206004820152601460248201527304d61782064656274206d757374206265203e20360641b6044820152606401610954565b82515f906128db90429063ffffffff16613fa3565b90505f81116129255760405162461bcd60e51b8152602060048201526016602482015275125b9d985b1a59081d995cdd1a5b99c81c195c9a5bd960521b6044820152606401610954565b5f612710866003602002015161293d90610708614029565b6129479190614040565b90508161295c82670de0b6b3a7640000614029565b6129669190614040565b8651909150612983906001600160a01b038a169033903090612ff2565b60408051610180810182526001600160a01b0389811682528a166020808301919091528851828401525f606083015288015160808201529087015160a082015260069060c08101886003602002015181526020018381526020015f8152602001428152602001875f600281106129fb576129fb613f4f565b602002015163ffffffff16815260200187600160028110612a1e57612a1e613f4f565b602002015163ffffffff16815250908060018154018082558091505060019003905f5260205f2090600b02015f909190919091505f820151815f015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055506020820151816001015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160020155606082015181600301556080820151816004015560a0820151816005015560c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015f6101000a81548163ffffffff021916908363ffffffff16021790555061016082015181600a0160046101000a81548163ffffffff021916908363ffffffff16021790555050505f6004549050600c5f8a6001600160a01b03166001600160a01b031681526020019081526020015f2081908060018154018082558091505060019003905f5260205f20015f9091909190915055600b5f896001600160a01b03166001600160a01b031681526020019081526020015f2081908060018154018082558091505060019003905f5260205f20015f909190919091505533600a5f8381526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060045f8154612c229061405f565b909155506001600160a01b03808916908a16827fe2cf7d92fe44fee405e71ceedac936dbc3b0d18e7d9582e31f2f2a2a3db75c978a60016020020151604051612c6d91815260200190565b60405180910390a498975050505050505050565b5f611a8e8383612140565b5f6001600160e01b03198216637965db0b60e01b148061083957506301ffc9a760e01b6001600160e01b0319831614610839565b612cca81336132cd565b50565b6040516001600160a01b03838116602483015260448201839052610d3f91859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050613306565b5f6108398261302b565b5f5f612d428484613372565b90508015611a8e575f8481526001602052604090206109129084613401565b5f5f612d6d8484613415565b90508015611a8e575f848152600160205260409020610912908461347e565b6002805403612ddd5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610954565b60028055565b5f60028260ff161115612e0657612dfb600283614077565b61083990600a614173565b506001919050565b5f8181526007602052604090206003810154600490910154612e309190613feb565b421115612cca575f60068281548110612e4b57612e4b613f4f565b5f91825260208083208584526007909152604090922054600b909102909101915060ff1615612ed6575f8281526007602052604081206001015460048301805491929091612e9a908490613feb565b90915550505f82815260076020526040902060020154600482015410612ed1575f8281526007602052604090206002015460048201555b612f33565b5f8281526007602052604081206001015460048301805491929091612efc908490613fa3565b90915550505f82815260076020526040902060020154600482015411612f33575f8281526007602052604090206002015460048201555b505f9081526007602052604090204263ffffffff16600490910155565b5f60068281548110612f6457612f64613f4f565b905f5260205f2090600b020190505f81600301549050805f03612f8657505050565b5f826009015442612f979190613fa3565b9050805f03612fa65750505050565b600a8301545f90600160201b900463ffffffff16612fc48385614029565b612fce9190614040565b9050612fda8184613fa3565b600385015550505063ffffffff421660099091015550565b6040516001600160a01b038481166024830152838116604483015260648201839052610d069186918216906323b872dd90608401612cfa565b5f5f6006838154811061304057613040613f4f565b5f91825260208083206040805161018081018252600b90940290910180546001600160a01b039081168552600182015416848401819052600282015485840152600382015460608601526004808301546080870152600583015460a0870152600683015460c0870152600783015460e087015260088301546101008701526009830154610120870152600a9092015463ffffffff808216610140880152600160201b90910416610160860152825163313ce56760e01b815292519496509363313ce56793838301939092908290030181865afa158015613122573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906131469190613fb6565b90505f825f01516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015613188573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906131ac9190613fb6565b90505f6131b886613492565b90505f6131c4876136c9565b90505f836131d3866024614077565b6131dd9190614077565b6131e890600a614173565b6131f28385614029565b6131fc9190614029565b9050670de0b6b3a76400006132118183614040565b61321b9190614040565b96508560a00151871015613231578560a0015196505b613244670de0b6b3a76400005f19614040565b8711156132845760405162461bcd60e51b815260206004820152600e60248201526d5072696365206f766572666c6f7760901b6044820152606401610954565b505050505050919050565b5f670de0b6b3a76400006132a38385614029565b611a8e9190614040565b5f611a8e83836138ed565b60605f611a8e83613913565b5f610839825490565b6132d78282611a95565b610f8a5760405163e2517d3f60e01b81526001600160a01b038216600482015260248101839052604401610954565b5f5f60205f8451602086015f885af180613325576040513d5f823e3d81fd5b50505f513d9150811561333c578060011415613349565b6001600160a01b0384163b155b15610d0657604051635274afe760e01b81526001600160a01b0385166004820152602401610954565b5f61337d8383611a95565b6133fa575f838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556133b23390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610839565b505f610839565b5f611a8e836001600160a01b03841661396a565b5f6134208383611a95565b156133fa575f838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610839565b5f611a8e836001600160a01b0384166139af565b5f5f600683815481106134a7576134a7613f4f565b5f91825260208083206040805161018081018252600b90940290910180546001600160a01b03908116855260018083015490911685850152600280830154868501526003808401546060808901919091526004808601546080808b01918252600588015460a0808d0191909152600689015460c08d01526007808a015460e08e015260088a01546101008e015260098a01546101208e0152600a9099015463ffffffff8082166101408f0152600160201b909104166101608d01528f8d52978a52888c2089519889018a52805460ff16151589529687015499880199909952938501549686019690965290830154908401529201549281019290925251919350916135b1866136c9565b90505f84610140015163ffffffff1642116135cc575f6135e2565b6101408501516135e29063ffffffff1642613fa3565b90505f8560c0015183670de0b6b3a76400006135fe9190614029565b6136089190614040565b90505f613616836001613feb565b6136208387614029565b61362a9190614040565b9050856060015186608001516136409190613feb565b421161369c5785511561367757602086015161365c9086613feb565b9450856040015185111561367257856040015194505b61369c565b60208601516136869086613fa3565b9450856040015185101561369c57856040015194505b808511156136bb576136ae8186613fa3565b9998505050505050505050565b505f98975050505050505050565b5f5f600683815481106136de576136de613f4f565b5f91825260208083206040805161018081018252600b90940290910180546001600160a01b039081168552600182015416928401929092526002820154908301526003810154606083015260048101546080830152600581015460a0830152600681015460c0830152600781015460e0830152600881015461010083018190526009820154610120840152600a9091015463ffffffff808216610140850152600160201b90910416610160830152909250900361379d57505f92915050565b5f815f01516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156137dd573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906138019190613fb6565b90505f82602001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015613844573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906138689190613fb6565b90505f613876826012614077565b61388190600a614173565b84606001516138909190614029565b90505f61389e846012614077565b6138a990600a614173565b8561010001516138b99190614029565b9050805f036138cf57505f199695505050505050565b5f816138e384670de0b6b3a7640000614029565b6123299190614040565b5f825f01828154811061390257613902613f4f565b905f5260205f200154905092915050565b6060815f01805480602002602001604051908101604052809291908181526020018280548015610be157602002820191905f5260205f2090815481526020019060010190808311610bcd5750505050509050919050565b5f8181526001830160205260408120546133fa57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610839565b5f8181526001830160205260408120548015613a89575f6139d1600183613fa3565b85549091505f906139e490600190613fa3565b9050808214613a43575f865f018281548110613a0257613a02613f4f565b905f5260205f200154905080875f018481548110613a2257613a22613f4f565b5f918252602080832090910192909255918252600188019052604090208390555b8554869080613a5457613a54613ffe565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610839565b5f915050610839565b6040518061012001604052805f6001600160a01b031681526020015f6001600160a01b031681526020015f81526020015f81526020015f81526020015f81526020015f6001600160a01b031681526020015f151581526020015f81525090565b5f60208284031215613b02575f5ffd5b81356001600160e01b031981168114611a8e575f5ffd5b6001600160a01b0381168114612cca575f5ffd5b5f5f60408385031215613b3e575f5ffd5b8235613b4981613b19565b946020939093013593505050565b5f5f60208385031215613b68575f5ffd5b823567ffffffffffffffff811115613b7e575f5ffd5b8301601f81018513613b8e575f5ffd5b803567ffffffffffffffff811115613ba4575f5ffd5b8560208260051b8401011115613bb8575f5ffd5b6020919091019590945092505050565b80516001600160a01b03908116835260208083015182169084015260408083015190840152606080830151908401526080808301519084015260a0828101519084015260c080830151918216908401525060e0810151613c2c60e084018215159052565b5061010090810151910152565b602080825282518282018190525f918401906040840190835b81811015613c7c57613c65838551613bc8565b602093909301926101209290920191600101613c52565b509095945050505050565b5f60208284031215613c97575f5ffd5b5035919050565b61012081016108398284613bc8565b5f60208284031215613cbd575f5ffd5b8135611a8e81613b19565b602080825282518282018190525f918401906040840190835b81811015613c7c578351835260209384019390920191600101613ce1565b5f5f60408385031215613d10575f5ffd5b823591506020830135613d2281613b19565b809150509250929050565b5f5f5f60608486031215613d3f575f5ffd5b83359250602084013591506040840135613d5881613b19565b809150509250925092565b5f5f60408385031215613d74575f5ffd5b50508035926020909101359150565b5f5f60408385031215613d94575f5ffd5b8235613d9f81613b19565b91506020830135613d2281613b19565b602080825282518282018190525f918401906040840190835b81811015613c7c5783516001600160a01b0316835260209384019390920191600101613dc8565b803563ffffffff81168114613e02575f5ffd5b919050565b5f60208284031215613e17575f5ffd5b611a8e82613def565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613e6957634e487b7160e01b5f52604160045260245ffd5b604052919050565b5f82601f830112613e80575f5ffd5b613e8a6040613e34565b806040840185811115613e9b575f5ffd5b845b81811015613c7c57613eae81613def565b845260209384019301613e9d565b5f5f5f5f6101008587031215613ed0575f5ffd5b8435613edb81613b19565b93506020850135613eeb81613b19565b9250605f85018613613efb575f5ffd5b613f056080613e34565b8060c0870188811115613f16575f5ffd5b604088015b81811015613f33578035845260209384019301613f1b565b50819450613f418982613e71565b935050505092959194509250565b634e487b7160e01b5f52603260045260245ffd5b60208082526012908201527110dbdb9d1c9858dd081a5cc81c185d5cd95960721b604082015260600190565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561083957610839613f8f565b5f60208284031215613fc6575f5ffd5b815160ff81168114611a8e575f5ffd5b5f81613fe457613fe4613f8f565b505f190190565b8082018082111561083957610839613f8f565b634e487b7160e01b5f52603160045260245ffd5b5f60208284031215614022575f5ffd5b5051919050565b808202811582820484141761083957610839613f8f565b5f8261405a57634e487b7160e01b5f52601260045260245ffd5b500490565b5f6001820161407057614070613f8f565b5060010190565b60ff828116828216039081111561083957610839613f8f565b6001815b60018411156140cb578085048111156140af576140af613f8f565b60018416156140bd57908102905b60019390931c928002614094565b935093915050565b5f826140e157506001610839565b816140ed57505f610839565b8160018114614103576002811461410d57614129565b6001915050610839565b60ff84111561411e5761411e613f8f565b50506001821b610839565b5060208310610133831016604e8410600b841016171561414c575081810a610839565b6141585f198484614090565b805f190482111561416b5761416b613f8f565b029392505050565b5f611a8e60ff8416836140d356fec1df76f4e50bdb95676f782d4b88b23904c5346d8bc7c986ae26f7e10e601891a2646970667358221220317cf4230659ddf13bf15cede67a9638365be754e7df668aac5de3f88d27db8764736f6c634300081b00330000000000000000000000005e4d8755c0cbd26e8670b27bc0bd21ef84cd881d

Deployed Bytecode

0x608060405234801561000f575f5ffd5b50600436106102cb575f3560e01c806391de4d071161017b578063c5f0d05c116100e4578063d547741f1161009e578063ddb2924711610079578063ddb29247146107a0578063ea5e0c60146107b3578063ed421a9c146107db578063f9a6466414610802575f5ffd5b8063d547741f14610771578063d627d25e14610784578063d918a16e14610797575f5ffd5b8063c5f0d05c146106fe578063c8558f1b14610711578063ca15c87314610724578063cfe9232b14610737578063d04cffeb1461074b578063d1af1fbc1461075e575f5ffd5b8063b33712c511610135578063b33712c5146105dd578063bc063e1a146105e5578063bc3b2b12146105ee578063be32ee2614610658578063c0680e201461066b578063c0aa0e8a1461067e575f5ffd5b806391de4d071461056a5780639b299d9a1461057d5780639cd85b5b14610590578063a217fddf146105a3578063a3246ad3146105aa578063b2f5de94146105ca575f5ffd5b806336568abe116102375780637b30564e116101f15780638dbdbe6d116101cc5780638dbdbe6d146104f25780639010d07c14610505578063909b2bb81461053057806391d1485414610557575f5ffd5b80637b30564e146104795780637bde82f21461048c5780638ad59c701461049f575f5ffd5b806336568abe14610404578063439766ce146104175780635c975abb1461041f5780636247f6f21461042c5780636e76fc8f1461043f578063725dafe014610466575f5ffd5b8063172c44ec11610288578063172c44ec1461038d5780631b014e85146103a057806324760807146103b3578063248a9ca3146103bc57806327507458146103de5780632f2ff15d146103f1575f5ffd5b806301ffc9a7146102cf57806306b40ea3146102f75780630868335e146103185780630fb81eb4146103385780631227b4021461034d578063154347b51461036d575b5f5ffd5b6102e26102dd366004613af2565b610815565b60405190151581526020015b60405180910390f35b61030a610305366004613b2d565b61083f565b6040519081526020016102ee565b61032b610326366004613b57565b61086a565b6040516102ee9190613c39565b61034b610346366004613c87565b61091a565b005b61036061035b366004613c87565b610aaf565b6040516102ee9190613c9e565b61038061037b366004613cad565b610b84565b6040516102ee9190613cc8565b61030a61039b366004613c87565b610bed565b6103806103ae366004613cad565b610bf7565b61030a60045481565b61030a6103ca366004613c87565b5f9081526020819052604090206001015490565b6102e26103ec366004613c87565b610c5e565b61034b6103ff366004613cff565b610ce2565b61034b610412366004613cff565b610d0c565b61034b610d44565b6003546102e29060ff1681565b61034b61043a366004613cad565b610da8565b61030a7f5358bcfd81d1ef3da152b1755e1c3c6739686fa7e83dbcad0071568cc4b73a6381565b61034b610474366004613cff565b610f8e565b6102e2610487366004613b2d565b6110ad565b61030a61049a366004613cff565b611151565b6104b26104ad366004613b2d565b6113e6565b604080516001600160a01b039097168752602087019590955293850192909252606084015263ffffffff90811660808401521660a082015260c0016102ee565b61034b610500366004613d2d565b61144b565b610518610513366004613d63565b611a77565b6040516001600160a01b0390911681526020016102ee565b61030a7fd5b31c46cc75555bed852936261f4e95cbe813f3d32342d2d830a8fb4561ff8e81565b6102e2610565366004613cff565b611a95565b6102e2610578366004613d83565b611abd565b61034b61058b366004613cad565b611b8f565b6102e261059e366004613cad565b611cc1565b61030a5f81565b6105bd6105b8366004613c87565b611cd9565b6040516102ee9190613daf565b61034b6105d8366004613c87565b611cf2565b61034b611f22565b61030a6103e881565b61062e6105fc366004613c87565b60076020525f90815260409020805460018201546002830154600384015460049094015460ff90931693919290919085565b6040805195151586526020860194909452928401919091526060830152608082015260a0016102ee565b61034b610666366004613cad565b611f83565b61030a610679366004613b2d565b612000565b61069161068c366004613c87565b612019565b604080516001600160a01b039d8e1681529c909b1660208d0152998b019890985260608a0196909652608089019490945260a088019290925260c087015260e086015261010085015261012084015263ffffffff90811661014084015216610160820152610180016102ee565b61034b61070c366004613e07565b61209f565b61030a61071f366004613b2d565b612140565b61030a610732366004613c87565b612335565b61030a5f5160206141825f395f51905f5281565b610380610759366004613cad565b61234b565b61051861076c366004613c87565b612431565b61034b61077f366004613cff565b612459565b61034b610792366004613cad565b61247d565b61030a600e5481565b61030a6107ae366004613ebc565b612556565b6105186107c1366004613c87565b600a6020525f90815260409020546001600160a01b031681565b6105187f0000000000000000000000005e4d8755c0cbd26e8670b27bc0bd21ef84cd881d81565b61030a610810366004613b2d565b612c81565b5f6001600160e01b03198216635a05180f60e01b1480610839575061083982612c8c565b92915050565b600c602052815f5260405f208181548110610858575f80fd5b905f5260205f20015f91509150505481565b60605f8267ffffffffffffffff81111561088657610886613e20565b6040519080825280602002602001820160405280156108bf57816020015b6108ac613a92565b8152602001906001900390816108a45790505b5090505f5b83811015610912576108ed8585838181106108e1576108e1613f4f565b90506020020135610aaf565b8282815181106108ff576108ff613f4f565b60209081029190910101526001016108c4565b509392505050565b5f5160206141825f395f51905f5261093181612cc0565b60035460ff161561095d5760405162461bcd60e51b815260040161095490613f63565b60405180910390fd5b5f828152600a60205260409020546001600160a01b031633146109b25760405162461bcd60e51b815260206004820152600d60248201526c139bdd081e5bdd5c88109bdb99609a1b6044820152606401610954565b42600683815481106109c6576109c6613f4f565b905f5260205f2090600b0201600a015f6101000a81548163ffffffff021916908363ffffffff1602179055505f60068381548110610a0657610a06613f4f565b905f5260205f2090600b02016003015460068481548110610a2957610a29613f4f565b905f5260205f2090600b020160020154610a439190613fa3565b9050610a80338260068681548110610a5d57610a5d613f4f565b5f91825260209091206001600b9092020101546001600160a01b03169190612ccd565b60405183907fc22a1d700260b389bc0ce34ad5cd517ce48733d9f3bf0f188725711b0f53940c905f90a2505050565b610ab7613a92565b5f60068381548110610acb57610acb613f4f565b5f9182526020918290206040805161012081018252600b90930290910180546001600160a01b03908116845260018201541693830193909352919250908101610b1385612d2c565b81526007830154602080830191909152600a80850154600160201b900463ffffffff16604080850191909152600286015460608501525f8881529190925220546001600160a01b0316608082015260a001610b6d85610c5e565b151581526020018260030154815250915050919050565b6001600160a01b0381165f908152600b6020908152604091829020805483518184028101840190945280845260609392830182828015610be157602002820191905f5260205f20905b815481526020019060010190808311610bcd575b50505050509050919050565b5f61083982612d2c565b6001600160a01b0381165f908152600c6020908152604091829020805483518184028101840190945280845260609392830182828015610be157602002820191905f5260205f2090815481526020019060010190808311610bcd5750505050509050919050565b5f60068281548110610c7257610c72613f4f565b5f9182526020909120600a600b90920201015463ffffffff164211801590610839575060068281548110610ca857610ca8613f4f565b905f5260205f2090600b02016006015460068381548110610ccb57610ccb613f4f565b905f5260205f2090600b0201600301541092915050565b5f82815260208190526040902060010154610cfc81612cc0565b610d068383612d36565b50505050565b6001600160a01b0381163314610d355760405163334bd91960e11b815260040160405180910390fd5b610d3f8282612d61565b505050565b7f5358bcfd81d1ef3da152b1755e1c3c6739686fa7e83dbcad0071568cc4b73a63610d6e81612cc0565b6003805460ff1916600117905560405133907f81990fd9a5c552b8e3677917d8a03c07678f0d2cb68f88b634aca2022e9bd19f905f90a250565b7fd5b31c46cc75555bed852936261f4e95cbe813f3d32342d2d830a8fb4561ff8e610dd281612cc0565b6001600160a01b038216610e205760405162461bcd60e51b8152602060048201526015602482015274496e76616c696420746f6b656e206164647265737360581b6044820152606401610954565b6001600160a01b0382165f9081526009602052604090205460ff1615610e885760405162461bcd60e51b815260206004820152601960248201527f546f6b656e20616c72656164792077686974656c6973746564000000000000006044820152606401610954565b816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610ee2575060408051601f3d908101601f19168201909252610edf91810190613fb6565b60015b610f245760405162461bcd60e51b815260206004820152601360248201527224b73b30b634b21022a9219918103a37b5b2b760691b6044820152606401610954565b506001600160a01b0382165f818152600960205260408120805460ff191660019081179091556005805491820181559091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00180546001600160a01b03191690911790555b5050565b5f828152600a60205260409020546001600160a01b03163314610fe65760405162461bcd60e51b815260206004820152601060248201526f2737ba1036b0b935b2ba1037bbb732b960811b6044820152606401610954565b610ffd5f5160206141825f395f51905f5282611a95565b61103a5760405162461bcd60e51b815260206004820152600e60248201526d2737ba1030bab1ba34b7b732b2b960911b6044820152606401610954565b5f828152600a602090815260409182902080546001600160a01b0319166001600160a01b03851690811790915582518581523392810192909252918101919091527f2ce31ebb7c731534ab7267f7655a662e4a2bce5ffbf2c5ac9c197c0f5c554e79906060015b60405180910390a15050565b6001600160a01b0382165f908152600d602052604081208054829190849081106110d9576110d9613f4f565b5f9182526020918290206040805160c081018252600590930290910180546001600160a01b031683526001810154938301939093526002830154908201526003820154606082015260049091015463ffffffff8082166080840152600160201b9091041660a090910181905242101591505092915050565b5f61115a612d8c565b6001600160a01b0382165f908152600d602052604081205490815b80156113d8578061118581613fd6565b6001600160a01b0387165f908152600d60205260408120805492945090925090839081106111b5576111b5613f4f565b905f5260205f2090600502019050868160030154036113d2575f6111d98784612140565b905080156113d05780826001015f8282546111f49190613fa3565b9091555061120490508185613feb565b935061121e878260068b81548110610a5d57610a5d613f4f565b81600101545f036113d0576001600160a01b0387165f908152600d602052604090205461124d90600190613fa3565b831461135e576001600160a01b0387165f908152600d60205260409020805461127890600190613fa3565b8154811061128857611288613f4f565b905f5260205f209060050201600d5f896001600160a01b03166001600160a01b031681526020019081526020015f2084815481106112c8576112c8613f4f565b5f9182526020909120825460059092020180546001600160a01b0319166001600160a01b039092169190911781556001808301549082015560028083015490820155600380830154908201556004918201805492909101805463ffffffff19811663ffffffff94851690811783559254600160201b9081900490941690930267ffffffffffffffff199093169091179190911790555b6001600160a01b0387165f908152600d6020526040902080548061138457611384613ffe565b5f8281526020812060055f199093019283020180546001600160a01b031916815560018101829055600281018290556003810191909155600401805467ffffffffffffffff1916905590555b505b50611175565b509150506108396001600255565b600d602052815f5260405f2081815481106113ff575f80fd5b5f918252602090912060059091020180546001820154600283015460038401546004909401546001600160a01b039093169550909350919063ffffffff80821691600160201b90041686565b611453612d8c565b6001600160a01b0381166114a05760405162461bcd60e51b8152602060048201526014602482015273496e76616c69642075736572206164647265737360601b6044820152606401610954565b60065483106114e55760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081b585c9ad95d081251607a1b6044820152606401610954565b5f600684815481106114f9576114f9613f4f565b5f9182526020909120600b90910201600a81015490915063ffffffff164211156115565760405162461bcd60e51b815260206004820152600e60248201526d109bdb99081a185cc8195b99195960921b6044820152606401610954565b80600601548160030154106115ad5760405162461bcd60e51b815260206004820152601d60248201527f4d6178696d756d20626f6e6420636170616369747920726561636865640000006044820152606401610954565b80546040805163313ce56760e01b815290515f926001600160a01b03169163313ce5679160048083019260209291908290030181865afa1580156115f3573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116179190613fb6565b90505f61162382612de3565b9050808510156116755760405162461bcd60e51b815260206004820152601f60248201527f4465706f7369742062656c6f77206d696e696d756d207468726573686f6c64006044820152606401610954565b82600701548511156116c95760405162461bcd60e51b815260206004820152601f60248201527f4465706f7369742065786365656473206d6178696d756d20616c6c6f776564006044820152606401610954565b6116d286612e0e565b6116db86612f50565b82546040516370a0823160e01b81523060048201526001600160a01b03909116905f9082906370a0823190602401602060405180830381865afa158015611724573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117489190614012565b905061175f6001600160a01b03831633308a612ff2565b6040516370a0823160e01b81523060048201525f906001600160a01b038416906370a0823190602401602060405180830381865afa1580156117a3573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117c79190614012565b9050876117d48383613fa3565b146118215760405162461bcd60e51b815260206004820152601960248201527f496e636f7272656374207472616e7366657220616d6f756e74000000000000006044820152606401610954565b8760068a8154811061183557611835613f4f565b905f5260205f2090600b02016008015f8282546118529190613feb565b909155505f90506118628a61302b565b90505f61186f8a8361328f565b600189015460068a015460038b01549293506001600160a01b0390911691611898908490613feb565b11156118e65760405162461bcd60e51b815260206004820152601960248201527f45786365656473206d6178696d756d20626f6e642064656274000000000000006044820152606401610954565b600d5f8b6001600160a01b03166001600160a01b031681526020019081526020015f206040518060c00160405280836001600160a01b031681526020018481526020018581526020018e81526020014263ffffffff168152602001428c600a0160049054906101000a900463ffffffff1663ffffffff166119679190613feb565b63ffffffff9081169091528254600181810185555f9485526020808620855160059094020180546001600160a01b039094166001600160a01b03199094169390931783558401519082015560408301516002820155606083015160038083019190915560808401516004909201805460a0909501518416600160201b0267ffffffffffffffff1990951692909316919091179290921790558a018054849290611a11908490613feb565b9091555050604080518c8152602081018490529081018490528c906001600160a01b038c16907f105066e10d7040f371761942e4dcb5b97c51daf3acfe0295b7d4c42d32af86f29060600160405180910390a3505050505050505050610d3f6001600255565b5f828152600160205260408120611a8e90836132ad565b9392505050565b5f918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b6001600160a01b0381165f908152600b6020908152604080832080548251818502810185019093528083528493830182828015611b1757602002820191905f5260205f20905b815481526020019060010190808311611b03575b509394505f93505050505b8151811015611b8557846001600160a01b0316600a5f848481518110611b4a57611b4a613f4f565b60209081029190910181015182528101919091526040015f20546001600160a01b031603611b7d57600192505050610839565b600101611b22565b505f949350505050565b5f611b9981612cc0565b6001600160a01b038216611bef5760405162461bcd60e51b815260206004820152601a60248201527f496e76616c69642061756374696f6e65657220616464726573730000000000006044820152606401610954565b611c065f5160206141825f395f51905f5283611a95565b15611c4b5760405162461bcd60e51b815260206004820152601560248201527420b63932b0b23c9030b71030bab1ba34b7b732b2b960591b6044820152606401610954565b611c625f5160206141825f395f51905f5283612d36565b506001600160a01b0382165f81815260086020526040808220805460ff19166001179055513392915f5160206141825f395f51905f52917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b5f6108395f5160206141825f395f51905f5283611a95565b5f818152600160205260409020606090610839906132b8565b5f5160206141825f395f51905f52611d0981612cc0565b60035460ff1615611d2c5760405162461bcd60e51b815260040161095490613f63565b5f828152600a60205260409020546001600160a01b03163314611d915760405162461bcd60e51b815260206004820152601760248201527f4e6f74206d61726b657427732061756374696f6e6565720000000000000000006044820152606401610954565b60068281548110611da457611da4613f4f565b5f9182526020909120600a600b90920201015463ffffffff164211611e045760405162461bcd60e51b8152602060048201526016602482015275109bdb99081b9bdd081e595d0818dbdb98db1d59195960521b6044820152606401610954565b5f60068381548110611e1857611e18613f4f565b5f91825260208220600b9091020154600680546001600160a01b0390921693509085908110611e4957611e49613f4f565b5f918252602082206008600b909202010154600e5490925015611e9057612710600e5483611e779190614029565b611e819190614040565b9050611e8d8183613fa3565b91505b611ea46001600160a01b0384163384612ccd565b8015611ede57611ede6001600160a01b0384167f0000000000000000000000005e4d8755c0cbd26e8670b27bc0bd21ef84cd881d83612ccd565b6040805183815260208101839052339187917f6cdd4eeaadbfd702bff31856ddd6a8ac93f3e7683aed304c11ac132081146a1f910160405180910390a35050505050565b7f5358bcfd81d1ef3da152b1755e1c3c6739686fa7e83dbcad0071568cc4b73a63611f4c81612cc0565b6003805460ff1916905560405133907f5b65b0c1363b3003db9bcc5e1fd8805a6d6bf5bf6dc9d3431ee4494cd7d11766905f90a250565b5f611f8d81612cc0565b611fa45f5160206141825f395f51905f5283612d61565b506001600160a01b0382165f81815260086020526040808220805460ff19169055513392915f5160206141825f395f51905f52917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b600b602052815f5260405f208181548110610858575f80fd5b60068181548110612028575f80fd5b5f9182526020909120600b9091020180546001820154600283015460038401546004850154600586015460068701546007880154600889015460098a0154600a909a01546001600160a01b03998a169b5097909816989597949693959294919390929063ffffffff80821691600160201b9004168c565b5f6120a981612cc0565b6103e88263ffffffff1611156120f05760405162461bcd60e51b815260206004820152600c60248201526b08ccaca40e8dede40d0d2ced60a31b6044820152606401610954565b600e805463ffffffff84169182905560408051828152602081019390935290917f528d9479e9f9889a87a3c30c7f7ba537e5e59c4c85a37733b16e57c62df61302910160405180910390a1505050565b6001600160a01b0382165f908152600d6020526040812080548291908490811061216c5761216c613f4f565b5f91825260208083206040805160c081018252600590940290910180546001600160a01b0316845260018101549284019290925260028201549083015260038101546060830181905260049091015463ffffffff8082166080850152600160201b9091041660a0830152600680549294509181106121ec576121ec613f4f565b5f9182526020918290206040805161018081018252600b90930290910180546001600160a01b03908116845260018201541693830193909352600283015490820152600382015460608201526004820154608080830191909152600583015460a0830152600683015460c0830152600783015460e083015260088301546101008301526009830154610120830152600a9092015463ffffffff808216610140840152600160201b909104811661016083015291840151909250164210156122b7575f92505050610839565b5f81610160015163ffffffff1690505f8360a0015163ffffffff1642116122f25760808401516122ed9063ffffffff1642613fa3565b6122f4565b815b90505f8285602001516123079190614040565b90505f6123148383614029565b90508560200151811115612329575060208501515b98975050505050505050565b5f818152600160205260408120610839906132c4565b6001600160a01b0381165f908152600d60205260408120546060919067ffffffffffffffff81111561237f5761237f613e20565b6040519080825280602002602001820160405280156123a8578160200160208202803683370190505b5090505f5b6001600160a01b0384165f908152600d602052604090205481101561242a576001600160a01b0384165f908152600d602052604090208054829081106123f5576123f5613f4f565b905f5260205f2090600502016003015482828151811061241757612417613f4f565b60209081029190910101526001016123ad565b5092915050565b60058181548110612440575f80fd5b5f918252602090912001546001600160a01b0316905081565b5f8281526020819052604090206001015461247381612cc0565b610d068383612d61565b7fd5b31c46cc75555bed852936261f4e95cbe813f3d32342d2d830a8fb4561ff8e6124a781612cc0565b6001600160a01b0382165f9081526009602052604090205460ff166125065760405162461bcd60e51b8152602060048201526015602482015274151bdad95b881b9bdd081dda1a5d195b1a5cdd1959605a1b6044820152606401610954565b6001600160a01b0382165f81815260096020908152604091829020805460ff1916905590519182527f108cc7e243d7eb6c2052789466e0961bb24cd62395e2c99e704001b48107a06191016110a1565b5f5f5160206141825f395f51905f5261256e81612cc0565b60035460ff16156125915760405162461bcd60e51b815260040161095490613f63565b6001600160a01b0386166125de5760405162461bcd60e51b815260206004820152601460248201527324b73b30b634b2103830bcb7baba103a37b5b2b760611b6044820152606401610954565b6001600160a01b03851661262a5760405162461bcd60e51b815260206004820152601360248201527224b73b30b634b21038bab7ba32903a37b5b2b760691b6044820152606401610954565b856001600160a01b0316856001600160a01b03160361268b5760405162461bcd60e51b815260206004820152601860248201527f546f6b656e73206d75737420626520646966666572656e7400000000000000006044820152606401610954565b6001600160a01b0386165f9081526009602052604090205460ff166126ea5760405162461bcd60e51b8152602060048201526015602482015274151bdad95b881b9bdd081dda1a5d195b1a5cdd1959605a1b6044820152606401610954565b6126f43386611abd565b1561274c5760405162461bcd60e51b815260206004820152602260248201527f416c726561647920686173206d61726b657420666f722071756f746520746f6b60448201526132b760f11b6064820152608401610954565b82514263ffffffff909116116127995760405162461bcd60e51b8152602060048201526012602482015271426f6e6420656e6420746f6f206561726c7960701b6044820152606401610954565b83516127dc5760405162461bcd60e51b81526020600482015260126024820152710416d6f756e74206d757374206265203e20360741b6044820152606401610954565b602084015161282d5760405162461bcd60e51b815260206004820152601c60248201527f436f6e74726f6c207661726961626c65206d757374206265203e2030000000006044820152606401610954565b604084015161287e5760405162461bcd60e51b815260206004820152601960248201527f4d696e696d756d207072696365206d757374206265203e2030000000000000006044820152606401610954565b60608401516128c65760405162461bcd60e51b815260206004820152601460248201527304d61782064656274206d757374206265203e20360641b6044820152606401610954565b82515f906128db90429063ffffffff16613fa3565b90505f81116129255760405162461bcd60e51b8152602060048201526016602482015275125b9d985b1a59081d995cdd1a5b99c81c195c9a5bd960521b6044820152606401610954565b5f612710866003602002015161293d90610708614029565b6129479190614040565b90508161295c82670de0b6b3a7640000614029565b6129669190614040565b8651909150612983906001600160a01b038a169033903090612ff2565b60408051610180810182526001600160a01b0389811682528a166020808301919091528851828401525f606083015288015160808201529087015160a082015260069060c08101886003602002015181526020018381526020015f8152602001428152602001875f600281106129fb576129fb613f4f565b602002015163ffffffff16815260200187600160028110612a1e57612a1e613f4f565b602002015163ffffffff16815250908060018154018082558091505060019003905f5260205f2090600b02015f909190919091505f820151815f015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055506020820151816001015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160020155606082015181600301556080820151816004015560a0820151816005015560c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015f6101000a81548163ffffffff021916908363ffffffff16021790555061016082015181600a0160046101000a81548163ffffffff021916908363ffffffff16021790555050505f6004549050600c5f8a6001600160a01b03166001600160a01b031681526020019081526020015f2081908060018154018082558091505060019003905f5260205f20015f9091909190915055600b5f896001600160a01b03166001600160a01b031681526020019081526020015f2081908060018154018082558091505060019003905f5260205f20015f909190919091505533600a5f8381526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060045f8154612c229061405f565b909155506001600160a01b03808916908a16827fe2cf7d92fe44fee405e71ceedac936dbc3b0d18e7d9582e31f2f2a2a3db75c978a60016020020151604051612c6d91815260200190565b60405180910390a498975050505050505050565b5f611a8e8383612140565b5f6001600160e01b03198216637965db0b60e01b148061083957506301ffc9a760e01b6001600160e01b0319831614610839565b612cca81336132cd565b50565b6040516001600160a01b03838116602483015260448201839052610d3f91859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050613306565b5f6108398261302b565b5f5f612d428484613372565b90508015611a8e575f8481526001602052604090206109129084613401565b5f5f612d6d8484613415565b90508015611a8e575f848152600160205260409020610912908461347e565b6002805403612ddd5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610954565b60028055565b5f60028260ff161115612e0657612dfb600283614077565b61083990600a614173565b506001919050565b5f8181526007602052604090206003810154600490910154612e309190613feb565b421115612cca575f60068281548110612e4b57612e4b613f4f565b5f91825260208083208584526007909152604090922054600b909102909101915060ff1615612ed6575f8281526007602052604081206001015460048301805491929091612e9a908490613feb565b90915550505f82815260076020526040902060020154600482015410612ed1575f8281526007602052604090206002015460048201555b612f33565b5f8281526007602052604081206001015460048301805491929091612efc908490613fa3565b90915550505f82815260076020526040902060020154600482015411612f33575f8281526007602052604090206002015460048201555b505f9081526007602052604090204263ffffffff16600490910155565b5f60068281548110612f6457612f64613f4f565b905f5260205f2090600b020190505f81600301549050805f03612f8657505050565b5f826009015442612f979190613fa3565b9050805f03612fa65750505050565b600a8301545f90600160201b900463ffffffff16612fc48385614029565b612fce9190614040565b9050612fda8184613fa3565b600385015550505063ffffffff421660099091015550565b6040516001600160a01b038481166024830152838116604483015260648201839052610d069186918216906323b872dd90608401612cfa565b5f5f6006838154811061304057613040613f4f565b5f91825260208083206040805161018081018252600b90940290910180546001600160a01b039081168552600182015416848401819052600282015485840152600382015460608601526004808301546080870152600583015460a0870152600683015460c0870152600783015460e087015260088301546101008701526009830154610120870152600a9092015463ffffffff808216610140880152600160201b90910416610160860152825163313ce56760e01b815292519496509363313ce56793838301939092908290030181865afa158015613122573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906131469190613fb6565b90505f825f01516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015613188573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906131ac9190613fb6565b90505f6131b886613492565b90505f6131c4876136c9565b90505f836131d3866024614077565b6131dd9190614077565b6131e890600a614173565b6131f28385614029565b6131fc9190614029565b9050670de0b6b3a76400006132118183614040565b61321b9190614040565b96508560a00151871015613231578560a0015196505b613244670de0b6b3a76400005f19614040565b8711156132845760405162461bcd60e51b815260206004820152600e60248201526d5072696365206f766572666c6f7760901b6044820152606401610954565b505050505050919050565b5f670de0b6b3a76400006132a38385614029565b611a8e9190614040565b5f611a8e83836138ed565b60605f611a8e83613913565b5f610839825490565b6132d78282611a95565b610f8a5760405163e2517d3f60e01b81526001600160a01b038216600482015260248101839052604401610954565b5f5f60205f8451602086015f885af180613325576040513d5f823e3d81fd5b50505f513d9150811561333c578060011415613349565b6001600160a01b0384163b155b15610d0657604051635274afe760e01b81526001600160a01b0385166004820152602401610954565b5f61337d8383611a95565b6133fa575f838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556133b23390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610839565b505f610839565b5f611a8e836001600160a01b03841661396a565b5f6134208383611a95565b156133fa575f838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610839565b5f611a8e836001600160a01b0384166139af565b5f5f600683815481106134a7576134a7613f4f565b5f91825260208083206040805161018081018252600b90940290910180546001600160a01b03908116855260018083015490911685850152600280830154868501526003808401546060808901919091526004808601546080808b01918252600588015460a0808d0191909152600689015460c08d01526007808a015460e08e015260088a01546101008e015260098a01546101208e0152600a9099015463ffffffff8082166101408f0152600160201b909104166101608d01528f8d52978a52888c2089519889018a52805460ff16151589529687015499880199909952938501549686019690965290830154908401529201549281019290925251919350916135b1866136c9565b90505f84610140015163ffffffff1642116135cc575f6135e2565b6101408501516135e29063ffffffff1642613fa3565b90505f8560c0015183670de0b6b3a76400006135fe9190614029565b6136089190614040565b90505f613616836001613feb565b6136208387614029565b61362a9190614040565b9050856060015186608001516136409190613feb565b421161369c5785511561367757602086015161365c9086613feb565b9450856040015185111561367257856040015194505b61369c565b60208601516136869086613fa3565b9450856040015185101561369c57856040015194505b808511156136bb576136ae8186613fa3565b9998505050505050505050565b505f98975050505050505050565b5f5f600683815481106136de576136de613f4f565b5f91825260208083206040805161018081018252600b90940290910180546001600160a01b039081168552600182015416928401929092526002820154908301526003810154606083015260048101546080830152600581015460a0830152600681015460c0830152600781015460e0830152600881015461010083018190526009820154610120840152600a9091015463ffffffff808216610140850152600160201b90910416610160830152909250900361379d57505f92915050565b5f815f01516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156137dd573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906138019190613fb6565b90505f82602001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015613844573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906138689190613fb6565b90505f613876826012614077565b61388190600a614173565b84606001516138909190614029565b90505f61389e846012614077565b6138a990600a614173565b8561010001516138b99190614029565b9050805f036138cf57505f199695505050505050565b5f816138e384670de0b6b3a7640000614029565b6123299190614040565b5f825f01828154811061390257613902613f4f565b905f5260205f200154905092915050565b6060815f01805480602002602001604051908101604052809291908181526020018280548015610be157602002820191905f5260205f2090815481526020019060010190808311610bcd5750505050509050919050565b5f8181526001830160205260408120546133fa57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610839565b5f8181526001830160205260408120548015613a89575f6139d1600183613fa3565b85549091505f906139e490600190613fa3565b9050808214613a43575f865f018281548110613a0257613a02613f4f565b905f5260205f200154905080875f018481548110613a2257613a22613f4f565b5f918252602080832090910192909255918252600188019052604090208390555b8554869080613a5457613a54613ffe565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610839565b5f915050610839565b6040518061012001604052805f6001600160a01b031681526020015f6001600160a01b031681526020015f81526020015f81526020015f81526020015f81526020015f6001600160a01b031681526020015f151581526020015f81525090565b5f60208284031215613b02575f5ffd5b81356001600160e01b031981168114611a8e575f5ffd5b6001600160a01b0381168114612cca575f5ffd5b5f5f60408385031215613b3e575f5ffd5b8235613b4981613b19565b946020939093013593505050565b5f5f60208385031215613b68575f5ffd5b823567ffffffffffffffff811115613b7e575f5ffd5b8301601f81018513613b8e575f5ffd5b803567ffffffffffffffff811115613ba4575f5ffd5b8560208260051b8401011115613bb8575f5ffd5b6020919091019590945092505050565b80516001600160a01b03908116835260208083015182169084015260408083015190840152606080830151908401526080808301519084015260a0828101519084015260c080830151918216908401525060e0810151613c2c60e084018215159052565b5061010090810151910152565b602080825282518282018190525f918401906040840190835b81811015613c7c57613c65838551613bc8565b602093909301926101209290920191600101613c52565b509095945050505050565b5f60208284031215613c97575f5ffd5b5035919050565b61012081016108398284613bc8565b5f60208284031215613cbd575f5ffd5b8135611a8e81613b19565b602080825282518282018190525f918401906040840190835b81811015613c7c578351835260209384019390920191600101613ce1565b5f5f60408385031215613d10575f5ffd5b823591506020830135613d2281613b19565b809150509250929050565b5f5f5f60608486031215613d3f575f5ffd5b83359250602084013591506040840135613d5881613b19565b809150509250925092565b5f5f60408385031215613d74575f5ffd5b50508035926020909101359150565b5f5f60408385031215613d94575f5ffd5b8235613d9f81613b19565b91506020830135613d2281613b19565b602080825282518282018190525f918401906040840190835b81811015613c7c5783516001600160a01b0316835260209384019390920191600101613dc8565b803563ffffffff81168114613e02575f5ffd5b919050565b5f60208284031215613e17575f5ffd5b611a8e82613def565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613e6957634e487b7160e01b5f52604160045260245ffd5b604052919050565b5f82601f830112613e80575f5ffd5b613e8a6040613e34565b806040840185811115613e9b575f5ffd5b845b81811015613c7c57613eae81613def565b845260209384019301613e9d565b5f5f5f5f6101008587031215613ed0575f5ffd5b8435613edb81613b19565b93506020850135613eeb81613b19565b9250605f85018613613efb575f5ffd5b613f056080613e34565b8060c0870188811115613f16575f5ffd5b604088015b81811015613f33578035845260209384019301613f1b565b50819450613f418982613e71565b935050505092959194509250565b634e487b7160e01b5f52603260045260245ffd5b60208082526012908201527110dbdb9d1c9858dd081a5cc81c185d5cd95960721b604082015260600190565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561083957610839613f8f565b5f60208284031215613fc6575f5ffd5b815160ff81168114611a8e575f5ffd5b5f81613fe457613fe4613f8f565b505f190190565b8082018082111561083957610839613f8f565b634e487b7160e01b5f52603160045260245ffd5b5f60208284031215614022575f5ffd5b5051919050565b808202811582820484141761083957610839613f8f565b5f8261405a57634e487b7160e01b5f52601260045260245ffd5b500490565b5f6001820161407057614070613f8f565b5060010190565b60ff828116828216039081111561083957610839613f8f565b6001815b60018411156140cb578085048111156140af576140af613f8f565b60018416156140bd57908102905b60019390931c928002614094565b935093915050565b5f826140e157506001610839565b816140ed57505f610839565b8160018114614103576002811461410d57614129565b6001915050610839565b60ff84111561411e5761411e613f8f565b50506001821b610839565b5060208310610133831016604e8410600b841016171561414c575081810a610839565b6141585f198484614090565b805f190482111561416b5761416b613f8f565b029392505050565b5f611a8e60ff8416836140d356fec1df76f4e50bdb95676f782d4b88b23904c5346d8bc7c986ae26f7e10e601891a2646970667358221220317cf4230659ddf13bf15cede67a9638365be754e7df668aac5de3f88d27db8764736f6c634300081b0033

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

0000000000000000000000005e4d8755c0cbd26e8670b27bc0bd21ef84cd881d

-----Decoded View---------------
Arg [0] : _mSig (address): 0x5e4D8755c0cBD26E8670b27Bc0bD21EF84cD881d

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000005e4d8755c0cbd26e8670b27bc0bd21ef84cd881d


Deployed Bytecode Sourcemap

57359:24863:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50895:214;;;;;;:::i;:::-;;:::i;:::-;;;566:14:1;;559:22;541:41;;529:2;514:18;50895:214:0;;;;;;;;59023:53;;;;;;:::i;:::-;;:::i;:::-;;;1247:25:1;;;1235:2;1220:18;59023:53:0;1101:177:1;74731:342:0;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;63919:436::-;;;;;;:::i;:::-;;:::i;:::-;;74125:598;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;72096:142::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;72902:107::-;;;;;;:::i;:::-;;:::i;72246:138::-;;;;;;:::i;:::-;;:::i;58645:28::-;;;;;;33970:122;;;;;;:::i;:::-;34035:7;34062:12;;;;;;;;;;:22;;;;33970:122;72721:162;;;;;;:::i;:::-;;:::i;34402:138::-;;;;;;:::i;:::-;;:::i;35539:251::-;;;;;;:::i;:::-;;:::i;71383:165::-;;;:::i;57724:18::-;;;;;;;;;70603:525;;;;;;:::i;:::-;;:::i;57635:80::-;;57682:33;57635:80;;65411:350;;;;;;:::i;:::-;;:::i;75227:174::-;;;;;;:::i;:::-;;:::i;68351:1308::-;;;;;;:::i;:::-;;:::i;59083:43::-;;;;;;:::i;:::-;;:::i;:::-;;;;-1:-1:-1;;;;;6262:32:1;;;6244:51;;6326:2;6311:18;;6304:34;;;;6354:18;;;6347:34;;;;6412:2;6397:18;;6390:34;6473:10;6461:23;;;6455:3;6440:19;;6433:52;6522:23;6282:3;6501:19;;6494:52;6231:3;6216:19;59083:43:0;5961:591:1;65886:2459:0;;;;;;:::i;:::-;;:::i;51708:144::-;;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;7564:32:1;;;7546:51;;7534:2;7519:18;51708:144:0;7400:203:1;57544:84:0;;57593:35;57544:84;;32986:138;;;;;;:::i;:::-;;:::i;81763:345::-;;;;;;:::i;:::-;;:::i;69799:489::-;;;;;;:::i;:::-;;:::i;73021:127::-;;;;;;:::i;:::-;;:::i;32298:49::-;;32343:4;32298:49;;52712:138;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;64367:1032::-;;;;;;:::i;:::-;;:::i;71556:170::-;;;:::i;59200:38::-;;59234:4;59200:38;;58745:45;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8921:14:1;;8914:22;8896:41;;8968:2;8953:18;;8946:34;;;;8996:18;;;8989:34;;;;9054:2;9039:18;;9032:34;9097:3;9082:19;;9075:35;8883:3;8868:19;58745:45:0;8643:473:1;70296:298:0;;;;;;:::i;:::-;;:::i;58964:52::-;;;;;;:::i;:::-;;:::i;58718:20::-;;;;;;:::i;:::-;;:::i;:::-;;;;-1:-1:-1;;;;;9592:32:1;;;9574:51;;9661:32;;;;9656:2;9641:18;;9634:60;9710:18;;;9703:34;;;;9768:2;9753:18;;9746:34;;;;9811:3;9796:19;;9789:35;;;;9612:3;9840:19;;9833:35;;;;9899:3;9884:19;;9877:35;9943:3;9928:19;;9921:35;9987:3;9972:19;;9965:35;10031:3;10016:19;;10009:35;10094:10;10081:24;;;10075:3;10060:19;;10053:53;10143:24;10137:3;10122:19;;10115:53;9561:3;9546:19;58718:20:0;9121:1053:1;71733:237:0;;;;;;:::i;:::-;;:::i;73156:959::-;;;;;;:::i;:::-;;:::i;52026:133::-;;;;;;:::i;:::-;;:::i;57467:70::-;;-1:-1:-1;;;;;;;;;;;57467:70:0;;72392:316;;;;;;:::i;:::-;;:::i;58680:31::-;;;;;;:::i;:::-;;:::i;34833:140::-;;;;;;:::i;:::-;;:::i;71136:232::-;;;;;;:::i;:::-;;:::i;59170:23::-;;;;;;61447:2462;;;;;;:::i;:::-;;:::i;58902:55::-;;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;58902:55:0;;;59134:29;;;;;75079:141;;;;;;:::i;:::-;;:::i;50895:214::-;50980:4;-1:-1:-1;;;;;;51004:57:0;;-1:-1:-1;;;51004:57:0;;:97;;;51065:36;51089:11;51065:23;:36::i;:::-;50997:104;50895:214;-1:-1:-1;;50895:214:0:o;59023:53::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;74731:342::-;74816:23;74848:31;74903:9;74882:38;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;74848:72:0;-1:-1:-1;74938:9:0;74933:110;74953:20;;;74933:110;;;75004:31;75022:9;;75032:1;75022:12;;;;;;;:::i;:::-;;;;;;;75004:17;:31::i;:::-;74991:7;74999:1;74991:10;;;;;;;;:::i;:::-;;;;;;;;;;:44;74975:3;;74933:110;;;-1:-1:-1;75062:7:0;74731:342;-1:-1:-1;;;74731:342:0:o;63919:436::-;-1:-1:-1;;;;;;;;;;;32582:16:0;32593:4;32582:10;:16::i;:::-;82167:6:::1;::::0;::::1;;82166:7;82158:38;;;;-1:-1:-1::0;;;82158:38:0::1;;;;;;;:::i;:::-;;;;;;;;;64028:25:::2;::::0;;;:20:::2;:25;::::0;;;;;-1:-1:-1;;;;;64028:25:0::2;64057:10;64028:39;64024:69;;64069:24;::::0;-1:-1:-1;;;64069:24:0;;13417:2:1;64069:24:0::2;::::0;::::2;13399:21:1::0;13456:2;13436:18;;;13429:30;-1:-1:-1;;;13475:18:1;;;13468:43;13528:18;;64069:24:0::2;13215:337:1::0;64024:69:0::2;64133:15;64104:5;64110:3;64104:10;;;;;;;;:::i;:::-;;;;;;;;;;;:19;;;:45;;;;;;;;;;;;;;;;;;64162:18;64209:5;64215:3;64209:10;;;;;;;;:::i;:::-;;;;;;;;;;;:20;;;64183:5;64189:3;64183:10;;;;;;;;:::i;:::-;;;;;;;;;;;:23;;;:46;;;;:::i;:::-;64162:67;;64243;64287:10;64299;64250:5;64256:3;64250:10;;;;;;;;:::i;:::-;;::::0;;;::::2;::::0;;;:22:::2;:10;::::0;;::::2;;:22;::::0;-1:-1:-1;;;;;64250:22:0::2;::::0;64243:67;:43:::2;:67::i;:::-;64329:14;::::0;64339:3;;64329:14:::2;::::0;;;::::2;64013:342;63919:436:::0;;:::o;74125:598::-;74191:21;;:::i;:::-;74225:18;74246:5;74252:8;74246:15;;;;;;;;:::i;:::-;;;;;;;;;;74289:426;;;;;;;;74246:15;;;;;;;74331;;-1:-1:-1;;;;;74331:15:0;;;74289:426;;74331:15;74374:16;;;;74289:426;;;;;;;74246:15;;-1:-1:-1;74289:426:0;;;74412:24;74427:8;74412:14;:24::i;:::-;74289:426;;74462:14;;;;74289:426;;;;;;;;74504:16;;;;;-1:-1:-1;;;74504:16:0;;;;74289:426;;;;;;;;74550:17;;;;74289:426;;;;-1:-1:-1;74594:30:0;;;;;;;;;-1:-1:-1;;;;;74594:30:0;74289:426;;;;;;74647:16;74594:30;74647:6;:16::i;:::-;74289:426;;;;;;74689:4;:14;;;74289:426;;;74282:433;;;74125:598;;;:::o;72096:142::-;-1:-1:-1;;;;;72203:27:0;;;;;;:15;:27;;;;;;;;;72196:34;;;;;;;;;;;;;;;;;72166:16;;72196:34;;;72203:27;72196:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;72096:142;;;:::o;72902:107::-;72954:7;72982:19;72997:3;72982:14;:19::i;72246:138::-;-1:-1:-1;;;;;72352:24:0;;;;;;:16;:24;;;;;;;;;72345:31;;;;;;;;;;;;;;;;;72313:16;;72345:31;;;72352:24;72345:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;72246:138;;;:::o;72721:162::-;72771:4;72815:5;72821:3;72815:10;;;;;;;;:::i;:::-;;;;;;;;;:19;:10;;;;;:19;;;;72796:15;:38;;;;:83;;;72861:5;72867:3;72861:10;;;;;;;;:::i;:::-;;;;;;;;;;;:18;;;72838:5;72844:3;72838:10;;;;;;;;:::i;:::-;;;;;;;;;;;:20;;;:41;72789:90;72721:162;-1:-1:-1;;72721:162:0:o;34402:138::-;34035:7;34062:12;;;;;;;;;;:22;;;32582:16;32593:4;32582:10;:16::i;:::-;34507:25:::1;34518:4;34524:7;34507:10;:25::i;:::-;;34402:138:::0;;;:::o;35539:251::-;-1:-1:-1;;;;;35633:34:0;;29295:10;35633:34;35629:104;;35691:30;;-1:-1:-1;;;35691:30:0;;;;;;;;;;;35629:104;35745:37;35757:4;35763:18;35745:11;:37::i;:::-;;35539:251;;:::o;71383:165::-;57682:33;32582:16;32593:4;32582:10;:16::i;:::-;71485:6:::1;:13:::0;;-1:-1:-1;;71485:13:0::1;71494:4;71485:13;::::0;;71514:26:::1;::::0;71529:10:::1;::::0;71514:26:::1;::::0;71485:6:::1;::::0;71514:26:::1;71383:165:::0;:::o;70603:525::-;57593:35;32582:16;32593:4;32582:10;:16::i;:::-;-1:-1:-1;;;;;70730:20:0;::::1;70722:54;;;::::0;-1:-1:-1;;;70722:54:0;;14024:2:1;70722:54:0::1;::::0;::::1;14006:21:1::0;14063:2;14043:18;;;14036:30;-1:-1:-1;;;14082:18:1;;;14075:51;14143:18;;70722:54:0::1;13822:345:1::0;70722:54:0::1;-1:-1:-1::0;;;;;70796:25:0;::::1;;::::0;;;:17:::1;:25;::::0;;;;;::::1;;70795:26;70787:64;;;::::0;-1:-1:-1;;;70787:64:0;;14374:2:1;70787:64:0::1;::::0;::::1;14356:21:1::0;14413:2;14393:18;;;14386:30;14452:27;14432:18;;;14425:55;14497:18;;70787:64:0::1;14172:349:1::0;70787:64:0::1;70923:6;-1:-1:-1::0;;;;;70908:31:0::1;;:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;70908:33:0::1;::::0;;::::1;;::::0;;::::1;-1:-1:-1::0;;70908:33:0::1;::::0;::::1;::::0;;;::::1;::::0;;::::1;::::0;::::1;:::i;:::-;;;70904:217;;71080:29;::::0;-1:-1:-1;;;71080:29:0;;15006:2:1;71080:29:0::1;::::0;::::1;14988:21:1::0;15045:2;15025:18;;;15018:30;-1:-1:-1;;;15064:18:1;;;15057:49;15123:18;;71080:29:0::1;14804:343:1::0;70904:217:0::1;-1:-1:-1::0;;;;;;70973:25:0;::::1;;::::0;;;:17:::1;:25;::::0;;;;:32;;-1:-1:-1;;70973:32:0::1;71001:4;70973:32:::0;;::::1;::::0;;;71020:13:::1;:26:::0;;;;::::1;::::0;;;;;;::::1;::::0;;-1:-1:-1;;;;;;71020:26:0::1;::::0;;::::1;::::0;;70904:217:::1;70603:525:::0;;:::o;65411:350::-;65500:30;;;;:20;:30;;;;;;-1:-1:-1;;;;;65500:30:0;65534:10;65500:44;65492:73;;;;-1:-1:-1;;;65492:73:0;;15354:2:1;65492:73:0;;;15336:21:1;15393:2;15373:18;;;15366:30;-1:-1:-1;;;15412:18:1;;;15405:46;15468:18;;65492:73:0;15152:340:1;65492:73:0;65580:39;-1:-1:-1;;;;;;;;;;;65605:13:0;65580:7;:39::i;:::-;65572:66;;;;-1:-1:-1;;;65572:66:0;;15699:2:1;65572:66:0;;;15681:21:1;15738:2;15718:18;;;15711:30;-1:-1:-1;;;15757:18:1;;;15750:44;15811:18;;65572:66:0;15497:338:1;65572:66:0;65645:30;;;;:20;:30;;;;;;;;;:46;;-1:-1:-1;;;;;;65645:46:0;-1:-1:-1;;;;;65645:46:0;;;;;;;;65703:54;;16042:25:1;;;65731:10:0;16083:18:1;;;16076:60;;;;16152:18;;;16145:60;;;;65703:54:0;;16030:2:1;16015:18;65703:54:0;;;;;;;;65411:350;;:::o;75227:174::-;-1:-1:-1;;;;;75329:14:0;;75297:4;75329:14;;;:8;:14;;;;;:23;;75297:4;;75329:14;75344:7;;75329:23;;;;;;:::i;:::-;;;;;;;;;;75310:42;;;;;;;;75329:23;;;;;;;75310:42;;-1:-1:-1;;;;;75310:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;75310:42:0;;;;;;;;;;;75366:15;:31;;;-1:-1:-1;;75227:174:0;;;;:::o;68351:1308::-;68425:22;55801:21;:19;:21::i;:::-;-1:-1:-1;;;;;68473:14:0;::::1;68456;68473::::0;;;:8:::1;:14;::::0;;;;:21;;;68588:1035:::1;68613:5:::0;;68588:1035:::1;;68632:3:::0;::::1;::::0;::::1;:::i;:::-;-1:-1:-1::0;;;;;68721:14:0;::::1;68694:24;68721:14:::0;;;:8:::1;:14;::::0;;;;:17;;68632:3;;-1:-1:-1;68694:24:0;;-1:-1:-1;68721:14:0;68632:3;;68721:17;::::1;;;;;:::i;:::-;;;;;;;;;;;68694:44;;68777:3;68753:11;:20;;;:27:::0;68749:867:::1;;68797:14;68814:30;68836:4;68842:1;68814:21;:30::i;:::-;68797:47:::0;-1:-1:-1;68877:10:0;;68873:732:::1;;68983:6;68957:11;:22;;;:32;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;69008:23:0::1;::::0;-1:-1:-1;69025:6:0;69008:23;::::1;:::i;:::-;;;69105:57;69149:4;69155:6;69112:5;69118:3;69112:10;;;;;;;;:::i;69105:57::-;69254:11;:22;;;69280:1;69254:27:::0;69250:340:::1;;-1:-1:-1::0;;;;;69389:14:0;::::1;;::::0;;;:8:::1;:14;::::0;;;;:21;:25:::1;::::0;69413:1:::1;::::0;69389:25:::1;:::i;:::-;69384:1;:30;69380:148;;-1:-1:-1::0;;;;;69463:14:0;::::1;;::::0;;;:8:::1;:14;::::0;;;;69478:21;;:25:::1;::::0;69502:1:::1;::::0;69478:25:::1;:::i;:::-;69463:41;;;;;;;;:::i;:::-;;;;;;;;;;;69443:8;:14;69452:4;-1:-1:-1::0;;;;;69443:14:0::1;-1:-1:-1::0;;;;;69443:14:0::1;;;;;;;;;;;;69458:1;69443:17;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;:61;;:17:::1;::::0;;::::1;;:61:::0;;-1:-1:-1;;;;;;69443:61:0::1;-1:-1:-1::0;;;;;69443:61:0;;::::1;::::0;;;::::1;::::0;;;;;::::1;::::0;;;::::1;::::0;::::1;::::0;;::::1;::::0;;;::::1;::::0;::::1;::::0;;::::1;::::0;;;::::1;::::0;::::1;::::0;;::::1;::::0;;;;;::::1;::::0;;-1:-1:-1;;69443:61:0;::::1;;::::0;;::::1;::::0;;::::1;::::0;;;;-1:-1:-1;;;69443:61:0;;;::::1;::::0;;::::1;::::0;;::::1;-1:-1:-1::0;;69443:61:0;;;;;;;;;::::1;::::0;;69380:148:::1;-1:-1:-1::0;;;;;69550:14:0;::::1;;::::0;;;:8:::1;:14;::::0;;;;:20;;;::::1;;;;:::i;:::-;;::::0;;;::::1;::::0;;::::1;-1:-1:-1::0;;69550:20:0;;;;;::::1;;::::0;;-1:-1:-1;;;;;;69550:20:0::1;::::0;;::::1;::::0;::::1;::::0;;;::::1;::::0;::::1;::::0;;;::::1;::::0;::::1;::::0;;;;::::1;;::::0;;-1:-1:-1;;69550:20:0;;;;;69250:340:::1;68782:834;68749:867;68621:1002;68588:1035;;;-1:-1:-1::0;69642:13:0;-1:-1:-1;;55845:20:0;55239:1;56365:7;:22;56182:213;59083:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;59083:43:0;;;;-1:-1:-1;59083:43:0;;-1:-1:-1;59083:43:0;;;;;;;-1:-1:-1;;;59083:43:0;;;;:::o;65886:2459::-;55801:21;:19;:21::i;:::-;-1:-1:-1;;;;;66021:18:0;::::1;66013:51;;;::::0;-1:-1:-1;;;66013:51:0;;16821:2:1;66013:51:0::1;::::0;::::1;16803:21:1::0;16860:2;16840:18;;;16833:30;-1:-1:-1;;;16879:18:1;;;16872:50;16939:18;;66013:51:0::1;16619:344:1::0;66013:51:0::1;66089:5;:12:::0;66083:18;::::1;66075:48;;;::::0;-1:-1:-1;;;66075:48:0;;17170:2:1;66075:48:0::1;::::0;::::1;17152:21:1::0;17209:2;17189:18;;;17182:30;-1:-1:-1;;;17228:18:1;;;17221:47;17285:18;;66075:48:0::1;16968:341:1::0;66075:48:0::1;66185:18;66206:5;66212:3;66206:10;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;::::1;::::0;;::::1;;66307:13;::::0;::::1;::::0;66206:10;;-1:-1:-1;66307:13:0::1;;66288:15;:32;;66280:59;;;::::0;-1:-1:-1;;;66280:59:0;;17516:2:1;66280:59:0::1;::::0;::::1;17498:21:1::0;17555:2;17535:18;;;17528:30;-1:-1:-1;;;17574:18:1;;;17567:44;17628:18;;66280:59:0::1;17314:338:1::0;66280:59:0::1;66375:4;:12;;;66358:4;:14;;;:29;66350:71;;;::::0;-1:-1:-1;;;66350:71:0;;17859:2:1;66350:71:0::1;::::0;::::1;17841:21:1::0;17898:2;17878:18;;;17871:30;17937:31;17917:18;;;17910:59;17986:18;;66350:71:0::1;17657:353:1::0;66350:71:0::1;66533:15:::0;;66510:51:::1;::::0;;-1:-1:-1;;;66510:51:0;;;;66488:19:::1;::::0;-1:-1:-1;;;;;66533:15:0::1;::::0;66510:49:::1;::::0;:51:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;66533:15;66510:51:::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;66488:73;;66572:22;66597:38;66621:13;66597:23;:38::i;:::-;66572:63;;66705:14;66695:6;:24;;66687:68;;;::::0;-1:-1:-1;;;66687:68:0;;18217:2:1;66687:68:0::1;::::0;::::1;18199:21:1::0;18256:2;18236:18;;;18229:30;18295:33;18275:18;;;18268:61;18346:18;;66687:68:0::1;18015:355:1::0;66687:68:0::1;66784:4;:14;;;66774:6;:24;;66766:68;;;::::0;-1:-1:-1;;;66766:68:0;;18577:2:1;66766:68:0::1;::::0;::::1;18559:21:1::0;18616:2;18596:18;;;18589:30;18655:33;18635:18;;;18628:61;18706:18;;66766:68:0::1;18375:355:1::0;66766:68:0::1;66937:10;66943:3;66937:5;:10::i;:::-;66958:15;66969:3;66958:10;:15::i;:::-;67060::::0;;67111:35:::1;::::0;-1:-1:-1;;;67111:35:0;;67140:4:::1;67111:35;::::0;::::1;7546:51:1::0;-1:-1:-1;;;;;67060:15:0;;::::1;::::0;67033:17:::1;::::0;67060:15;;67111:20:::1;::::0;7519:18:1;;67111:35:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;67087:59:::0;-1:-1:-1;67157:62:0::1;-1:-1:-1::0;;;;;67157:27:0;::::1;67185:10;67205:4;67212:6:::0;67157:27:::1;:62::i;:::-;67254:35;::::0;-1:-1:-1;;;67254:35:0;;67283:4:::1;67254:35;::::0;::::1;7546:51:1::0;67231:20:0::1;::::0;-1:-1:-1;;;;;67254:20:0;::::1;::::0;::::1;::::0;7519:18:1;;67254:35:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;67231:58:::0;-1:-1:-1;67340:6:0;67308:28:::1;67323:13:::0;67231:58;67308:28:::1;:::i;:::-;:38;67300:76;;;::::0;-1:-1:-1;;;67300:76:0;;19126:2:1;67300:76:0::1;::::0;::::1;19108:21:1::0;19165:2;19145:18;;;19138:30;19204:27;19184:18;;;19177:55;19249:18;;67300:76:0::1;18924:349:1::0;67300:76:0::1;67419:6;67387:5;67393:3;67387:10;;;;;;;;:::i;:::-;;;;;;;;;;;:28;;;:38;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;67492:13:0::1;::::0;-1:-1:-1;67508:17:0::1;67521:3:::0;67508:12:::1;:17::i;:::-;67492:33;;67581:17;67601:33;67620:6;67628:5;67601:18;:33::i;:::-;67667:16;::::0;::::1;::::0;67798:12:::1;::::0;::::1;::::0;67768:14:::1;::::0;::::1;::::0;67581:53;;-1:-1:-1;;;;;;67667:16:0;;::::1;::::0;67768:26:::1;::::0;67581:53;;67768:26:::1;:::i;:::-;:42;;67760:80;;;::::0;-1:-1:-1;;;67760:80:0;;19480:2:1;67760:80:0::1;::::0;::::1;19462:21:1::0;19519:2;19499:18;;;19492:30;19558:27;19538:18;;;19531:55;19603:18;;67760:80:0::1;19278:349:1::0;67760:80:0::1;67911:8;:14;67920:4;-1:-1:-1::0;;;;;67911:14:0::1;-1:-1:-1::0;;;;;67911:14:0::1;;;;;;;;;;;;67931:267;;;;;;;;67964:11;-1:-1:-1::0;;;;;67931:267:0::1;;;;;68002:9;67931:267;;;;68038:5;67931:267;;;;68068:3;67931:267;;;;68104:15;67931:267;;;;;;68170:15;68151:4;:16;;;;;;;;;;;;:34;;;;;;:::i;:::-;67931:267;::::0;;::::1;::::0;;;67911:288;;::::1;::::0;;::::1;::::0;;-1:-1:-1;67911:288:0;;;::::1;::::0;;;;;::::1;::::0;;::::1;;::::0;;-1:-1:-1;;;;;67911:288:0;;::::1;-1:-1:-1::0;;;;;;67911:288:0;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;;;;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;;::::1;::::0;;::::1;::::0;;::::1;-1:-1:-1::0;;;67911:288:0::1;-1:-1:-1::0;;67911:288:0;;;;;;::::1;::::0;;;;;;;::::1;::::0;;68242:14;::::1;:27:::0;;68260:9;;-1:-1:-1;68242:27:0::1;::::0;68260:9;;68242:27:::1;:::i;:::-;::::0;;;-1:-1:-1;;68287:50:0::1;::::0;;19834:25:1;;;19890:2;19875:18;;19868:34;;;19918:18;;;19911:34;;;68307:3:0;;-1:-1:-1;;;;;68287:50:0;::::1;::::0;::::1;::::0;19822:2:1;19807:18;68287:50:0::1;;;;;;;65966:2379;;;;;;;;;55845:20:::0;55239:1;56365:7;:22;56182:213;51708:144;51789:7;51816:18;;;:12;:18;;;;;:28;;51838:5;51816:21;:28::i;:::-;51809:35;51708:144;-1:-1:-1;;;51708:144:0:o;32986:138::-;33063:4;33087:12;;;;;;;;;;;-1:-1:-1;;;;;33087:29:0;;;;;;;;;;;;;;;32986:138::o;81763:345::-;-1:-1:-1;;;;;81901:27:0;;81861:4;81901:27;;;:15;:27;;;;;;;;81874:54;;;;;;;;;;;;;;;;;81861:4;;81874:54;;81901:27;81874:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;81874:54:0;;-1:-1:-1;81939:9:0;;-1:-1:-1;;;;81935:151:0;81958:7;:14;81954:1;:18;81935:151;;;82029:10;-1:-1:-1;;;;;81993:46:0;:20;:32;82014:7;82022:1;82014:10;;;;;;;;:::i;:::-;;;;;;;;;;;;81993:32;;;;;;;;;;-1:-1:-1;81993:32:0;;-1:-1:-1;;;;;81993:32:0;:46;81990:89;;82063:4;82056:11;;;;;;81990:89;81974:3;;81935:151;;;-1:-1:-1;82099:5:0;;81763:345;-1:-1:-1;;;;81763:345:0:o;69799:489::-;32343:4;32582:16;32343:4;32582:10;:16::i;:::-;-1:-1:-1;;;;;69966:25:0;::::1;69958:64;;;::::0;-1:-1:-1;;;69958:64:0;;20158:2:1;69958:64:0::1;::::0;::::1;20140:21:1::0;20197:2;20177:18;;;20170:30;20236:28;20216:18;;;20209:56;20282:18;;69958:64:0::1;19956:350:1::0;69958:64:0::1;70042:37;-1:-1:-1::0;;;;;;;;;;;70067:11:0::1;70042:7;:37::i;:::-;70041:38;70033:72;;;::::0;-1:-1:-1;;;70033:72:0;;20513:2:1;70033:72:0::1;::::0;::::1;20495:21:1::0;20552:2;20532:18;;;20525:30;-1:-1:-1;;;20571:18:1;;;20564:51;20632:18;;70033:72:0::1;20311:345:1::0;70033:72:0::1;70118:40;-1:-1:-1::0;;;;;;;;;;;70146:11:0::1;70118:10;:40::i;:::-;-1:-1:-1::0;;;;;;70169:35:0;::::1;;::::0;;;:22:::1;:35;::::0;;;;;:42;;-1:-1:-1;;70169:42:0::1;70207:4;70169:42;::::0;;70227:53;70269:10:::1;::::0;70169:35;-1:-1:-1;;;;;;;;;;;57509:28:0;70227:53:::1;::::0;70169:35;70227:53:::1;69799:489:::0;;:::o;73021:127::-;73083:4;73107:33;-1:-1:-1;;;;;;;;;;;73132:7:0;73107;:33::i;52712:138::-;52815:18;;;;:12;:18;;;;;52779:16;;52815:27;;:25;:27::i;64367:1032::-;-1:-1:-1;;;;;;;;;;;32582:16:0;32593:4;32582:10;:16::i;:::-;82167:6:::1;::::0;::::1;;82166:7;82158:38;;;;-1:-1:-1::0;;;82158:38:0::1;;;;;;;:::i;:::-;64546:25:::2;::::0;;;:20:::2;:25;::::0;;;;;-1:-1:-1;;;;;64546:25:0::2;64575:10;64546:39;64538:75;;;::::0;-1:-1:-1;;;64538:75:0;;20863:2:1;64538:75:0::2;::::0;::::2;20845:21:1::0;20902:2;20882:18;;;20875:30;20941:25;20921:18;;;20914:53;20984:18;;64538:75:0::2;20661:347:1::0;64538:75:0::2;64678:5;64684:3;64678:10;;;;;;;;:::i;:::-;;::::0;;;::::2;::::0;;;:19:::2;:10;::::0;;::::2;;:19;::::0;::::2;;64660:15;:37;64652:72;;;::::0;-1:-1:-1;;;64652:72:0;;21215:2:1;64652:72:0::2;::::0;::::2;21197:21:1::0;21254:2;21234:18;;;21227:30;-1:-1:-1;;;21273:18:1;;;21266:52;21335:18;;64652:72:0::2;21013:346:1::0;64652:72:0::2;64777:18;64798:5;64804:3;64798:10;;;;;;;;:::i;:::-;;::::0;;;::::2;::::0;;::::2;::::0;;::::2;;:21:::0;64844:5:::2;:10:::0;;-1:-1:-1;;;;;64798:21:0;;::::2;::::0;-1:-1:-1;64844:5:0;64850:3;;64844:10;::::2;;;;;:::i;:::-;;::::0;;;::::2;::::0;;:28:::2;:10;::::0;;::::2;;:28;::::0;64950:8:::2;::::0;64844:28;;-1:-1:-1;64950:12:0;64946:142:::2;;65007:5;64995:8;;64985:7;:18;;;;:::i;:::-;64984:28;;;;:::i;:::-;64975:37:::0;-1:-1:-1;65063:17:0::2;64975:37:::0;65063:17;::::2;:::i;:::-;;;64946:142;65144:52;-1:-1:-1::0;;;;;65144:31:0;::::2;65176:10;65188:7:::0;65144:31:::2;:52::i;:::-;65252:10:::0;;65248:80:::2;;65275:45;-1:-1:-1::0;;;;;65275:31:0;::::2;65307:4;65313:6:::0;65275:31:::2;:45::i;:::-;65341:54;::::0;;21933:25:1;;;21989:2;21974:18;;21967:34;;;65367:10:0::2;::::0;65362:3;;65341:54:::2;::::0;21906:18:1;65341:54:0::2;;;;;;;64458:941;;;64367:1032:::0;;:::o;71556:170::-;57682:33;32582:16;32593:4;32582:10;:16::i;:::-;71660:6:::1;:14:::0;;-1:-1:-1;;71660:14:0::1;::::0;;71690:28:::1;::::0;71707:10:::1;::::0;71690:28:::1;::::0;71669:5:::1;::::0;71690:28:::1;71556:170:::0;:::o;70296:298::-;32343:4;32582:16;32343:4;32582:10;:16::i;:::-;70422:41:::1;-1:-1:-1::0;;;;;;;;;;;70451:11:0::1;70422;:41::i;:::-;-1:-1:-1::0;;;;;;70474:35:0;::::1;70512:5;70474:35:::0;;;:22:::1;:35;::::0;;;;;:43;;-1:-1:-1;;70474:43:0::1;::::0;;70533:53;70575:10:::1;::::0;70474:35;-1:-1:-1;;;;;;;;;;;57509:28:0;70533:53:::1;::::0;70512:5;70533:53:::1;70296:298:::0;;:::o;58964:52::-;;;;;;;;;;;;;;;;;;;;58718:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;58718:20:0;;;;-1:-1:-1;58718:20:0;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;58718:20:0;;;;:::o;71733:237::-;32343:4;32582:16;32343:4;32582:10;:16::i;:::-;59234:4:::1;71826:10;:21;;;;71818:46;;;::::0;-1:-1:-1;;;71818:46:0;;22214:2:1;71818:46:0::1;::::0;::::1;22196:21:1::0;22253:2;22233:18;;;22226:30;-1:-1:-1;;;22272:18:1;;;22265:42;22324:18;;71818:46:0::1;22012:336:1::0;71818:46:0::1;71888:8;::::0;;71903:21:::1;::::0;::::1;::::0;;;;71936:30:::1;::::0;;22526:25:1;;;22582:2;22567:18;;22560:51;;;;71888:8:0;;71936:30:::1;::::0;22499:18:1;71936:30:0::1;;;;;;;71811:159;71733:237:::0;;:::o;73156:959::-;-1:-1:-1;;;;;73274:14:0;;73239:7;73274:14;;;:8;:14;;;;;:23;;73239:7;;73274:14;73289:7;;73274:23;;;;;;:::i;:::-;;;;;;;;;73255:42;;;;;;;;73274:23;;;;;;;73255:42;;-1:-1:-1;;;;;73255:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;73255:42:0;;;;;;;;73324:5;:20;;73255:42;;-1:-1:-1;73324:5:0;:20;;;;;;:::i;:::-;;;;;;;;;;73304:40;;;;;;;;73324:20;;;;;;;73304:40;;-1:-1:-1;;;;;73304:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;73304:40:0;;;;;;;;;73407:14;;;;73304:40;;-1:-1:-1;73389:32:0;:15;:32;73385:65;;;73441:1;73434:8;;;;;;73385:65;73499:19;73521:4;:16;;;73499:38;;;;73594:19;73634:4;:12;;;73616:30;;:15;:30;:99;;73701:14;;;;73683:32;;;;:15;:32;:::i;:::-;73616:99;;;73659:11;73616:99;73594:121;;73760:23;73804:11;73786:4;:15;;;:29;;;;:::i;:::-;73760:55;-1:-1:-1;73867:24:0;73894:29;73912:11;73760:55;73894:29;:::i;:::-;73867:56;;74010:4;:15;;;73991:16;:34;73987:93;;;-1:-1:-1;74057:15:0;;;;73987:93;74095:16;73156:959;-1:-1:-1;;;;;;;;73156:959:0:o;52026:133::-;52097:7;52124:18;;;:12;:18;;;;;:27;;:25;:27::i;72392:316::-;-1:-1:-1;;;;;72533:14:0;;72488:28;72533:14;;;:8;:14;;;;;:21;72455:16;;72488:28;72519:36;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;72519:36:0;-1:-1:-1;72488:67:0;-1:-1:-1;72567:9:0;72562:114;-1:-1:-1;;;;;72586:14:0;;;;;;:8;:14;;;;;:21;72582:25;;72562:114;;;-1:-1:-1;;;;;72642:14:0;;;;;;:8;:14;;;;;:17;;72657:1;;72642:17;;;;;;:::i;:::-;;;;;;;;;;;:26;;;72625:11;72637:1;72625:14;;;;;;;;:::i;:::-;;;;;;;;;;:43;72609:3;;72562:114;;;-1:-1:-1;72689:11:0;72392:316;-1:-1:-1;;72392:316:0:o;58680:31::-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;58680:31:0;;-1:-1:-1;58680:31:0;:::o;34833:140::-;34035:7;34062:12;;;;;;;;;;:22;;;32582:16;32593:4;32582:10;:16::i;:::-;34939:26:::1;34951:4;34957:7;34939:11;:26::i;71136:232::-:0;57593:35;32582:16;32593:4;32582:10;:16::i;:::-;-1:-1:-1;;;;;71235:25:0;::::1;;::::0;;;:17:::1;:25;::::0;;;;;::::1;;71227:59;;;::::0;-1:-1:-1;;;71227:59:0;;22824:2:1;71227:59:0::1;::::0;::::1;22806:21:1::0;22863:2;22843:18;;;22836:30;-1:-1:-1;;;22882:18:1;;;22875:51;22943:18;;71227:59:0::1;22622:345:1::0;71227:59:0::1;-1:-1:-1::0;;;;;71293:25:0;::::1;71321:5;71293:25:::0;;;:17:::1;:25;::::0;;;;;;;;:33;;-1:-1:-1;;71293:33:0::1;::::0;;71338:26;;7546:51:1;;;71338:26:0::1;::::0;7519:18:1;71338:26:0::1;7400:203:1::0;61447:2462:0;61736:16;-1:-1:-1;;;;;;;;;;;32582:16:0;32593:4;32582:10;:16::i;:::-;82167:6:::1;::::0;::::1;;82166:7;82158:38;;;;-1:-1:-1::0;;;82158:38:0::1;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;61797:26:0;::::2;61789:59;;;::::0;-1:-1:-1;;;61789:59:0;;23174:2:1;61789:59:0::2;::::0;::::2;23156:21:1::0;23213:2;23193:18;;;23186:30;-1:-1:-1;;;23232:18:1;;;23225:50;23292:18;;61789:59:0::2;22972:344:1::0;61789:59:0::2;-1:-1:-1::0;;;;;61863:34:0;::::2;61855:66;;;::::0;-1:-1:-1;;;61855:66:0;;23523:2:1;61855:66:0::2;::::0;::::2;23505:21:1::0;23562:2;23542:18;;;23535:30;-1:-1:-1;;;23581:18:1;;;23574:49;23640:18;;61855:66:0::2;23321:343:1::0;61855:66:0::2;61960:12;-1:-1:-1::0;;;;;61936:36:0::2;61944:11;-1:-1:-1::0;;;;;61936:36:0::2;::::0;61928:73:::2;;;::::0;-1:-1:-1;;;61928:73:0;;23871:2:1;61928:73:0::2;::::0;::::2;23853:21:1::0;23910:2;23890:18;;;23883:30;23949:26;23929:18;;;23922:54;23993:18;;61928:73:0::2;23669:348:1::0;61928:73:0::2;-1:-1:-1::0;;;;;62016:31:0;::::2;;::::0;;;:17:::2;:31;::::0;;;;;::::2;;62008:65;;;::::0;-1:-1:-1;;;62008:65:0;;22824:2:1;62008:65:0::2;::::0;::::2;22806:21:1::0;22863:2;22843:18;;;22836:30;-1:-1:-1;;;22882:18:1;;;22875:51;22943:18;;62008:65:0::2;22622:345:1::0;62008:65:0::2;62089:61;62117:10;62137:11;62089:27;:61::i;:::-;62088:62;62080:109;;;::::0;-1:-1:-1;;;62080:109:0;;24224:2:1;62080:109:0::2;::::0;::::2;24206:21:1::0;24263:2;24243:18;;;24236:30;24302:34;24282:18;;;24275:62;-1:-1:-1;;;24353:18:1;;;24346:32;24395:19;;62080:109:0::2;24022:398:1::0;62080:109:0::2;62235:16:::0;;62254:15:::2;62235:34;::::0;;::::2;;62227:65;;;::::0;-1:-1:-1;;;62227:65:0;;24627:2:1;62227:65:0::2;::::0;::::2;24609:21:1::0;24666:2;24646:18;;;24639:30;-1:-1:-1;;;24685:18:1;;;24678:48;24743:18;;62227:65:0::2;24425:342:1::0;62227:65:0::2;62343:9:::0;;62335:44:::2;;;::::0;-1:-1:-1;;;62335:44:0;;24974:2:1;62335:44:0::2;::::0;::::2;24956:21:1::0;25013:2;24993:18;;;24986:30;-1:-1:-1;;;25032:18:1;;;25025:48;25090:18;;62335:44:0::2;24772:342:1::0;62335:44:0::2;62394:9;::::0;::::2;::::0;62386:54:::2;;;::::0;-1:-1:-1;;;62386:54:0;;25321:2:1;62386:54:0::2;::::0;::::2;25303:21:1::0;25360:2;25340:18;;;25333:30;25399;25379:18;;;25372:58;25447:18;;62386:54:0::2;25119:352:1::0;62386:54:0::2;62455:9:::0;;::::2;::::0;62447:51:::2;;;::::0;-1:-1:-1;;;62447:51:0;;25678:2:1;62447:51:0::2;::::0;::::2;25660:21:1::0;25717:2;25697:18;;;25690:30;25756:27;25736:18;;;25729:55;25801:18;;62447:51:0::2;25476:349:1::0;62447:51:0::2;62513:9:::0;;::::2;::::0;62505:46:::2;;;::::0;-1:-1:-1;;;62505:46:0;;26032:2:1;62505:46:0::2;::::0;::::2;26014:21:1::0;26071:2;26051:18;;;26044:30;-1:-1:-1;;;26090:18:1;;;26083:50;26150:18;;62505:46:0::2;25830:344:1::0;62505:46:0::2;62594:16:::0;;62564:27:::2;::::0;62594:34:::2;::::0;62613:15:::2;::::0;62594:34:::2;;;:::i;:::-;62564:64;;62665:1;62643:19;:23;62635:58;;;::::0;-1:-1:-1;;;62635:58:0;;26381:2:1;62635:58:0::2;::::0;::::2;26363:21:1::0;26420:2;26400:18;;;26393:30;-1:-1:-1;;;26439:18:1;;;26432:52;26501:18;;62635:58:0::2;26179:346:1::0;62635:58:0::2;62757:18;62799:5;62779:6:::0;62786:1:::2;62779:9;;;::::0;:16:::2;::::0;62791:4:::2;62779:16;:::i;:::-;62778:26;;;;:::i;:::-;62757:47:::0;-1:-1:-1;62866:19:0;62845:17:::2;62757:47:::0;62858:4:::2;62845:17;:::i;:::-;62844:41;;;;:::i;:::-;63052:9:::0;;62831:54;;-1:-1:-1;62987:75:0::2;::::0;-1:-1:-1;;;;;62987:37:0;::::2;::::0;63025:10:::2;::::0;63045:4:::2;::::0;62987:37:::2;:75::i;:::-;63108:427;::::0;;::::2;::::0;::::2;::::0;;-1:-1:-1;;;;;63108:427:0;;::::2;::::0;;;::::2;;::::0;;::::2;::::0;;;;63218:9;;63108:427;;;;-1:-1:-1;63108:427:0;;;;63255:9;::::2;::::0;63108:427;;;;63289:9;;::::2;::::0;63108:427;;;;63097:5:::2;::::0;63108:427;;;63218:9;63325:1:::2;63318:9;;;;63108:427;;;;63349:10;63108:427;;;;63389:1;63108:427;;;;63412:15;63108:427;;;;63448:13;63462:1;63448:16;;;;;;;:::i;:::-;;;;;63108:427;;;;;;63488:13;63502:1;63488:16;;;;;;;:::i;:::-;;;;;63108:427;;;;::::0;63097:439:::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;63097:439:0::2;;;;;-1:-1:-1::0;;;;;63097:439:0::2;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;63097:439:0::2;;;;;-1:-1:-1::0;;;;;63097:439:0::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63573:16;63592:13;;63573:32;;63612:16;:30;63629:12;-1:-1:-1::0;;;;;63612:30:0::2;-1:-1:-1::0;;;;;63612:30:0::2;;;;;;;;;;;;63648:8;63612:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63664:15;:37;63688:11;-1:-1:-1::0;;;;;63664:37:0::2;-1:-1:-1::0;;;;;63664:37:0::2;;;;;;;;;;;;63707:8;63664:52;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63756:10;63723:20;:30;63744:8;63723:30;;;;;;;;;;;;:43;;;;;-1:-1:-1::0;;;;;63723:43:0::2;;;;;-1:-1:-1::0;;;;;63723:43:0::2;;;;;;63781:13;;63779:15;;;;;:::i;:::-;::::0;;;-1:-1:-1;;;;;;63806:71:0;;::::2;::::0;;::::2;63821:8:::0;63806:71:::2;63867:6:::0;63874:1:::2;63867:9;;;;63806:71;;;;1247:25:1::0;;1235:2;1220:18;;1101:177;63806:71:0::2;;;;;;;;63897:8:::0;61447:2462;-1:-1:-1;;;;;;;;61447:2462:0:o;75079:141::-;75150:14;75180:36;75202:4;75208:7;75180:21;:36::i;32690:204::-;32775:4;-1:-1:-1;;;;;;32799:47:0;;-1:-1:-1;;;32799:47:0;;:87;;-1:-1:-1;;;;;;;;;;30267:40:0;;;32850:36;30167:148;33339:105;33406:30;33417:4;29295:10;33406;:30::i;:::-;33339:105;:::o;15846:162::-;15956:43;;-1:-1:-1;;;;;26862:32:1;;;15956:43:0;;;26844:51:1;26911:18;;;26904:34;;;15929:71:0;;15949:5;;15971:14;;;;;26817:18:1;;15956:43:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;15956:43:0;;;;;;;;;;;15929:19;:71::i;78389:139::-;78448:13;78499:17;78512:3;78499:12;:17::i;52957:263::-;53043:4;53060:12;53075:31;53092:4;53098:7;53075:16;:31::i;:::-;53060:46;;53121:7;53117:71;;;53145:18;;;;:12;:18;;;;;:31;;53168:7;53145:22;:31::i;53328:268::-;53415:4;53432:12;53447:32;53465:4;53471:7;53447:17;:32::i;:::-;53432:47;;53494:7;53490:74;;;53518:18;;;;:12;:18;;;;;:34;;53544:7;53518:25;:34::i;55881:293::-;55283:1;56015:7;;:19;56007:63;;;;-1:-1:-1;;;56007:63:0;;27151:2:1;56007:63:0;;;27133:21:1;27190:2;27170:18;;;27163:30;27229:33;27209:18;;;27202:61;27280:18;;56007:63:0;26949:355:1;56007:63:0;55283:1;56148:18;;55881:293::o;81207:340::-;81279:7;81397:1;81386:8;:12;;;81382:96;;;81427:12;81438:1;81427:8;:12;:::i;:::-;81420:20;;:2;:20;:::i;81382:96::-;-1:-1:-1;81495:1:0;;81207:340;-1:-1:-1;81207:340:0:o;76261:783::-;76363:16;;;;:11;:16;;;;;:23;;;;76334:26;;;;;:52;;76363:23;76334:52;:::i;:::-;76316:15;:70;76312:719;;;76399:18;76420:5;76426:3;76420:10;;;;;;;;:::i;:::-;;;;;;;;;76455:16;;;:11;:16;;;;;;;:20;76420:10;;;;;;;;-1:-1:-1;76455:20:0;;76451:500;;;76516:16;;;;:11;:16;;;;;:21;;;76492:20;;;:45;;76516:21;;76492:20;;:45;;76516:21;;76492:45;:::i;:::-;;;;-1:-1:-1;;76594:16:0;;;;:11;:16;;;;;:23;;;76570:20;;;;:47;76566:134;;76661:16;;;;:11;:16;;;;;:23;;;76638:20;;;:46;76566:134;76451:500;;;76756:16;;;;:11;:16;;;;;:21;;;76732:20;;;:45;;76756:21;;76732:20;;:45;;76756:21;;76732:45;:::i;:::-;;;;-1:-1:-1;;76834:16:0;;;;:11;:16;;;;;:23;;;76810:20;;;;:47;76806:134;;76901:16;;;;:11;:16;;;;;:23;;;76878:20;;;:46;76806:134;-1:-1:-1;76971:16:0;;;;:11;:16;;;;;77007:15;76971:52;;:26;;;;:52;76261:783::o;75532:715::-;75581:18;75602:5;75608:3;75602:10;;;;;;;;:::i;:::-;;;;;;;;;;;75581:31;;75667:19;75689:4;:14;;;75667:36;;75714:11;75729:1;75714:16;75710:29;;75732:7;;75532:715;:::o;75710:29::-;75832;75882:4;:14;;;75864:15;:32;;;;:::i;:::-;75832:64;;75949:21;75974:1;75949:26;75945:39;;75977:7;;;75532:715;:::o;75945:39::-;76104:16;;;;76050:13;;-1:-1:-1;;;76104:16:0;;;;76066:35;76080:21;76066:11;:35;:::i;:::-;:54;;;;:::i;:::-;76050:70;-1:-1:-1;76177:19:0;76050:70;76177:11;:19;:::i;:::-;76160:14;;;:36;-1:-1:-1;;;76203:40:0;76227:15;76203:40;:14;;;;:40;-1:-1:-1;75532:715:0:o;16253:190::-;16381:53;;-1:-1:-1;;;;;29117:32:1;;;16381:53:0;;;29099:51:1;29186:32;;;29166:18;;;29159:60;29235:18;;;29228:34;;;16354:81:0;;16374:5;;16396:18;;;;;29072::1;;16381:53:0;28897:371:1;77052:1315:0;77110:13;77132:17;77152:5;77158:3;77152:10;;;;;;;;:::i;:::-;;;;;;;;;77132:30;;;;;;;;77152:10;;;;;;;77132:30;;-1:-1:-1;;;;;77132:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;77132:30:0;;;;;;;;77260:52;;-1:-1:-1;;;77260:52:0;;;;77132:30;;-1:-1:-1;77132:30:0;77260:50;;:52;;;;77152:10;;77260:52;;;;;;77132:30;77260:52;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;77237:75;;77319:19;77364:4;:15;;;-1:-1:-1;;;;;77341:49:0;;:51;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;77319:73;;77457:17;77477:28;77501:3;77477:23;:28::i;:::-;77457:48;;77512:17;77532:15;77543:3;77532:10;:15::i;:::-;77512:35;-1:-1:-1;77708:19:0;77786:13;77764:19;77769:14;77764:2;:19;:::i;:::-;:35;;;;:::i;:::-;77757:43;;:2;:43;:::i;:::-;77731:21;77743:9;77731;:21;:::i;:::-;77730:71;;;;:::i;:::-;77708:93;-1:-1:-1;78001:4:0;77980:18;78001:4;77708:93;77980:18;:::i;:::-;:25;;;;:::i;:::-;77972:33;;78087:4;:17;;;78079:5;:25;78075:75;;;78125:4;:17;;;78117:25;;78075:75;78320:24;78340:4;-1:-1:-1;;78320:24:0;:::i;:::-;78311:5;:33;;78303:60;;;;-1:-1:-1;;;78303:60:0;;29475:2:1;78303:60:0;;;29457:21:1;29514:2;29494:18;;;29487:30;-1:-1:-1;;;29533:18:1;;;29526:44;29587:18;;78303:60:0;29273:338:1;78303:60:0;77125:1242;;;;;;77052:1315;;;:::o;81616:139::-;81698:7;81747:4;81729:14;81738:5;81729:6;:14;:::i;:::-;81728:23;;;;:::i;47028:158::-;47102:7;47153:22;47157:3;47169:5;47153:3;:22::i;47736:282::-;47799:16;47828:22;47853:19;47861:3;47853:7;:19::i;46557:117::-;46620:7;46647:19;46655:3;41885:18;;41802:109;33580:201;33669:22;33677:4;33683:7;33669;:22::i;:::-;33664:110;;33715:47;;-1:-1:-1;;;33715:47:0;;-1:-1:-1;;;;;26862:32:1;;33715:47:0;;;26844:51:1;26911:18;;;26904:34;;;26817:18;;33715:47:0;26670:274:1;22439:738:0;22520:18;22549:19;22689:4;22686:1;22679:4;22673:11;22666:4;22660;22656:15;22653:1;22646:5;22639;22634:60;22748:7;22738:180;;22793:4;22787:11;22839:16;22836:1;22831:3;22816:40;22886:16;22881:3;22874:29;22738:180;-1:-1:-1;;22997:1:0;22991:8;22946:16;;-1:-1:-1;23026:15:0;;:68;;23078:11;23093:1;23078:16;;23026:68;;;-1:-1:-1;;;;;23044:26:0;;;:31;23026:68;23022:148;;;23118:40;;-1:-1:-1;;;23118:40:0;;-1:-1:-1;;;;;7564:32:1;;23118:40:0;;;7546:51:1;7519:18;;23118:40:0;7400:203:1;36416:324:0;36493:4;36515:22;36523:4;36529:7;36515;:22::i;:::-;36510:223;;36554:6;:12;;;;;;;;;;;-1:-1:-1;;;;;36554:29:0;;;;;;;;;:36;;-1:-1:-1;;36554:36:0;36586:4;36554:36;;;36637:12;29295:10;;29215:98;36637:12;-1:-1:-1;;;;;36610:40:0;36628:7;-1:-1:-1;;;;;36610:40:0;36622:4;36610:40;;;;;;;;;;-1:-1:-1;36672:4:0;36665:11;;36510:223;-1:-1:-1;36716:5:0;36709:12;;45732:152;45802:4;45826:50;45831:3;-1:-1:-1;;;;;45851:23:0;;45826:4;:50::i;36984:325::-;37062:4;37083:22;37091:4;37097:7;37083;:22::i;:::-;37079:223;;;37154:5;37122:12;;;;;;;;;;;-1:-1:-1;;;;;37122:29:0;;;;;;;;;;:37;;-1:-1:-1;;37122:37:0;;;37179:40;29295:10;;37122:12;;37179:40;;37154:5;37179:40;-1:-1:-1;37241:4:0;37234:11;;46060:158;46133:4;46157:53;46165:3;-1:-1:-1;;;;;46185:23:0;;46157:7;:53::i;79559:1580::-;79628:7;79644:17;79664:5;79670:3;79664:10;;;;;;;;:::i;:::-;;;;;;;;;79644:30;;;;;;;;79664:10;;;;;;;79644:30;;-1:-1:-1;;;;;79644:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;79644:30:0;;;;;;;;79708:16;;;;;;;;;79681:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;79780:20;79644:30;;-1:-1:-1;79681:43:0;79878:15;79720:3;79878:10;:15::i;:::-;79851:42;;79900:26;79947:4;:13;;;79929:31;;:15;:31;:89;;80017:1;79929:89;;;79991:13;;;;79973:31;;;;:15;:31;:::i;:::-;79900:118;;80123:25;80179:4;:12;;;80152:16;80171:4;80152:23;;;;:::i;:::-;80151:40;;;;:::i;:::-;80123:68;-1:-1:-1;80235:19:0;80289:22;:18;80310:1;80289:22;:::i;:::-;80258:26;80267:17;80258:6;:26;:::i;:::-;80257:55;;;;:::i;:::-;80235:77;;80428:10;:17;;;80405:10;:20;;;:40;;;;:::i;:::-;80386:15;:59;80382:633;;80462:14;;80458:550;;;80547:15;;;;80537:25;;;;:::i;:::-;;;80646:10;:17;;;80637:6;:26;80633:93;;;80693:10;:17;;;80684:26;;80633:93;80458:550;;;80812:15;;;;80802:25;;;;:::i;:::-;;;80917:10;:17;;;80908:6;:26;80904:93;;;80964:10;:17;;;80955:26;;80904:93;81056:11;81047:6;:20;81043:72;;;81087:20;81096:11;81087:6;:20;:::i;:::-;81080:27;79559:1580;-1:-1:-1;;;;;;;;;79559:1580:0:o;81043:72::-;-1:-1:-1;81134:1:0;;79559:1580;-1:-1:-1;;;;;;;;79559:1580:0:o;78537:1009::-;78593:7;78613:17;78633:5;78639:3;78633:10;;;;;;;;:::i;:::-;;;;;;;;;78613:30;;;;;;;;78633:10;;;;;;;78613:30;;-1:-1:-1;;;;;78613:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;78613:30:0;;;;;;;;;;-1:-1:-1;78656:27:0;;78652:61;;-1:-1:-1;78704:1:0;;78537:1009;-1:-1:-1;;78537:1009:0:o;78652:61::-;78770:19;78821:4;:15;;;-1:-1:-1;;;;;78798:49:0;;:51;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;78770:80;;78857:20;78909:4;:16;;;-1:-1:-1;;;;;78886:50:0;;:52;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;78857:82;-1:-1:-1;79021:17:0;79064:19;78857:82;79064:2;:19;:::i;:::-;79059:25;;:2;:25;:::i;:::-;79041:4;:14;;;:44;;;;:::i;:::-;79021:64;-1:-1:-1;79151:20:0;79207:18;79212:13;79207:2;:18;:::i;:::-;79200:26;;:2;:26;:::i;:::-;79174:4;:22;;;:53;;;;:::i;:::-;79151:76;;79277:12;79293:1;79277:17;79273:97;;-1:-1:-1;;;79314:17:0;78537:1009;-1:-1:-1;;;;;;78537:1009:0:o;79273:97::-;79460:17;79501:12;79481:16;:9;79493:4;79481:16;:::i;:::-;79480:33;;;;:::i;42265:120::-;42332:7;42359:3;:11;;42371:5;42359:18;;;;;;;;:::i;:::-;;;;;;;;;42352:25;;42265:120;;;;:::o;42935:111::-;42991:16;43027:3;:11;;43020:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;42935:111;;;:::o;39507:416::-;39570:4;41682:21;;;:14;;;:21;;;;;;39587:329;;-1:-1:-1;39630:23:0;;;;;;;;:11;:23;;;;;;;;;;;;;39815:18;;39791:21;;;:14;;;:21;;;;;;:42;;;;39848:11;;40099:1400;40165:4;40296:21;;;:14;;;:21;;;;;;40334:13;;40330:1162;;40707:18;40728:12;40739:1;40728:8;:12;:::i;:::-;40775:18;;40707:33;;-1:-1:-1;40755:17:0;;40775:22;;40796:1;;40775:22;:::i;:::-;40755:42;;40832:9;40818:10;:23;40814:385;;40862:17;40882:3;:11;;40894:9;40882:22;;;;;;;;:::i;:::-;;;;;;;;;40862:42;;41032:9;41006:3;:11;;41018:10;41006:23;;;;;;;;:::i;:::-;;;;;;;;;;;;:35;;;;41147:25;;;:14;;;:25;;;;;:36;;;40814:385;41280:17;;:3;;:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;41386:3;:14;;:21;41401:5;41386:21;;;;;;;;;;;41379:28;;;41431:4;41424:11;;;;;;;40330:1162;41475:5;41468:12;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:286:1:-;72:6;125:2;113:9;104:7;100:23;96:32;93:52;;;141:1;138;131:12;93:52;167:23;;-1:-1:-1;;;;;;219:32:1;;209:43;;199:71;;266:1;263;256:12;593:131;-1:-1:-1;;;;;668:31:1;;658:42;;648:70;;714:1;711;704:12;729:367;797:6;805;858:2;846:9;837:7;833:23;829:32;826:52;;;874:1;871;864:12;826:52;913:9;900:23;932:31;957:5;932:31;:::i;:::-;982:5;1060:2;1045:18;;;;1032:32;;-1:-1:-1;;;729:367:1:o;1283:610::-;1369:6;1377;1430:2;1418:9;1409:7;1405:23;1401:32;1398:52;;;1446:1;1443;1436:12;1398:52;1486:9;1473:23;1519:18;1511:6;1508:30;1505:50;;;1551:1;1548;1541:12;1505:50;1574:22;;1627:4;1619:13;;1615:27;-1:-1:-1;1605:55:1;;1656:1;1653;1646:12;1605:55;1696:2;1683:16;1722:18;1714:6;1711:30;1708:50;;;1754:1;1751;1744:12;1708:50;1807:7;1802:2;1792:6;1789:1;1785:14;1781:2;1777:23;1773:32;1770:45;1767:65;;;1828:1;1825;1818:12;1767:65;1859:2;1851:11;;;;;1881:6;;-1:-1:-1;1283:610:1;-1:-1:-1;;;1283:610:1:o;2007:710::-;2091:12;;-1:-1:-1;;;;;2087:38:1;;;2075:51;;2179:4;2168:16;;;2162:23;2158:49;;2142:14;;;2135:73;2257:4;2246:16;;;2240:23;2224:14;;;2217:47;2313:4;2302:16;;;2296:23;2280:14;;;2273:47;2369:4;2358:16;;;2352:23;2336:14;;;2329:47;2113:3;2414:16;;;2408:23;2392:14;;;2385:47;2478:4;2467:16;;;2461:23;1964:31;;;2526:14;;;1952:44;2493:48;2589:4;2582:5;2578:16;2572:23;2604:47;2645:4;2640:3;2636:14;2620;375:13;368:21;356:34;;305:91;2604:47;-1:-1:-1;2702:6:1;2691:18;;;2685:25;2667:16;;2660:51;2007:710::o;2722:705::-;2976:2;2988:21;;;3058:13;;2961:18;;;3080:22;;;2928:4;;3159:15;;;3133:2;3118:18;;;2928:4;3202:199;3216:6;3213:1;3210:13;3202:199;;;3265:52;3313:3;3304:6;3298:13;3265:52;:::i;:::-;3388:2;3376:15;;;;;3346:6;3337:16;;;;;3238:1;3231:9;3202:199;;;-1:-1:-1;3418:3:1;;2722:705;-1:-1:-1;;;;;2722:705:1:o;3432:226::-;3491:6;3544:2;3532:9;3523:7;3519:23;3515:32;3512:52;;;3560:1;3557;3550:12;3512:52;-1:-1:-1;3605:23:1;;3432:226;-1:-1:-1;3432:226:1:o;3663:268::-;3861:3;3846:19;;3874:51;3850:9;3907:6;3874:51;:::i;3936:247::-;3995:6;4048:2;4036:9;4027:7;4023:23;4019:32;4016:52;;;4064:1;4061;4054:12;4016:52;4103:9;4090:23;4122:31;4147:5;4122:31;:::i;4188:611::-;4378:2;4390:21;;;4460:13;;4363:18;;;4482:22;;;4330:4;;4561:15;;;4535:2;4520:18;;;4330:4;4604:169;4618:6;4615:1;4612:13;4604:169;;;4679:13;;4667:26;;4722:2;4748:15;;;;4713:12;;;;4640:1;4633:9;4604:169;;5217:367;5285:6;5293;5346:2;5334:9;5325:7;5321:23;5317:32;5314:52;;;5362:1;5359;5352:12;5314:52;5407:23;;;-1:-1:-1;5506:2:1;5491:18;;5478:32;5519:33;5478:32;5519:33;:::i;:::-;5571:7;5561:17;;;5217:367;;;;;:::o;6557:487::-;6634:6;6642;6650;6703:2;6691:9;6682:7;6678:23;6674:32;6671:52;;;6719:1;6716;6709:12;6671:52;6764:23;;;-1:-1:-1;6884:2:1;6869:18;;6856:32;;-1:-1:-1;6966:2:1;6951:18;;6938:32;6979:33;6938:32;6979:33;:::i;:::-;7031:7;7021:17;;;6557:487;;;;;:::o;7049:346::-;7117:6;7125;7178:2;7166:9;7157:7;7153:23;7149:32;7146:52;;;7194:1;7191;7184:12;7146:52;-1:-1:-1;;7239:23:1;;;7359:2;7344:18;;;7331:32;;-1:-1:-1;7049:346:1:o;7608:388::-;7676:6;7684;7737:2;7725:9;7716:7;7712:23;7708:32;7705:52;;;7753:1;7750;7743:12;7705:52;7792:9;7779:23;7811:31;7836:5;7811:31;:::i;:::-;7861:5;-1:-1:-1;7918:2:1;7903:18;;7890:32;7931:33;7890:32;7931:33;:::i;8001:637::-;8191:2;8203:21;;;8273:13;;8176:18;;;8295:22;;;8143:4;;8374:15;;;8348:2;8333:18;;;8143:4;8417:195;8431:6;8428:1;8425:13;8417:195;;;8496:13;;-1:-1:-1;;;;;8492:39:1;8480:52;;8561:2;8587:15;;;;8552:12;;;;8528:1;8446:9;8417:195;;10179:163;10246:20;;10306:10;10295:22;;10285:33;;10275:61;;10332:1;10329;10322:12;10275:61;10179:163;;;:::o;10347:184::-;10405:6;10458:2;10446:9;10437:7;10433:23;10429:32;10426:52;;;10474:1;10471;10464:12;10426:52;10497:28;10515:9;10497:28;:::i;10536:127::-;10597:10;10592:3;10588:20;10585:1;10578:31;10628:4;10625:1;10618:15;10652:4;10649:1;10642:15;10668:372;10739:2;10733:9;10804:2;10785:13;;-1:-1:-1;;10781:27:1;10769:40;;10839:18;10824:34;;10860:22;;;10821:62;10818:185;;;10925:10;10920:3;10916:20;10913:1;10906:31;10960:4;10957:1;10950:15;10988:4;10985:1;10978:15;10818:185;11019:2;11012:22;10668:372;;-1:-1:-1;10668:372:1:o;11045:566::-;11094:5;11147:3;11140:4;11132:6;11128:17;11124:27;11114:55;;11165:1;11162;11155:12;11114:55;11266:19;11244:2;11266:19;:::i;:::-;11309:3;11347:2;11339:6;11335:15;11373:3;11365:6;11362:15;11359:35;;;11390:1;11387;11380:12;11359:35;11414:6;11429:151;11445:6;11440:3;11437:15;11429:151;;;11513:22;11531:3;11513:22;:::i;:::-;11501:35;;11565:4;11556:14;;;;11462;11429:151;;11616:1115;11760:6;11768;11776;11784;11837:3;11825:9;11816:7;11812:23;11808:33;11805:53;;;11854:1;11851;11844:12;11805:53;11893:9;11880:23;11912:31;11937:5;11912:31;:::i;:::-;11962:5;-1:-1:-1;12019:2:1;12004:18;;11991:32;12032:33;11991:32;12032:33;:::i;:::-;12084:7;-1:-1:-1;12129:2:1;12114:18;;12110:32;-1:-1:-1;12100:60:1;;12156:1;12153;12146:12;12100:60;12258:20;12235:3;12258:20;:::i;:::-;12300:3;12341;12330:9;12326:19;12368:7;12360:6;12357:19;12354:39;;;12389:1;12386;12379:12;12354:39;12428:2;12417:9;12413:18;12440:202;12456:6;12451:3;12448:15;12440:202;;;12550:17;;12580:20;;12629:2;12620:12;;;;12473;12440:202;;;12444:3;12661:5;12651:15;;12685:40;12717:7;12709:6;12685:40;:::i;:::-;12675:50;;;;;11616:1115;;;;;;;:::o;12736:127::-;12797:10;12792:3;12788:20;12785:1;12778:31;12828:4;12825:1;12818:15;12852:4;12849:1;12842:15;12868:342;13070:2;13052:21;;;13109:2;13089:18;;;13082:30;-1:-1:-1;;;13143:2:1;13128:18;;13121:48;13201:2;13186:18;;12868:342::o;13557:127::-;13618:10;13613:3;13609:20;13606:1;13599:31;13649:4;13646:1;13639:15;13673:4;13670:1;13663:15;13689:128;13756:9;;;13777:11;;;13774:37;;;13791:18;;:::i;14526:273::-;14594:6;14647:2;14635:9;14626:7;14622:23;14618:32;14615:52;;;14663:1;14660;14653:12;14615:52;14695:9;14689:16;14745:4;14738:5;14734:16;14727:5;14724:27;14714:55;;14765:1;14762;14755:12;16216:136;16255:3;16283:5;16273:39;;16292:18;;:::i;:::-;-1:-1:-1;;;16328:18:1;;16216:136::o;16357:125::-;16422:9;;;16443:10;;;16440:36;;;16456:18;;:::i;16487:127::-;16548:10;16543:3;16539:20;16536:1;16529:31;16579:4;16576:1;16569:15;16603:4;16600:1;16593:15;18735:184;18805:6;18858:2;18846:9;18837:7;18833:23;18829:32;18826:52;;;18874:1;18871;18864:12;18826:52;-1:-1:-1;18897:16:1;;18735:184;-1:-1:-1;18735:184:1:o;21364:168::-;21437:9;;;21468;;21485:15;;;21479:22;;21465:37;21455:71;;21506:18;;:::i;21537:217::-;21577:1;21603;21593:132;;21647:10;21642:3;21638:20;21635:1;21628:31;21682:4;21679:1;21672:15;21710:4;21707:1;21700:15;21593:132;-1:-1:-1;21739:9:1;;21537:217::o;26530:135::-;26569:3;26590:17;;;26587:43;;26610:18;;:::i;:::-;-1:-1:-1;26657:1:1;26646:13;;26530:135::o;27309:151::-;27399:4;27392:12;;;27378;;;27374:31;;27417:14;;27414:40;;;27434:18;;:::i;27465:375::-;27553:1;27571:5;27585:249;27606:1;27596:8;27593:15;27585:249;;;27656:4;27651:3;27647:14;27641:4;27638:24;27635:50;;;27665:18;;:::i;:::-;27715:1;27705:8;27701:16;27698:49;;;27729:16;;;;27698:49;27812:1;27808:16;;;;;27768:15;;27585:249;;;27465:375;;;;;;:::o;27845:902::-;27894:5;27924:8;27914:80;;-1:-1:-1;27965:1:1;27979:5;;27914:80;28013:4;28003:76;;-1:-1:-1;28050:1:1;28064:5;;28003:76;28095:4;28113:1;28108:59;;;;28181:1;28176:174;;;;28088:262;;28108:59;28138:1;28129:10;;28152:5;;;28176:174;28213:3;28203:8;28200:17;28197:43;;;28220:18;;:::i;:::-;-1:-1:-1;;28276:1:1;28262:16;;28335:5;;28088:262;;28434:2;28424:8;28421:16;28415:3;28409:4;28406:13;28402:36;28396:2;28386:8;28383:16;28378:2;28372:4;28369:12;28365:35;28362:77;28359:203;;;-1:-1:-1;28471:19:1;;;28547:5;;28359:203;28594:42;-1:-1:-1;;28619:8:1;28613:4;28594:42;:::i;:::-;28672:6;28668:1;28664:6;28660:19;28651:7;28648:32;28645:58;;;28683:18;;:::i;:::-;28721:20;;27845:902;-1:-1:-1;;;27845:902:1:o;28752:140::-;28810:5;28839:47;28880:4;28870:8;28866:19;28860:4;28839:47;:::i

Swarm Source

ipfs://317cf4230659ddf13bf15cede67a9638365be754e7df668aac5de3f88d27db87

Block Transaction Gas Used Reward
view all blocks produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ 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.