Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00Token Holdings
More Info
Private Name Tags
ContractCreator
Latest 17 from a total of 17 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Take Loan | 19060959 | 236 days ago | IN | 0 ETH | 0.00566475 | ||||
Deposit Token | 19060957 | 236 days ago | IN | 0 ETH | 0.01183759 | ||||
Create Loan Borr... | 19025058 | 241 days ago | IN | 0 ETH | 0.01154459 | ||||
Set Fee Percent | 19025041 | 242 days ago | IN | 0 ETH | 0.0009601 | ||||
Deposit Token | 19018239 | 242 days ago | IN | 0 ETH | 0.00524264 | ||||
Create Loan Lend | 18901195 | 259 days ago | IN | 0 ETH | 0.00458219 | ||||
Take Loan | 18901029 | 259 days ago | IN | 0 ETH | 0.00187593 | ||||
Deposit Token | 18901020 | 259 days ago | IN | 0 ETH | 0.0037164 | ||||
Cancel Loan | 18515239 | 313 days ago | IN | 0 ETH | 0.00294552 | ||||
Create Loan Lend | 18511684 | 313 days ago | IN | 0 ETH | 0.01129764 | ||||
Create Loan Lend | 18511614 | 313 days ago | IN | 0 ETH | 0.01056873 | ||||
Create Loan Lend | 18511592 | 313 days ago | IN | 0 ETH | 0.00772926 | ||||
Deposit Token | 18508723 | 314 days ago | IN | 0 ETH | 0.00424864 | ||||
Add Price Feed | 18508614 | 314 days ago | IN | 0 ETH | 0.00117108 | ||||
Add Price Feed | 18508607 | 314 days ago | IN | 0 ETH | 0.00110875 | ||||
Add Price Feed | 18508603 | 314 days ago | IN | 0 ETH | 0.00102019 | ||||
0x60806040 | 18508432 | 314 days ago | IN | 0 ETH | 0.15297412 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
Coinlend
Compiler Version
v0.8.20+commit.a1b79de6
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2023-11-05 */ // File: @openzeppelin/contracts/interfaces/draft-IERC6093.sol // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol) pragma solidity ^0.8.20; /** * @dev Standard ERC20 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens. */ interface IERC20Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC20InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC20InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. * @param spender Address that may be allowed to operate on tokens without being their owner. * @param allowance Amount of tokens a `spender` is allowed to operate with. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC20InvalidApprover(address approver); /** * @dev Indicates a failure with the `spender` to be approved. Used in approvals. * @param spender Address that may be allowed to operate on tokens without being their owner. */ error ERC20InvalidSpender(address spender); } /** * @dev Standard ERC721 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens. */ interface IERC721Errors { /** * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20. * Used in balance queries. * @param owner Address of the current owner of a token. */ error ERC721InvalidOwner(address owner); /** * @dev Indicates a `tokenId` whose `owner` is the zero address. * @param tokenId Identifier number of a token. */ error ERC721NonexistentToken(uint256 tokenId); /** * @dev Indicates an error related to the ownership over a particular token. Used in transfers. * @param sender Address whose tokens are being transferred. * @param tokenId Identifier number of a token. * @param owner Address of the current owner of a token. */ error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC721InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC721InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param tokenId Identifier number of a token. */ error ERC721InsufficientApproval(address operator, uint256 tokenId); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC721InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC721InvalidOperator(address operator); } /** * @dev Standard ERC1155 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens. */ interface IERC1155Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. * @param tokenId Identifier number of a token. */ error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC1155InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC1155InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param owner Address of the current owner of a token. */ error ERC1155MissingApprovalForAll(address operator, address owner); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC1155InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC1155InvalidOperator(address operator); /** * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. * Used in batch transfers. * @param idsLength Length of the array of token identifiers * @param valuesLength Length of the array of token amounts */ error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); } // File: @openzeppelin/contracts/utils/Address.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @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 AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @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 * {FailedInnerCall} 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 AddressInsufficientBalance(address(this)); } (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 {FailedInnerCall}) 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 {FailedInnerCall} 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 {FailedInnerCall}. */ 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 /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } } // File: @openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); } // File: @openzeppelin/contracts/token/ERC20/IERC20.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ 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); } // File: @openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.20; /** * @dev Interface for the optional metadata functions from the ERC20 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); } // File: @openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev An operation with an ERC20 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. */ 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. */ 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. */ 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 Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data); if (returndata.length != 0 && !abi.decode(returndata, (bool))) { 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 silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0; } } // File: @chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol pragma solidity ^0.8.0; interface AggregatorV3Interface { function decimals() external view returns (uint8); function description() external view returns (string memory); function version() external view returns (uint256); function getRoundData(uint80 _roundId) external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); function latestRoundData() external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); } // File: @openzeppelin/contracts/utils/Context.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/Context.sol) 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; } } // File: @openzeppelin/contracts/token/ERC20/ERC20.sol // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.20; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. */ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors { mapping(address account => uint256) private _balances; mapping(address account => mapping(address spender => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the default value returned by this function, unless * it's overridden. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `value`. */ function transfer(address to, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _transfer(owner, to, value); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, value); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `value`. * - the caller must have allowance for ``from``'s tokens of at least * `value`. */ function transferFrom(address from, address to, uint256 value) public virtual returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, value); _transfer(from, to, value); return true; } /** * @dev Moves a `value` amount of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _transfer(address from, address to, uint256 value) internal { if (from == address(0)) { revert ERC20InvalidSender(address(0)); } if (to == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(from, to, value); } /** * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from` * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding * this function. * * Emits a {Transfer} event. */ function _update(address from, address to, uint256 value) internal virtual { if (from == address(0)) { // Overflow check required: The rest of the code assumes that totalSupply never overflows _totalSupply += value; } else { uint256 fromBalance = _balances[from]; if (fromBalance < value) { revert ERC20InsufficientBalance(from, fromBalance, value); } unchecked { // Overflow not possible: value <= fromBalance <= totalSupply. _balances[from] = fromBalance - value; } } if (to == address(0)) { unchecked { // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply. _totalSupply -= value; } } else { unchecked { // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256. _balances[to] += value; } } emit Transfer(from, to, value); } /** * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0). * Relies on the `_update` mechanism * * Emits a {Transfer} event with `from` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _mint(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(address(0), account, value); } /** * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply. * Relies on the `_update` mechanism. * * Emits a {Transfer} event with `to` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead */ function _burn(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidSender(address(0)); } _update(account, address(0), value); } /** * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. * * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument. */ function _approve(address owner, address spender, uint256 value) internal { _approve(owner, spender, value, true); } /** * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event. * * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any * `Approval` event during `transferFrom` operations. * * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to * true using the following override: * ``` * function _approve(address owner, address spender, uint256 value, bool) internal virtual override { * super._approve(owner, spender, value, true); * } * ``` * * Requirements are the same as {_approve}. */ function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual { if (owner == address(0)) { revert ERC20InvalidApprover(address(0)); } if (spender == address(0)) { revert ERC20InvalidSpender(address(0)); } _allowances[owner][spender] = value; if (emitEvent) { emit Approval(owner, spender, value); } } /** * @dev Updates `owner` s allowance for `spender` based on spent `value`. * * Does not update the allowance value in case of infinite allowance. * Revert if not enough allowance is available. * * Does not emit an {Approval} event. */ function _spendAllowance(address owner, address spender, uint256 value) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { if (currentAllowance < value) { revert ERC20InsufficientAllowance(spender, currentAllowance, value); } unchecked { _approve(owner, spender, currentAllowance - value, false); } } } } // File: @openzeppelin/contracts/access/Ownable.sol // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.19; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } } // File: @openzeppelin/contracts/utils/ReentrancyGuard.sol // OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol) pragma solidity ^0.8.20; /** * @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; /** * @dev Unauthorized reentrant call. */ error ReentrancyGuardReentrantCall(); 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 if (_status == ENTERED) { revert ReentrancyGuardReentrantCall(); } // 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; } } // File: Coinlend.sol pragma solidity 0.8.20; /** * @title The Conlend DeFi contract * @author Jan Pumpe * @notice This contract is used for a decentralized lending platform */ contract Coinlend is ReentrancyGuard, Ownable { struct Loan { // Attributes of an loan uint256 id; // Unique identifier for loan address user; // Creator of loan address lender; // User who is lending address tokenLending; // Address of the token borrower receives uint256 tokenLendingAmount; // Amount to lend address tokenCollateral; // Address of token used as collateral uint256 tokenCollateralAmount; // Amount collateral uint256 interestRate; // Interest rate of the loan in basis points -> 5% = 500 uint256 loanDuration; // The loan duration in days uint256 loanState; // The state of the loan (0 = OPEN, 1 = CANCELED, 2 = ACTIVE, 3 = COMPLETE) address borrower; // User who is borrowing uint256 timestamp; // Time when loan was created or taken } struct Transfer { uint256 id; // Unique identifier for deposit address user; // User who is lending address token; // Address of the token which is transferred uint256 tokenAmount; // Amount transferred uint256 transferType; // 0 -> Deposit, 1 -> Withdraw uint256 timestamp; // Time transfer was created } /* State variables */ /** * Mapping of the exchange balances */ mapping(address => mapping(address => uint256)) public tokens; /** * Mapping of all loans on the platform (id as key) */ mapping(uint256 => Loan) public loans; /** * Store the fee percent for the loans so fee percent changes don't affect existing loans. * Separate mapping needed since loan struct is too big already. */ mapping(uint256 => uint256) public loansFee; /** * Mapping of all deposits/withdrawals on the platform (id as key) */ mapping(uint256 => Transfer) public transfers; /** * Mapping of pricefeeds for all supported tokens on the platform */ mapping(address => AggregatorV3Interface) public priceFeeds; /** * Count of all loans on the platform -> used as ID */ uint256 public loanCount = 1; /** * Count of all transfers on the platform -> used as ID */ uint256 public transferCount = 1; /** * The address that receives all fee payments */ address public feeAccount; /** * The fee charged for the interest generated on the platform in basis points: 5% -> 500 */ uint256 public feePercent; /** * The maximum LTV for new loans */ uint256 public maxLTV; /** * The maximum LTV for exiting loans. If LTV exceeds this threshold the lender can force liquidate loan */ uint256 public ltvThreshold; /** * The time that needs to pass after loan expiration after which the lender can force liquidate the loan if it is not payed back */ uint256 public expirationBuffer = 60 * 60 * 24 * 7; // 7 days /** * The address of the Coinlend Credits token */ address public coinlendCredits; /** * Discount in percent for paying with Coinlend Credits */ uint256 public coinlendCreditsDiscount; /* Events */ event LoanListingCreated( // Attributes of an loan uint256 id, // Unique identifier for loan address user, // Creater of the loan address lender, // User who is lending address tokenLending, // Address of the token they receive uint256 tokenLendingAmount, // Amount to lend address borrower, // user who is borowwing address tokenCollateral, // Address of token for the collateral uint256 tokenCollateralAmount, // Amount collateral uint256 interestRate, uint256 loanDuration, uint256 loanState, uint256 timestamp // When loan was created ); event LoanListingCancelled( // Attributes of an loan uint256 id, // Unique identifier for loan address user, // user that created event address lender, // User who is lending address tokenLending, // Address of the token they receive uint256 tokenLendingAmount, // Amount to lend address borrower, address tokenCollateral, // Address of token for the collateral uint256 tokenCollateralAmount, // Amount collateral uint256 interestRate, uint256 loanDuration, uint256 loanState, uint256 timestamp // When loan was created ); event LoanTaken( // Attributes of an loan uint256 id, // Unique identifier for loan address user, address lender, // User who is lending address tokenLending, // Address of the token they receive uint256 tokenLendingAmount, // Amount to lend address borrower, address tokenCollateral, // Address of token for the collateral uint256 tokenCollateralAmount, // Amount collateral uint256 interestRate, uint256 loanDuration, uint256 loanState, uint256 timestamp // When loan was created ); event LoanPayBack( // Attributes of an loan uint256 id, // Unique identifier for loan address user, address lender, // User who is lending address tokenLending, // Address of the token they receive uint256 tokenLendingAmount, // Amount to lend address borrower, address tokenCollateral, // Address of token for the collateral uint256 tokenCollateralAmount, // Amount collateral uint256 interestRate, uint256 loanDuration, uint256 interest, uint256 timestamp // When loan was created ); event LoanOfferCancelled(address indexed loanProvider, uint256 loanId); event Deposit(uint256 id, address token, address user, uint256 amount, uint256 balance); event Withdraw(uint256 id, address token, address user, uint256 amount, uint256 balance); /* Functions */ constructor(address initialOwner) ReentrancyGuard() Ownable(initialOwner) { feeAccount = msg.sender; // Deployer will receive fees by default feePercent = 500; // 5% default fee maxLTV = 80; // Maximum LTV = 80% ltvThreshold = 90; // Loans can be liquidated if LTV exceed 90% } /** * Deposit tokens to the platform * @param _token Address of the token to deposit * @param _amount Amount of token to deposit */ function depositToken(address _token, uint256 _amount) public nonReentrant { // Only allow deposit of token with pricefeed (prevent deposit of fake token) require(getLatestPrice(_token) > 0); // Only allow valid amounts greater 0 require(_amount > 0); uint256 balanceBefore = IERC20(_token).balanceOf(address(this)); // Transfer tokens to exchange SafeERC20.safeTransferFrom( IERC20(_token), // Pass the token contract address as the first parameter msg.sender, // Sender of the tokens address(this), // Recipient of the tokens _amount // Amount of tokens to transfer ); // Special handling for deflationary tokens uint256 balanceAfter = IERC20(_token).balanceOf(address(this)); uint256 balanceDiff = balanceAfter - balanceBefore; if (balanceDiff < _amount) { _amount = balanceDiff; } // Update user balance tokens[_token][msg.sender] = tokens[_token][msg.sender] + _amount; transfers[transferCount] = Transfer( transferCount, msg.sender, _token, _amount, 0, block.timestamp ); // Emit deposit event emit Deposit(transferCount, _token, msg.sender, _amount, tokens[_token][msg.sender]); transferCount++; } /** * Withdraw tokens from the platform * @param _token Address of the token to withdraw * @param _amount Amount of token to withdraw */ function withdrawToken(address _token, uint256 _amount) public nonReentrant { // Ensure user has enough tokens to withdraw require(tokens[_token][msg.sender] >= _amount); // Transfer tokens to user SafeERC20.safeTransfer( IERC20(_token), // Pass the token contract address as the first parameter msg.sender, // Sender of the tokens _amount // Amount of tokens to transfer ); // Update user balance tokens[_token][msg.sender] = tokens[_token][msg.sender] - _amount; transfers[transferCount] = Transfer( transferCount, msg.sender, _token, _amount, 1, block.timestamp ); // Emit withdraw event emit Withdraw(transferCount, _token, msg.sender, _amount, tokens[_token][msg.sender]); transferCount++; } function balanceOf(address _token, address _user) public view returns (uint256) { return tokens[_token][_user]; } function createLoanLend( address _tokenLend, uint256 _tokenLendAmount, address _tokenCollateral, uint256 _interestRate, // Interest in basis points: 12% -> 1200 uint256 _loanDuration, uint256 _ltv ) public nonReentrant { require(_ltv > 0 && _ltv <= maxLTV); require(_interestRate >= 1 && _interestRate <= 10000); // Interest in basis points: 0,01% - 100% require(_tokenLendAmount > 0); require(_loanDuration > 0 && _loanDuration < 3650); require(balanceOf(_tokenLend, msg.sender) >= _tokenLendAmount); uint256 tokenCollateralAmount = (_tokenLendAmount * 100 * getLatestPrice(_tokenLend)) / _ltv / getLatestPrice(_tokenCollateral); tokens[_tokenLend][msg.sender] -= _tokenLendAmount; createLoanInternal( msg.sender, // loan creator msg.sender, _tokenLend, _tokenLendAmount, address(0), _tokenCollateral, tokenCollateralAmount, _interestRate, _loanDuration ); } function createLoanBorrow( address _tokenLend, uint256 _tokenLendAmount, address _tokenCollateral, uint256 _interestRate, uint256 _loanDuration, uint256 _ltv ) public nonReentrant { require(_ltv > 0 && _ltv <= maxLTV); require(_interestRate >= 1 && _interestRate <= 10000); // Interest in basis points: 0,01% - 100% require(_tokenLendAmount > 0); require(_loanDuration > 0 && _loanDuration < 3650); uint256 tokenCollateralAmount = (_tokenLendAmount * 100 * getLatestPrice(_tokenLend)) / _ltv / getLatestPrice(_tokenCollateral); require(balanceOf(_tokenCollateral, msg.sender) >= tokenCollateralAmount); tokens[_tokenCollateral][msg.sender] -= tokenCollateralAmount; createLoanInternal( msg.sender, // loan creator address(0), _tokenLend, _tokenLendAmount, msg.sender, _tokenCollateral, tokenCollateralAmount, _interestRate, _loanDuration ); } function createLoanInternal( address _user, address _lender, address _tokenLending, uint256 _tokenLendingAmount, address _borrower, address _tokenCollateral, uint256 _tokenCollateralAmount, // Amount collateral uint256 _interestRate, // Interest in basis points: 12% -> 1200 uint256 _loanDuration ) internal { loans[loanCount] = Loan( loanCount, _user, _lender, _tokenLending, _tokenLendingAmount, _tokenCollateral, _tokenCollateralAmount, _interestRate, _loanDuration, 0, _borrower, block.timestamp ); loansFee[loanCount] = feePercent; // Emit event emit LoanListingCreated( loanCount, _user, // loan creator _lender, _tokenLending, _tokenLendingAmount, _borrower, _tokenCollateral, _tokenCollateralAmount, _interestRate, _loanDuration, 0, block.timestamp ); loanCount++; } function cancelLoan(uint256 _id) public nonReentrant { // Fetch loan Loan storage _loan = loans[_id]; // Ensure the caller of the function is the owner of the loan require(address(_loan.user) == msg.sender); // Ensue the loan is in state open require(_loan.loanState == 0); // Update loan state _loan.loanState = 1; if (_loan.borrower == address(0)) { tokens[_loan.tokenLending][_loan.lender] += _loan.tokenLendingAmount; } else if (_loan.lender == address(0)) { tokens[_loan.tokenCollateral][_loan.borrower] += _loan.tokenCollateralAmount; } // Emit event emit LoanListingCancelled( _loan.id, msg.sender, _loan.lender, _loan.tokenLending, _loan.tokenLendingAmount, _loan.borrower, _loan.tokenCollateral, _loan.tokenCollateralAmount, _loan.interestRate, _loan.loanDuration, 1, block.timestamp ); } function takeLoan(uint256 _id) public nonReentrant { // Fetch loan Loan storage _loan = loans[_id]; // Loan must exist require(_loan.id == _id); // Check loan state: Only open loans can be taken require(_loan.loanState == 0); // If user takes a lending offer -> check if he has enough collateral if (_loan.borrower == address(0)) { require(balanceOf(_loan.tokenCollateral, msg.sender) >= _loan.tokenCollateralAmount); } // If user provides funds for a borrow offer -> check if he has enough funds to lend if (_loan.lender == address(0)) { require(balanceOf(_loan.tokenLending, msg.sender) >= _loan.tokenLendingAmount); } _loan.loanState = 2; _loan.timestamp = block.timestamp; // Transfer tokens if (_loan.borrower == address(0)) { // Borrower takes a loan: Transfer lending amount to him and transfer collateral to contract // Transfer away collateral from borrower tokens[_loan.tokenCollateral][msg.sender] -= _loan.tokenCollateralAmount; // Transfer borrowed coins to borrower tokens[_loan.tokenLending][msg.sender] += _loan.tokenLendingAmount; _loan.borrower = msg.sender; } else if (_loan.lender == address(0)) { // Lender takes borrowing offer // Transfer borrowed coins to borrower tokens[_loan.tokenLending][_loan.borrower] += _loan.tokenLendingAmount; // Subtract borrowed coins from lender tokens[_loan.tokenLending][msg.sender] -= _loan.tokenLendingAmount; _loan.lender = msg.sender; } // Emit event emit LoanTaken( _loan.id, msg.sender, _loan.lender, _loan.tokenLending, _loan.tokenLendingAmount, _loan.borrower, _loan.tokenCollateral, _loan.tokenCollateralAmount, _loan.interestRate, _loan.loanDuration, 2, block.timestamp ); } function payBackLoan(uint256 _id) public nonReentrant { // Fetch loan Loan storage _loan = loans[_id]; // Ensure the caller of the function is the owner of the loan require(address(_loan.borrower) == msg.sender); // Only active loans can be paid back require(_loan.loanState == 2); _loan.loanState = 3; // Calculate interest uint256 interestAmount = calculateInterest( _loan.tokenLendingAmount, _loan.interestRate, _loan.timestamp, block.timestamp ); uint256 fee = calculateFee(interestAmount, loansFee[_id]); // Check if borrower has enough funds for payback require(hasBorrowerEnoughFundsForPayback(_loan, interestAmount)); payBackLoanInternal(_loan, interestAmount, fee); } function payBackLoanInternal(Loan memory _loan, uint256 _interestAmount, uint256 _fee) private { uint256 feeValue = (((_fee * getLatestPrice(_loan.tokenLending)) / (10 ** (ERC20(_loan.tokenLending).decimals()))) * (100 - coinlendCreditsDiscount)) / 100; // Transfer fee to fee account bool senderHasEnoughCredits = senderHasEnoughCoinlendCredits(feeValue); if (senderHasEnoughCredits) { tokens[coinlendCredits][feeAccount] += feeValue; } else { tokens[_loan.tokenLending][feeAccount] += _fee; } uint256 interestAmountMinusFee = _interestAmount - _fee; // Payback borrowed token to lender tokens[_loan.tokenLending][_loan.lender] += _loan.tokenLendingAmount + interestAmountMinusFee; if (senderHasEnoughCredits) { tokens[coinlendCredits][_loan.borrower] -= feeValue; // substract lending amount and interest from borrower balance tokens[_loan.tokenLending][_loan.borrower] -= (_loan.tokenLendingAmount + interestAmountMinusFee); } else { // substract lending amount and interest from borrower balance tokens[_loan.tokenLending][_loan.borrower] -= (_loan.tokenLendingAmount + _interestAmount); } // Payback collateral tokens[_loan.tokenCollateral][_loan.borrower] += _loan.tokenCollateralAmount; // Emit event emit LoanPayBack( _loan.id, msg.sender, _loan.lender, _loan.tokenLending, _loan.tokenLendingAmount, _loan.borrower, _loan.tokenCollateral, _loan.tokenCollateralAmount, _loan.interestRate, _loan.loanDuration, interestAmountMinusFee, block.timestamp ); } function hasBorrowerEnoughFundsForPayback( Loan memory _loan, uint256 _interestAmount ) internal view returns (bool) { return tokens[_loan.tokenLending][_loan.borrower] >= _loan.tokenLendingAmount + _interestAmount; } function senderHasEnoughCoinlendCredits(uint256 _feeValue) internal view returns (bool) { return balanceOf(coinlendCredits, msg.sender) >= _feeValue; } function calculateInterest( uint256 _tokenLendingAmount, uint256 _interestRate, uint256 _startTime, uint256 _endTime ) internal pure returns (uint256) { // End time needs to be bigger than the start time require(_endTime > _startTime); uint256 interestAmount = (((_tokenLendingAmount * _interestRate) * (_endTime - _startTime)) / 365 / 24 / 60 / 60 / 10000); return interestAmount; } function calculateFee( uint256 _interestAmount, uint256 _feePercent ) internal pure returns (uint256) { return (_interestAmount * _feePercent) / 10000; } function forceLiquidateExpiredLoan(uint256 _id) public nonReentrant { // Fetch loan Loan storage _loan = loans[_id]; // Ensure the caller of the function is the lender of the loan require(address(_loan.lender) == msg.sender); // Check loan state require(_loan.loanState == 2); // check loan is expired + buffer // Only loans which are expired the loan duration plus buffer can be liquidated require(_loan.timestamp + _loan.loanDuration + expirationBuffer < block.timestamp); // If borrower has enough of borrowed currency + fee -> payback lender and return collateral uint256 interestAmount = calculateInterest( _loan.tokenLendingAmount, _loan.interestRate, _loan.timestamp, block.timestamp ); uint256 fee = calculateFee(interestAmount, loansFee[_id]); // Check if borrower has enough funds for payback if (hasBorrowerEnoughFundsForPayback(_loan, interestAmount)) { payBackLoanInternal(_loan, interestAmount, fee); } else { // If borrower has not enough of borrowed currency + fee -> move ownership of collateral to lender tokens[_loan.tokenCollateral][_loan.lender] += _loan.tokenCollateralAmount; // Emit event emit LoanPayBack( _loan.id, msg.sender, _loan.lender, _loan.tokenLending, _loan.tokenLendingAmount, _loan.borrower, _loan.tokenCollateral, _loan.tokenCollateralAmount, _loan.interestRate, _loan.loanDuration, interestAmount - fee, block.timestamp ); } _loan.loanState = 3; } function forceLiquidateMarginExceeded(uint256 _id) public nonReentrant { // Fetch loan Loan storage _loan = loans[_id]; // Ensure the caller of the function is the lender of the loan require(address(_loan.lender) == msg.sender); // Check loan state require(_loan.loanState == 2); uint256 ltv = calculateLTV(_loan); // Loan can not be liquiditated since ltv threshold was not exeeded yet require(ltv > ltvThreshold); // If borrower has enough of borrowed currency + fee -> payback lender and return collateral uint256 interestAmount = calculateInterest( _loan.tokenLendingAmount, _loan.interestRate, _loan.timestamp, block.timestamp ); uint256 fee = calculateFee(interestAmount, loansFee[_id]); // Check if borrower has enough funds for payback if (hasBorrowerEnoughFundsForPayback(_loan, interestAmount)) { payBackLoanInternal(_loan, interestAmount, fee); } else { // If borrower has not enough of borrowed currency + fee -> move ownership of collateral to lender tokens[_loan.tokenCollateral][_loan.lender] += _loan.tokenCollateralAmount; // Emit event emit LoanPayBack( _loan.id, msg.sender, _loan.lender, _loan.tokenLending, _loan.tokenLendingAmount, _loan.borrower, _loan.tokenCollateral, _loan.tokenCollateralAmount, _loan.interestRate, _loan.loanDuration, interestAmount - fee, block.timestamp ); } _loan.loanState = 3; } /** * Increase the collateral amount of the loan for the given loan ID */ function increaseCollateral(uint256 _id, uint256 _amount) public nonReentrant { // Fetch loan Loan storage _loan = loans[_id]; // Ensure the caller of the function is the borrower of the loan require(address(_loan.borrower) == msg.sender); // Check loan state require(_loan.loanState == 2); // check if borrower has enough funds to increase collateral require(tokens[_loan.tokenCollateral][msg.sender] >= _amount); tokens[_loan.tokenCollateral][_loan.borrower] -= _amount; _loan.tokenCollateralAmount += _amount; } /** * Returns the latest price adjusted for the decimals of the token */ function getLatestPrice(address _currencyAddress) public view returns (uint256) { (uint80 roundID, int price, , uint256 timeStamp, uint80 answeredInRound) = priceFeeds[ _currencyAddress ].latestRoundData(); uint256 decimalsFeed = priceFeeds[_currencyAddress].decimals(); // Validate price feed data require(price > 0 && answeredInRound >= roundID && timeStamp != 0); return uint256(price) * 10 ** (18 - decimalsFeed); // Price comes with variable decimals but we need 18 } function calculateLTV(uint256 _loanId) internal view returns (uint256) { return calculateLTV(loans[_loanId]); } function calculateLTV(Loan memory _loan) internal view returns (uint256) { uint256 tokenLendingTotalValue = (getLatestPrice(_loan.tokenLending) * _loan.tokenLendingAmount); uint256 tokenCollateralTotalValue = (getLatestPrice(_loan.tokenCollateral) * _loan.tokenCollateralAmount); return (tokenLendingTotalValue * 100) / tokenCollateralTotalValue; } function addPriceFeed(address _currencyAddress, address _priceFeedAddress) public onlyOwner { priceFeeds[_currencyAddress] = AggregatorV3Interface(_priceFeedAddress); } function setMaxLTV(uint256 _maxLTV) public onlyOwner { require(maxLTV > 0); maxLTV = _maxLTV; } function setFeeAccount(address _feeAccount) public onlyOwner { feeAccount = _feeAccount; } function setExpirationBuffer(uint256 _expirationBuffer) public onlyOwner { expirationBuffer = _expirationBuffer; } function setCoinlendCredits(address _coinlendCredits) public onlyOwner { coinlendCredits = _coinlendCredits; } function setFeePercent(uint256 _feePercent) public onlyOwner { require(_feePercent <= 3000); // limit fee to max 30% feePercent = _feePercent; } function setCoinlendCreditsDiscount(uint256 _coinlendCreditsDiscount) public onlyOwner { coinlendCreditsDiscount = _coinlendCreditsDiscount; } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"initialOwner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"balance","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"address","name":"lender","type":"address"},{"indexed":false,"internalType":"address","name":"tokenLending","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenLendingAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"address","name":"tokenCollateral","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenCollateralAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"interestRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"loanDuration","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"loanState","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"LoanListingCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"address","name":"lender","type":"address"},{"indexed":false,"internalType":"address","name":"tokenLending","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenLendingAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"address","name":"tokenCollateral","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenCollateralAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"interestRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"loanDuration","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"loanState","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"LoanListingCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"loanProvider","type":"address"},{"indexed":false,"internalType":"uint256","name":"loanId","type":"uint256"}],"name":"LoanOfferCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"address","name":"lender","type":"address"},{"indexed":false,"internalType":"address","name":"tokenLending","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenLendingAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"address","name":"tokenCollateral","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenCollateralAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"interestRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"loanDuration","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"interest","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"LoanPayBack","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"address","name":"lender","type":"address"},{"indexed":false,"internalType":"address","name":"tokenLending","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenLendingAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"address","name":"tokenCollateral","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenCollateralAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"interestRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"loanDuration","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"loanState","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"LoanTaken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"balance","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[{"internalType":"address","name":"_currencyAddress","type":"address"},{"internalType":"address","name":"_priceFeedAddress","type":"address"}],"name":"addPriceFeed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_user","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"cancelLoan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"coinlendCredits","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"coinlendCreditsDiscount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenLend","type":"address"},{"internalType":"uint256","name":"_tokenLendAmount","type":"uint256"},{"internalType":"address","name":"_tokenCollateral","type":"address"},{"internalType":"uint256","name":"_interestRate","type":"uint256"},{"internalType":"uint256","name":"_loanDuration","type":"uint256"},{"internalType":"uint256","name":"_ltv","type":"uint256"}],"name":"createLoanBorrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenLend","type":"address"},{"internalType":"uint256","name":"_tokenLendAmount","type":"uint256"},{"internalType":"address","name":"_tokenCollateral","type":"address"},{"internalType":"uint256","name":"_interestRate","type":"uint256"},{"internalType":"uint256","name":"_loanDuration","type":"uint256"},{"internalType":"uint256","name":"_ltv","type":"uint256"}],"name":"createLoanLend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"expirationBuffer","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeAccount","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feePercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"forceLiquidateExpiredLoan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"forceLiquidateMarginExceeded","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_currencyAddress","type":"address"}],"name":"getLatestPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"increaseCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"loanCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"loans","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"lender","type":"address"},{"internalType":"address","name":"tokenLending","type":"address"},{"internalType":"uint256","name":"tokenLendingAmount","type":"uint256"},{"internalType":"address","name":"tokenCollateral","type":"address"},{"internalType":"uint256","name":"tokenCollateralAmount","type":"uint256"},{"internalType":"uint256","name":"interestRate","type":"uint256"},{"internalType":"uint256","name":"loanDuration","type":"uint256"},{"internalType":"uint256","name":"loanState","type":"uint256"},{"internalType":"address","name":"borrower","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"loansFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ltvThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxLTV","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"payBackLoan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"priceFeeds","outputs":[{"internalType":"contract AggregatorV3Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_coinlendCredits","type":"address"}],"name":"setCoinlendCredits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_coinlendCreditsDiscount","type":"uint256"}],"name":"setCoinlendCreditsDiscount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_expirationBuffer","type":"uint256"}],"name":"setExpirationBuffer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeAccount","type":"address"}],"name":"setFeeAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_feePercent","type":"uint256"}],"name":"setFeePercent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxLTV","type":"uint256"}],"name":"setMaxLTV","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"takeLoan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"tokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"transferCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"transfers","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"internalType":"uint256","name":"transferType","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawToken","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040526001600755600160085562093a80600d5534801562000021575f80fd5b5060405162005a8238038062005a8283398181016040528101906200004791906200025c565b8060015f819055505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603620000c2575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401620000b991906200029d565b60405180910390fd5b620000d3816200013460201b60201c565b503360095f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101f4600a819055506050600b81905550605a600c8190555050620002b8565b5f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6200022682620001fb565b9050919050565b62000238816200021a565b811462000243575f80fd5b50565b5f8151905062000256816200022d565b92915050565b5f60208284031215620002745762000273620001f7565b5b5f620002838482850162000246565b91505092915050565b62000297816200021a565b82525050565b5f602082019050620002b25f8301846200028c565b92915050565b6157bc80620002c65f395ff3fe608060405234801561000f575f80fd5b506004361061021a575f3560e01c80639377d71111610123578063e0384691116100ab578063f0af5b711161007a578063f0af5b711461060a578063f2fde38b14610626578063f384bd0514610642578063f7888aec14610660578063fb9ee6c7146106905761021a565b8063e038469114610579578063e1ec3c6814610595578063e3d33fc9146105d0578063e8a97a3e146105ee5761021a565b8063b2b3ff4b116100f2578063b2b3ff4b146104d5578063bdbfa3de146104f3578063ce63094d1461050f578063d7b4c4e11461052d578063df6d088d146105495761021a565b80639377d711146104365780639dcb511a1461046b5780639e281a981461049b578063aedd2dfc146104b75761021a565b80636faa8b3f116101a6578063803e265d11610175578063803e265d146103a45780638c803fc2146103c25780638da5cb5b146103de578063929d106f146103fc5780639340817a1461041a5761021a565b80636faa8b3f14610344578063715018a6146103605780637ce3489b1461036a5780637fd6f15c146103865761021a565b8063338b5dea116101ed578063338b5dea146102a25780634b023cf8146102be578063508493bc146102da57806354f0cb0d1461030a57806365e17c9d146103265761021a565b806308a0c3751461021e57806316345f181461023a5780631cdd78301461026a57806325b6905914610286575b5f80fd5b610238600480360381019061023391906149da565b6106ac565b005b610254600480360381019061024f9190614a5f565b6106cb565b6040516102619190614a99565b60405180910390f35b610284600480360381019061027f91906149da565b6108dc565b005b6102a0600480360381019061029b91906149da565b6111aa565b005b6102bc60048036038101906102b79190614ab2565b61188f565b005b6102d860048036038101906102d39190614a5f565b611cd4565b005b6102f460048036038101906102ef9190614af0565b611d1f565b6040516103019190614a99565b60405180910390f35b610324600480360381019061031f9190614b2e565b611d3f565b005b61032e611f67565b60405161033b9190614b7b565b60405180910390f35b61035e600480360381019061035991906149da565b611f8c565b005b610368612474565b005b610384600480360381019061037f91906149da565b612487565b005b61038e6124a7565b60405161039b9190614a99565b60405180910390f35b6103ac6124ad565b6040516103b99190614a99565b60405180910390f35b6103dc60048036038101906103d791906149da565b6124b3565b005b6103e6612b4c565b6040516103f39190614b7b565b60405180910390f35b610404612b74565b6040516104119190614b7b565b60405180910390f35b610434600480360381019061042f91906149da565b612b99565b005b610450600480360381019061044b91906149da565b612bab565b60405161046296959493929190614b94565b60405180910390f35b61048560048036038101906104809190614a5f565b612c21565b6040516104929190614c4e565b60405180910390f35b6104b560048036038101906104b09190614ab2565b612c51565b005b6104bf612fe8565b6040516104cc9190614a99565b60405180910390f35b6104dd612fee565b6040516104ea9190614a99565b60405180910390f35b61050d600480360381019061050891906149da565b612ff4565b005b6105176133df565b6040516105249190614a99565b60405180910390f35b61054760048036038101906105429190614a5f565b6133e5565b005b610563600480360381019061055e91906149da565b613430565b6040516105709190614a99565b60405180910390f35b610593600480360381019061058e9190614c67565b613445565b005b6105af60048036038101906105aa91906149da565b6135aa565b6040516105c79c9b9a99989796959493929190614cf0565b60405180910390f35b6105d86136a1565b6040516105e59190614a99565b60405180910390f35b61060860048036038101906106039190614af0565b6136a7565b005b610624600480360381019061061f91906149da565b61372e565b005b610640600480360381019061063b9190614a5f565b613740565b005b61064a6137c4565b6040516106579190614a99565b60405180910390f35b61067a60048036038101906106759190614af0565b6137ca565b6040516106879190614a99565b60405180910390f35b6106aa60048036038101906106a59190614c67565b61384c565b005b6106b46139b1565b5f600b54116106c1575f80fd5b80600b8190555050565b5f805f805f60065f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610775573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107999190614e2e565b9450945050935093505f60065f8873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610848573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061086c9190614edb565b60ff1690505f8413801561089857508469ffffffffffffffffffff168269ffffffffffffffffffff1610155b80156108a457505f8314155b6108ac575f80fd5b8060126108b99190614f33565b600a6108c59190615095565b846108d091906150df565b95505050505050919050565b6108e4613a38565b5f60035f8381526020019081526020015f2090503373ffffffffffffffffffffffffffffffffffffffff16816002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610952575f80fd5b6002816009015414610962575f80fd5b5f610b6682604051806101800160405290815f8201548152602001600182015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600282015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600382015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160048201548152602001600582015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160068201548152602001600782015481526020016008820154815260200160098201548152602001600a82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600b82015481525050613a7c565b9050600c548111610b75575f80fd5b5f610b8e8360040154846007015485600b015442613adc565b90505f610bac8260045f8881526020019081526020015f2054613b56565b9050610db284604051806101800160405290815f8201548152602001600182015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600282015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600382015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160048201548152602001600582015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160068201548152602001600782015481526020016008820154815260200160098201548152602001600a82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600b8201548152505083613b78565b15610fc157610fbc84604051806101800160405290815f8201548152602001600182015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600282015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600382015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160048201548152602001600582015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160068201548152602001600782015481526020016008820154815260200160098201548152602001600a82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600b820154815250508383613c15565b611191565b836006015460025f866005015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f866002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546110929190615120565b925050819055507f9cdc815dd4fb4c3e808deb72539377b7ee6e0cd3f227c5b48db4ad03f0eb64bb845f015433866002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16876003015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16886004015489600a015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff168a6005015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff168b600601548c600701548d600801548b8d61116f9190614f33565b426040516111889c9b9a99989796959493929190615153565b60405180910390a15b60038460090181905550505050506111a761424c565b50565b6111b2613a38565b5f60035f8381526020019081526020015f2090503373ffffffffffffffffffffffffffffffffffffffff16816002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611220575f80fd5b6002816009015414611230575f80fd5b42600d54826008015483600b01546112489190615120565b6112529190615120565b1061125b575f80fd5b5f6112748260040154836007015484600b015442613adc565b90505f6112928260045f8781526020019081526020015f2054613b56565b905061149883604051806101800160405290815f8201548152602001600182015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600282015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600382015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160048201548152602001600582015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160068201548152602001600782015481526020016008820154815260200160098201548152602001600a82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600b8201548152505083613b78565b156116a7576116a283604051806101800160405290815f8201548152602001600182015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600282015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600382015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160048201548152602001600582015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160068201548152602001600782015481526020016008820154815260200160098201548152602001600a82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600b820154815250508383613c15565b611877565b826006015460025f856005015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f856002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546117789190615120565b925050819055507f9cdc815dd4fb4c3e808deb72539377b7ee6e0cd3f227c5b48db4ad03f0eb64bb835f015433856002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16866003015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16876004015488600a015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16896005015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff168a600601548b600701548c600801548b8d6118559190614f33565b4260405161186e9c9b9a99989796959493929190615153565b60405180910390a15b6003836009018190555050505061188c61424c565b50565b611897613a38565b5f6118a1836106cb565b116118aa575f80fd5b5f81116118b5575f80fd5b5f8273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016118ef9190614b7b565b602060405180830381865afa15801561190a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061192e919061520b565b905061193c83333085614255565b5f8373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016119769190614b7b565b602060405180830381865afa158015611991573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119b5919061520b565b90505f82826119c49190614f33565b9050838110156119d2578093505b8360025f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054611a569190615120565b60025f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055506040518060c0016040528060085481526020013373ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018581526020015f81526020014281525060055f60085481526020019081526020015f205f820151815f01556020820151816001015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506040820151816002015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301556080820151816004015560a082015181600501559050507feb65d0f36862bbd8763c5e2c983c9d753267d223eee35a224d8d0a9d7ef433a260085486338760025f8b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054604051611ca6959493929190615236565b60405180910390a160085f815480929190611cc090615287565b9190505550505050611cd061424c565b5050565b611cdc6139b1565b8060095f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6002602052815f5260405f20602052805f5260405f205f91509150505481565b611d47613a38565b5f60035f8481526020019081526020015f2090503373ffffffffffffffffffffffffffffffffffffffff1681600a015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611db5575f80fd5b6002816009015414611dc5575f80fd5b8160025f836005015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611e6c575f80fd5b8160025f836005015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f83600a015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611f399190614f33565b9250508190555081816006015f828254611f539190615120565b9250508190555050611f6361424c565b5050565b60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611f94613a38565b5f60035f8381526020019081526020015f2090503373ffffffffffffffffffffffffffffffffffffffff1681600a015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612002575f80fd5b6002816009015414612012575f80fd5b600381600901819055505f6120358260040154836007015484600b015442613adc565b90505f6120538260045f8781526020019081526020015f2054613b56565b905061225983604051806101800160405290815f8201548152602001600182015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600282015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600382015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160048201548152602001600582015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160068201548152602001600782015481526020016008820154815260200160098201548152602001600a82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600b8201548152505083613b78565b612261575f80fd5b61246683604051806101800160405290815f8201548152602001600182015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600282015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600382015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160048201548152602001600582015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160068201548152602001600782015481526020016008820154815260200160098201548152602001600a82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600b820154815250508383613c15565b50505061247161424c565b50565b61247c6139b1565b6124855f6142d7565b565b61248f6139b1565b610bb881111561249d575f80fd5b80600a8190555050565b600a5481565b600f5481565b6124bb613a38565b5f60035f8381526020019081526020015f20905081815f0154146124dd575f80fd5b5f8160090154146124ec575f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff1681600a015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff160361257f578060060154612574826005015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16336137ca565b101561257e575f80fd5b5b5f73ffffffffffffffffffffffffffffffffffffffff16816002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1603612612578060040154612607826003015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16336137ca565b1015612611575f80fd5b5b600281600901819055504281600b01819055505f73ffffffffffffffffffffffffffffffffffffffff1681600a015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff160361282c57806006015460025f836005015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546127299190614f33565b92505081905550806004015460025f836003015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546127de9190615120565b925050819055503381600a015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550612a53565b5f73ffffffffffffffffffffffffffffffffffffffff16816002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1603612a5257806004015460025f836003015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f83600a015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546129539190615120565b92505081905550806004015460025f836003015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612a089190614f33565b9250508190555033816002015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b5b7fdcafc6dbac5448cffb7b7888d7c84dc838744a5d806e90325d40920386eacd2f815f015433836002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16846003015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856004015486600a015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16876005015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16886006015489600701548a60080154600242604051612b389c9b9a99989796959493929190615307565b60405180910390a150612b4961424c565b50565b5f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600e5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b612ba16139b1565b80600f8190555050565b6005602052805f5260405f205f91509050805f015490806001015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690806002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060030154908060040154908060050154905086565b6006602052805f5260405f205f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b612c59613a38565b8060025f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612cdd575f80fd5b612ce882338361439a565b8060025f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054612d6c9190614f33565b60025f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055506040518060c0016040528060085481526020013373ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff168152602001828152602001600181526020014281525060055f60085481526020019081526020015f205f820151815f01556020820151816001015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506040820151816002015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301556080820151816004015560a082015181600501559050507ffe7813e2866053d5c3938554e517b554fce6666a6561bed9eaa7419b29fa9b6860085483338460025f8873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054604051612fbd959493929190615236565b60405180910390a160085f815480929190612fd790615287565b9190505550612fe461424c565b5050565b600c5481565b600d5481565b612ffc613a38565b5f60035f8381526020019081526020015f2090503373ffffffffffffffffffffffffffffffffffffffff16816001015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461306a575f80fd5b5f816009015414613079575f80fd5b600181600901819055505f73ffffffffffffffffffffffffffffffffffffffff1681600a015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16036131b657806004015460025f836003015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f836002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546131aa9190615120565b925050819055506132e6565b5f73ffffffffffffffffffffffffffffffffffffffff16816002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16036132e557806006015460025f836005015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f83600a015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546132dd9190615120565b925050819055505b5b7ff12c65f01e4cbc4711a3be05281e821ea706e98cac3d7fc25aa512be38d069d7815f015433836002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16846003015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856004015486600a015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16876005015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16886006015489600701548a600801546001426040516133cb9c9b9a999897969594939291906153f8565b60405180910390a1506133dc61424c565b50565b60075481565b6133ed6139b1565b80600e5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6004602052805f5260405f205f915090505481565b61344d613a38565b5f8111801561345e5750600b548111155b613466575f80fd5b6001831015801561347957506127108311155b613481575f80fd5b5f851161348c575f80fd5b5f8211801561349c5750610e4282105b6134a4575f80fd5b846134af87336137ca565b10156134b9575f80fd5b5f6134c3856106cb565b826134cd896106cb565b6064896134da91906150df565b6134e491906150df565b6134ee91906154dd565b6134f891906154dd565b90508560025f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546135819190614f33565b92505081905550613599333389895f8a878b8b614419565b506135a261424c565b505050505050565b6003602052805f5260405f205f91509050805f015490806001015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690806002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690806003015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690806004015490806005015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169080600601549080600701549080600801549080600901549080600a015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169080600b015490508c565b60085481565b6136af6139b1565b8060065f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b6137366139b1565b80600d8190555050565b6137486139b1565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036137b8575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016137af9190614b7b565b60405180910390fd5b6137c1816142d7565b50565b600b5481565b5f60025f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b613854613a38565b5f811180156138655750600b548111155b61386d575f80fd5b6001831015801561388057506127108311155b613888575f80fd5b5f8511613893575f80fd5b5f821180156138a35750610e4282105b6138ab575f80fd5b5f6138b5856106cb565b826138bf896106cb565b6064896138cc91906150df565b6138d691906150df565b6138e091906154dd565b6138ea91906154dd565b9050806138f786336137ca565b1015613901575f80fd5b8060025f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546139889190614f33565b925050819055506139a0335f8989338a878b8b614419565b506139a961424c565b505050505050565b6139b9614722565b73ffffffffffffffffffffffffffffffffffffffff166139d7612b4c565b73ffffffffffffffffffffffffffffffffffffffff1614613a36576139fa614722565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401613a2d9190614b7b565b60405180910390fd5b565b60025f5403613a73576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025f81905550565b5f808260800151613a9084606001516106cb565b613a9a91906150df565b90505f8360c00151613aaf8560a001516106cb565b613ab991906150df565b905080606483613ac991906150df565b613ad391906154dd565b92505050919050565b5f828211613ae8575f80fd5b5f612710603c80601861016d8888613b009190614f33565b8a8c613b0c91906150df565b613b1691906150df565b613b2091906154dd565b613b2a91906154dd565b613b3491906154dd565b613b3e91906154dd565b613b4891906154dd565b905080915050949350505050565b5f6127108284613b6691906150df565b613b7091906154dd565b905092915050565b5f818360800151613b899190615120565b60025f856060015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f85610140015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015905092915050565b5f6064600f546064613c279190614f33565b856060015173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015613c74573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613c989190614edb565b600a613ca4919061550d565b613cb187606001516106cb565b85613cbc91906150df565b613cc691906154dd565b613cd091906150df565b613cda91906154dd565b90505f613ce682614729565b90508015613dc3578160025f600e5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613db79190615120565b92505081905550613e77565b8260025f876060015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613e6f9190615120565b925050819055505b5f8385613e849190614f33565b9050808660800151613e969190615120565b60025f886060015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f886040015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613f249190615120565b925050819055508115614090578260025f600e5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f88610140015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613fde9190614f33565b92505081905550808660800151613ff59190615120565b60025f886060015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f88610140015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546140849190614f33565b92505081905550614137565b8486608001516140a09190615120565b60025f886060015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f88610140015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461412f9190614f33565b925050819055505b8560c0015160025f8860a0015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f88610140015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546141cb9190615120565b925050819055507f9cdc815dd4fb4c3e808deb72539377b7ee6e0cd3f227c5b48db4ad03f0eb64bb865f015133886040015189606001518a608001518b61014001518c60a001518d60c001518e60e001518f61010001518b4260405161423c9c9b9a99989796959493929190615153565b60405180910390a1505050505050565b60015f81905550565b6142d1848573ffffffffffffffffffffffffffffffffffffffff166323b872dd86868660405160240161428a93929190615557565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061475f565b50505050565b5f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b614414838473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85856040516024016143cd92919061558c565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061475f565b505050565b60405180610180016040528060075481526020018a73ffffffffffffffffffffffffffffffffffffffff1681526020018973ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018781526020018573ffffffffffffffffffffffffffffffffffffffff1681526020018481526020018381526020018281526020015f81526020018673ffffffffffffffffffffffffffffffffffffffff1681526020014281525060035f60075481526020019081526020015f205f820151815f01556020820151816001015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506040820151816002015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506060820151816003015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506080820151816004015560a0820151816005015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061016082015181600b0155905050600a5460045f60075481526020019081526020015f20819055507f2fbbf22c6ebe94502147a9c148009f41c67fe0f03501a407e2e4f72d8236133d6007548a8a8a8a8a8a8a8a8a5f426040516146f89c9b9a999897969594939291906155ec565b60405180910390a160075f81548092919061471290615287565b9190505550505050505050505050565b5f33905090565b5f81614756600e5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16336137ca565b10159050919050565b5f614789828473ffffffffffffffffffffffffffffffffffffffff166147f490919063ffffffff16565b90505f8151141580156147ad5750808060200190518101906147ab91906156d9565b155b156147ef57826040517f5274afe70000000000000000000000000000000000000000000000000000000081526004016147e69190614b7b565b60405180910390fd5b505050565b606061480183835f614809565b905092915050565b60608147101561485057306040517fcd7860590000000000000000000000000000000000000000000000000000000081526004016148479190614b7b565b60405180910390fd5b5f808573ffffffffffffffffffffffffffffffffffffffff1684866040516148789190615770565b5f6040518083038185875af1925050503d805f81146148b2576040519150601f19603f3d011682016040523d82523d5f602084013e6148b7565b606091505b50915091506148c78683836148d2565b925050509392505050565b6060826148e7576148e28261495f565b614957565b5f825114801561490d57505f8473ffffffffffffffffffffffffffffffffffffffff163b145b1561494f57836040517f9996b3150000000000000000000000000000000000000000000000000000000081526004016149469190614b7b565b60405180910390fd5b819050614958565b5b9392505050565b5f815111156149715780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80fd5b5f819050919050565b6149b9816149a7565b81146149c3575f80fd5b50565b5f813590506149d4816149b0565b92915050565b5f602082840312156149ef576149ee6149a3565b5b5f6149fc848285016149c6565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f614a2e82614a05565b9050919050565b614a3e81614a24565b8114614a48575f80fd5b50565b5f81359050614a5981614a35565b92915050565b5f60208284031215614a7457614a736149a3565b5b5f614a8184828501614a4b565b91505092915050565b614a93816149a7565b82525050565b5f602082019050614aac5f830184614a8a565b92915050565b5f8060408385031215614ac857614ac76149a3565b5b5f614ad585828601614a4b565b9250506020614ae6858286016149c6565b9150509250929050565b5f8060408385031215614b0657614b056149a3565b5b5f614b1385828601614a4b565b9250506020614b2485828601614a4b565b9150509250929050565b5f8060408385031215614b4457614b436149a3565b5b5f614b51858286016149c6565b9250506020614b62858286016149c6565b9150509250929050565b614b7581614a24565b82525050565b5f602082019050614b8e5f830184614b6c565b92915050565b5f60c082019050614ba75f830189614a8a565b614bb46020830188614b6c565b614bc16040830187614b6c565b614bce6060830186614a8a565b614bdb6080830185614a8a565b614be860a0830184614a8a565b979650505050505050565b5f819050919050565b5f614c16614c11614c0c84614a05565b614bf3565b614a05565b9050919050565b5f614c2782614bfc565b9050919050565b5f614c3882614c1d565b9050919050565b614c4881614c2e565b82525050565b5f602082019050614c615f830184614c3f565b92915050565b5f805f805f8060c08789031215614c8157614c806149a3565b5b5f614c8e89828a01614a4b565b9650506020614c9f89828a016149c6565b9550506040614cb089828a01614a4b565b9450506060614cc189828a016149c6565b9350506080614cd289828a016149c6565b92505060a0614ce389828a016149c6565b9150509295509295509295565b5f61018082019050614d045f83018f614a8a565b614d11602083018e614b6c565b614d1e604083018d614b6c565b614d2b606083018c614b6c565b614d38608083018b614a8a565b614d4560a083018a614b6c565b614d5260c0830189614a8a565b614d5f60e0830188614a8a565b614d6d610100830187614a8a565b614d7b610120830186614a8a565b614d89610140830185614b6c565b614d97610160830184614a8a565b9d9c50505050505050505050505050565b5f69ffffffffffffffffffff82169050919050565b614dc681614da8565b8114614dd0575f80fd5b50565b5f81519050614de181614dbd565b92915050565b5f819050919050565b614df981614de7565b8114614e03575f80fd5b50565b5f81519050614e1481614df0565b92915050565b5f81519050614e28816149b0565b92915050565b5f805f805f60a08688031215614e4757614e466149a3565b5b5f614e5488828901614dd3565b9550506020614e6588828901614e06565b9450506040614e7688828901614e1a565b9350506060614e8788828901614e1a565b9250506080614e9888828901614dd3565b9150509295509295909350565b5f60ff82169050919050565b614eba81614ea5565b8114614ec4575f80fd5b50565b5f81519050614ed581614eb1565b92915050565b5f60208284031215614ef057614eef6149a3565b5b5f614efd84828501614ec7565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f614f3d826149a7565b9150614f48836149a7565b9250828203905081811115614f6057614f5f614f06565b5b92915050565b5f8160011c9050919050565b5f808291508390505b6001851115614fbb57808604811115614f9757614f96614f06565b5b6001851615614fa65780820291505b8081029050614fb485614f66565b9450614f7b565b94509492505050565b5f82614fd3576001905061508e565b81614fe0575f905061508e565b8160018114614ff657600281146150005761502f565b600191505061508e565b60ff84111561501257615011614f06565b5b8360020a91508482111561502957615028614f06565b5b5061508e565b5060208310610133831016604e8410600b84101617156150645782820a90508381111561505f5761505e614f06565b5b61508e565b6150718484846001614f72565b9250905081840481111561508857615087614f06565b5b81810290505b9392505050565b5f61509f826149a7565b91506150aa836149a7565b92506150d77fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484614fc4565b905092915050565b5f6150e9826149a7565b91506150f4836149a7565b9250828202615102816149a7565b9150828204841483151761511957615118614f06565b5b5092915050565b5f61512a826149a7565b9150615135836149a7565b925082820190508082111561514d5761514c614f06565b5b92915050565b5f610180820190506151675f83018f614a8a565b615174602083018e614b6c565b615181604083018d614b6c565b61518e606083018c614b6c565b61519b608083018b614a8a565b6151a860a083018a614b6c565b6151b560c0830189614b6c565b6151c260e0830188614a8a565b6151d0610100830187614a8a565b6151de610120830186614a8a565b6151ec610140830185614a8a565b6151fa610160830184614a8a565b9d9c50505050505050505050505050565b5f602082840312156152205761521f6149a3565b5b5f61522d84828501614e1a565b91505092915050565b5f60a0820190506152495f830188614a8a565b6152566020830187614b6c565b6152636040830186614b6c565b6152706060830185614a8a565b61527d6080830184614a8a565b9695505050505050565b5f615291826149a7565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036152c3576152c2614f06565b5b600182019050919050565b5f819050919050565b5f6152f16152ec6152e7846152ce565b614bf3565b6149a7565b9050919050565b615301816152d7565b82525050565b5f6101808201905061531b5f83018f614a8a565b615328602083018e614b6c565b615335604083018d614b6c565b615342606083018c614b6c565b61534f608083018b614a8a565b61535c60a083018a614b6c565b61536960c0830189614b6c565b61537660e0830188614a8a565b615384610100830187614a8a565b615392610120830186614a8a565b6153a06101408301856152f8565b6153ae610160830184614a8a565b9d9c50505050505050505050505050565b5f819050919050565b5f6153e26153dd6153d8846153bf565b614bf3565b6149a7565b9050919050565b6153f2816153c8565b82525050565b5f6101808201905061540c5f83018f614a8a565b615419602083018e614b6c565b615426604083018d614b6c565b615433606083018c614b6c565b615440608083018b614a8a565b61544d60a083018a614b6c565b61545a60c0830189614b6c565b61546760e0830188614a8a565b615475610100830187614a8a565b615483610120830186614a8a565b6154916101408301856153e9565b61549f610160830184614a8a565b9d9c50505050505050505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f6154e7826149a7565b91506154f2836149a7565b925082615502576155016154b0565b5b828204905092915050565b5f615517826149a7565b915061552283614ea5565b925061554f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484614fc4565b905092915050565b5f60608201905061556a5f830186614b6c565b6155776020830185614b6c565b6155846040830184614a8a565b949350505050565b5f60408201905061559f5f830185614b6c565b6155ac6020830184614a8a565b9392505050565b5f819050919050565b5f6155d66155d16155cc846155b3565b614bf3565b6149a7565b9050919050565b6155e6816155bc565b82525050565b5f610180820190506156005f83018f614a8a565b61560d602083018e614b6c565b61561a604083018d614b6c565b615627606083018c614b6c565b615634608083018b614a8a565b61564160a083018a614b6c565b61564e60c0830189614b6c565b61565b60e0830188614a8a565b615669610100830187614a8a565b615677610120830186614a8a565b6156856101408301856155dd565b615693610160830184614a8a565b9d9c50505050505050505050505050565b5f8115159050919050565b6156b8816156a4565b81146156c2575f80fd5b50565b5f815190506156d3816156af565b92915050565b5f602082840312156156ee576156ed6149a3565b5b5f6156fb848285016156c5565b91505092915050565b5f81519050919050565b5f81905092915050565b5f5b8381101561573557808201518184015260208101905061571a565b5f8484015250505050565b5f61574a82615704565b615754818561570e565b9350615764818560208601615718565b80840191505092915050565b5f61577b8284615740565b91508190509291505056fea2646970667358221220af5a0ae2c27b8386bed1a02ef36a5deff53347387a1556aadc32e8a208c2416c64736f6c634300081400330000000000000000000000002726ffe32ad10b8264b9c44494d5f319caf92d76
Deployed Bytecode
0x608060405234801561000f575f80fd5b506004361061021a575f3560e01c80639377d71111610123578063e0384691116100ab578063f0af5b711161007a578063f0af5b711461060a578063f2fde38b14610626578063f384bd0514610642578063f7888aec14610660578063fb9ee6c7146106905761021a565b8063e038469114610579578063e1ec3c6814610595578063e3d33fc9146105d0578063e8a97a3e146105ee5761021a565b8063b2b3ff4b116100f2578063b2b3ff4b146104d5578063bdbfa3de146104f3578063ce63094d1461050f578063d7b4c4e11461052d578063df6d088d146105495761021a565b80639377d711146104365780639dcb511a1461046b5780639e281a981461049b578063aedd2dfc146104b75761021a565b80636faa8b3f116101a6578063803e265d11610175578063803e265d146103a45780638c803fc2146103c25780638da5cb5b146103de578063929d106f146103fc5780639340817a1461041a5761021a565b80636faa8b3f14610344578063715018a6146103605780637ce3489b1461036a5780637fd6f15c146103865761021a565b8063338b5dea116101ed578063338b5dea146102a25780634b023cf8146102be578063508493bc146102da57806354f0cb0d1461030a57806365e17c9d146103265761021a565b806308a0c3751461021e57806316345f181461023a5780631cdd78301461026a57806325b6905914610286575b5f80fd5b610238600480360381019061023391906149da565b6106ac565b005b610254600480360381019061024f9190614a5f565b6106cb565b6040516102619190614a99565b60405180910390f35b610284600480360381019061027f91906149da565b6108dc565b005b6102a0600480360381019061029b91906149da565b6111aa565b005b6102bc60048036038101906102b79190614ab2565b61188f565b005b6102d860048036038101906102d39190614a5f565b611cd4565b005b6102f460048036038101906102ef9190614af0565b611d1f565b6040516103019190614a99565b60405180910390f35b610324600480360381019061031f9190614b2e565b611d3f565b005b61032e611f67565b60405161033b9190614b7b565b60405180910390f35b61035e600480360381019061035991906149da565b611f8c565b005b610368612474565b005b610384600480360381019061037f91906149da565b612487565b005b61038e6124a7565b60405161039b9190614a99565b60405180910390f35b6103ac6124ad565b6040516103b99190614a99565b60405180910390f35b6103dc60048036038101906103d791906149da565b6124b3565b005b6103e6612b4c565b6040516103f39190614b7b565b60405180910390f35b610404612b74565b6040516104119190614b7b565b60405180910390f35b610434600480360381019061042f91906149da565b612b99565b005b610450600480360381019061044b91906149da565b612bab565b60405161046296959493929190614b94565b60405180910390f35b61048560048036038101906104809190614a5f565b612c21565b6040516104929190614c4e565b60405180910390f35b6104b560048036038101906104b09190614ab2565b612c51565b005b6104bf612fe8565b6040516104cc9190614a99565b60405180910390f35b6104dd612fee565b6040516104ea9190614a99565b60405180910390f35b61050d600480360381019061050891906149da565b612ff4565b005b6105176133df565b6040516105249190614a99565b60405180910390f35b61054760048036038101906105429190614a5f565b6133e5565b005b610563600480360381019061055e91906149da565b613430565b6040516105709190614a99565b60405180910390f35b610593600480360381019061058e9190614c67565b613445565b005b6105af60048036038101906105aa91906149da565b6135aa565b6040516105c79c9b9a99989796959493929190614cf0565b60405180910390f35b6105d86136a1565b6040516105e59190614a99565b60405180910390f35b61060860048036038101906106039190614af0565b6136a7565b005b610624600480360381019061061f91906149da565b61372e565b005b610640600480360381019061063b9190614a5f565b613740565b005b61064a6137c4565b6040516106579190614a99565b60405180910390f35b61067a60048036038101906106759190614af0565b6137ca565b6040516106879190614a99565b60405180910390f35b6106aa60048036038101906106a59190614c67565b61384c565b005b6106b46139b1565b5f600b54116106c1575f80fd5b80600b8190555050565b5f805f805f60065f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610775573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107999190614e2e565b9450945050935093505f60065f8873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610848573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061086c9190614edb565b60ff1690505f8413801561089857508469ffffffffffffffffffff168269ffffffffffffffffffff1610155b80156108a457505f8314155b6108ac575f80fd5b8060126108b99190614f33565b600a6108c59190615095565b846108d091906150df565b95505050505050919050565b6108e4613a38565b5f60035f8381526020019081526020015f2090503373ffffffffffffffffffffffffffffffffffffffff16816002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610952575f80fd5b6002816009015414610962575f80fd5b5f610b6682604051806101800160405290815f8201548152602001600182015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600282015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600382015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160048201548152602001600582015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160068201548152602001600782015481526020016008820154815260200160098201548152602001600a82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600b82015481525050613a7c565b9050600c548111610b75575f80fd5b5f610b8e8360040154846007015485600b015442613adc565b90505f610bac8260045f8881526020019081526020015f2054613b56565b9050610db284604051806101800160405290815f8201548152602001600182015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600282015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600382015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160048201548152602001600582015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160068201548152602001600782015481526020016008820154815260200160098201548152602001600a82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600b8201548152505083613b78565b15610fc157610fbc84604051806101800160405290815f8201548152602001600182015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600282015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600382015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160048201548152602001600582015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160068201548152602001600782015481526020016008820154815260200160098201548152602001600a82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600b820154815250508383613c15565b611191565b836006015460025f866005015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f866002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546110929190615120565b925050819055507f9cdc815dd4fb4c3e808deb72539377b7ee6e0cd3f227c5b48db4ad03f0eb64bb845f015433866002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16876003015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16886004015489600a015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff168a6005015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff168b600601548c600701548d600801548b8d61116f9190614f33565b426040516111889c9b9a99989796959493929190615153565b60405180910390a15b60038460090181905550505050506111a761424c565b50565b6111b2613a38565b5f60035f8381526020019081526020015f2090503373ffffffffffffffffffffffffffffffffffffffff16816002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611220575f80fd5b6002816009015414611230575f80fd5b42600d54826008015483600b01546112489190615120565b6112529190615120565b1061125b575f80fd5b5f6112748260040154836007015484600b015442613adc565b90505f6112928260045f8781526020019081526020015f2054613b56565b905061149883604051806101800160405290815f8201548152602001600182015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600282015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600382015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160048201548152602001600582015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160068201548152602001600782015481526020016008820154815260200160098201548152602001600a82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600b8201548152505083613b78565b156116a7576116a283604051806101800160405290815f8201548152602001600182015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600282015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600382015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160048201548152602001600582015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160068201548152602001600782015481526020016008820154815260200160098201548152602001600a82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600b820154815250508383613c15565b611877565b826006015460025f856005015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f856002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546117789190615120565b925050819055507f9cdc815dd4fb4c3e808deb72539377b7ee6e0cd3f227c5b48db4ad03f0eb64bb835f015433856002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16866003015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16876004015488600a015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16896005015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff168a600601548b600701548c600801548b8d6118559190614f33565b4260405161186e9c9b9a99989796959493929190615153565b60405180910390a15b6003836009018190555050505061188c61424c565b50565b611897613a38565b5f6118a1836106cb565b116118aa575f80fd5b5f81116118b5575f80fd5b5f8273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016118ef9190614b7b565b602060405180830381865afa15801561190a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061192e919061520b565b905061193c83333085614255565b5f8373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016119769190614b7b565b602060405180830381865afa158015611991573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119b5919061520b565b90505f82826119c49190614f33565b9050838110156119d2578093505b8360025f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054611a569190615120565b60025f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055506040518060c0016040528060085481526020013373ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018581526020015f81526020014281525060055f60085481526020019081526020015f205f820151815f01556020820151816001015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506040820151816002015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301556080820151816004015560a082015181600501559050507feb65d0f36862bbd8763c5e2c983c9d753267d223eee35a224d8d0a9d7ef433a260085486338760025f8b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054604051611ca6959493929190615236565b60405180910390a160085f815480929190611cc090615287565b9190505550505050611cd061424c565b5050565b611cdc6139b1565b8060095f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6002602052815f5260405f20602052805f5260405f205f91509150505481565b611d47613a38565b5f60035f8481526020019081526020015f2090503373ffffffffffffffffffffffffffffffffffffffff1681600a015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611db5575f80fd5b6002816009015414611dc5575f80fd5b8160025f836005015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611e6c575f80fd5b8160025f836005015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f83600a015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611f399190614f33565b9250508190555081816006015f828254611f539190615120565b9250508190555050611f6361424c565b5050565b60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611f94613a38565b5f60035f8381526020019081526020015f2090503373ffffffffffffffffffffffffffffffffffffffff1681600a015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612002575f80fd5b6002816009015414612012575f80fd5b600381600901819055505f6120358260040154836007015484600b015442613adc565b90505f6120538260045f8781526020019081526020015f2054613b56565b905061225983604051806101800160405290815f8201548152602001600182015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600282015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600382015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160048201548152602001600582015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160068201548152602001600782015481526020016008820154815260200160098201548152602001600a82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600b8201548152505083613b78565b612261575f80fd5b61246683604051806101800160405290815f8201548152602001600182015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600282015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600382015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160048201548152602001600582015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160068201548152602001600782015481526020016008820154815260200160098201548152602001600a82015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600b820154815250508383613c15565b50505061247161424c565b50565b61247c6139b1565b6124855f6142d7565b565b61248f6139b1565b610bb881111561249d575f80fd5b80600a8190555050565b600a5481565b600f5481565b6124bb613a38565b5f60035f8381526020019081526020015f20905081815f0154146124dd575f80fd5b5f8160090154146124ec575f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff1681600a015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff160361257f578060060154612574826005015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16336137ca565b101561257e575f80fd5b5b5f73ffffffffffffffffffffffffffffffffffffffff16816002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1603612612578060040154612607826003015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16336137ca565b1015612611575f80fd5b5b600281600901819055504281600b01819055505f73ffffffffffffffffffffffffffffffffffffffff1681600a015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff160361282c57806006015460025f836005015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546127299190614f33565b92505081905550806004015460025f836003015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546127de9190615120565b925050819055503381600a015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550612a53565b5f73ffffffffffffffffffffffffffffffffffffffff16816002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1603612a5257806004015460025f836003015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f83600a015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546129539190615120565b92505081905550806004015460025f836003015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612a089190614f33565b9250508190555033816002015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b5b7fdcafc6dbac5448cffb7b7888d7c84dc838744a5d806e90325d40920386eacd2f815f015433836002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16846003015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856004015486600a015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16876005015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16886006015489600701548a60080154600242604051612b389c9b9a99989796959493929190615307565b60405180910390a150612b4961424c565b50565b5f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600e5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b612ba16139b1565b80600f8190555050565b6005602052805f5260405f205f91509050805f015490806001015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690806002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060030154908060040154908060050154905086565b6006602052805f5260405f205f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b612c59613a38565b8060025f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612cdd575f80fd5b612ce882338361439a565b8060025f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054612d6c9190614f33565b60025f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055506040518060c0016040528060085481526020013373ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff168152602001828152602001600181526020014281525060055f60085481526020019081526020015f205f820151815f01556020820151816001015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506040820151816002015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301556080820151816004015560a082015181600501559050507ffe7813e2866053d5c3938554e517b554fce6666a6561bed9eaa7419b29fa9b6860085483338460025f8873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054604051612fbd959493929190615236565b60405180910390a160085f815480929190612fd790615287565b9190505550612fe461424c565b5050565b600c5481565b600d5481565b612ffc613a38565b5f60035f8381526020019081526020015f2090503373ffffffffffffffffffffffffffffffffffffffff16816001015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461306a575f80fd5b5f816009015414613079575f80fd5b600181600901819055505f73ffffffffffffffffffffffffffffffffffffffff1681600a015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16036131b657806004015460025f836003015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f836002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546131aa9190615120565b925050819055506132e6565b5f73ffffffffffffffffffffffffffffffffffffffff16816002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16036132e557806006015460025f836005015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f83600a015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546132dd9190615120565b925050819055505b5b7ff12c65f01e4cbc4711a3be05281e821ea706e98cac3d7fc25aa512be38d069d7815f015433836002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16846003015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856004015486600a015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16876005015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16886006015489600701548a600801546001426040516133cb9c9b9a999897969594939291906153f8565b60405180910390a1506133dc61424c565b50565b60075481565b6133ed6139b1565b80600e5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6004602052805f5260405f205f915090505481565b61344d613a38565b5f8111801561345e5750600b548111155b613466575f80fd5b6001831015801561347957506127108311155b613481575f80fd5b5f851161348c575f80fd5b5f8211801561349c5750610e4282105b6134a4575f80fd5b846134af87336137ca565b10156134b9575f80fd5b5f6134c3856106cb565b826134cd896106cb565b6064896134da91906150df565b6134e491906150df565b6134ee91906154dd565b6134f891906154dd565b90508560025f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546135819190614f33565b92505081905550613599333389895f8a878b8b614419565b506135a261424c565b505050505050565b6003602052805f5260405f205f91509050805f015490806001015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690806002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690806003015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690806004015490806005015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169080600601549080600701549080600801549080600901549080600a015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169080600b015490508c565b60085481565b6136af6139b1565b8060065f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b6137366139b1565b80600d8190555050565b6137486139b1565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036137b8575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016137af9190614b7b565b60405180910390fd5b6137c1816142d7565b50565b600b5481565b5f60025f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b613854613a38565b5f811180156138655750600b548111155b61386d575f80fd5b6001831015801561388057506127108311155b613888575f80fd5b5f8511613893575f80fd5b5f821180156138a35750610e4282105b6138ab575f80fd5b5f6138b5856106cb565b826138bf896106cb565b6064896138cc91906150df565b6138d691906150df565b6138e091906154dd565b6138ea91906154dd565b9050806138f786336137ca565b1015613901575f80fd5b8060025f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546139889190614f33565b925050819055506139a0335f8989338a878b8b614419565b506139a961424c565b505050505050565b6139b9614722565b73ffffffffffffffffffffffffffffffffffffffff166139d7612b4c565b73ffffffffffffffffffffffffffffffffffffffff1614613a36576139fa614722565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401613a2d9190614b7b565b60405180910390fd5b565b60025f5403613a73576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025f81905550565b5f808260800151613a9084606001516106cb565b613a9a91906150df565b90505f8360c00151613aaf8560a001516106cb565b613ab991906150df565b905080606483613ac991906150df565b613ad391906154dd565b92505050919050565b5f828211613ae8575f80fd5b5f612710603c80601861016d8888613b009190614f33565b8a8c613b0c91906150df565b613b1691906150df565b613b2091906154dd565b613b2a91906154dd565b613b3491906154dd565b613b3e91906154dd565b613b4891906154dd565b905080915050949350505050565b5f6127108284613b6691906150df565b613b7091906154dd565b905092915050565b5f818360800151613b899190615120565b60025f856060015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f85610140015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015905092915050565b5f6064600f546064613c279190614f33565b856060015173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015613c74573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613c989190614edb565b600a613ca4919061550d565b613cb187606001516106cb565b85613cbc91906150df565b613cc691906154dd565b613cd091906150df565b613cda91906154dd565b90505f613ce682614729565b90508015613dc3578160025f600e5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613db79190615120565b92505081905550613e77565b8260025f876060015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f60095f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613e6f9190615120565b925050819055505b5f8385613e849190614f33565b9050808660800151613e969190615120565b60025f886060015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f886040015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613f249190615120565b925050819055508115614090578260025f600e5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f88610140015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613fde9190614f33565b92505081905550808660800151613ff59190615120565b60025f886060015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f88610140015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546140849190614f33565b92505081905550614137565b8486608001516140a09190615120565b60025f886060015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f88610140015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461412f9190614f33565b925050819055505b8560c0015160025f8860a0015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f88610140015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546141cb9190615120565b925050819055507f9cdc815dd4fb4c3e808deb72539377b7ee6e0cd3f227c5b48db4ad03f0eb64bb865f015133886040015189606001518a608001518b61014001518c60a001518d60c001518e60e001518f61010001518b4260405161423c9c9b9a99989796959493929190615153565b60405180910390a1505050505050565b60015f81905550565b6142d1848573ffffffffffffffffffffffffffffffffffffffff166323b872dd86868660405160240161428a93929190615557565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061475f565b50505050565b5f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b614414838473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85856040516024016143cd92919061558c565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061475f565b505050565b60405180610180016040528060075481526020018a73ffffffffffffffffffffffffffffffffffffffff1681526020018973ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018781526020018573ffffffffffffffffffffffffffffffffffffffff1681526020018481526020018381526020018281526020015f81526020018673ffffffffffffffffffffffffffffffffffffffff1681526020014281525060035f60075481526020019081526020015f205f820151815f01556020820151816001015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506040820151816002015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506060820151816003015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506080820151816004015560a0820151816005015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061016082015181600b0155905050600a5460045f60075481526020019081526020015f20819055507f2fbbf22c6ebe94502147a9c148009f41c67fe0f03501a407e2e4f72d8236133d6007548a8a8a8a8a8a8a8a8a5f426040516146f89c9b9a999897969594939291906155ec565b60405180910390a160075f81548092919061471290615287565b9190505550505050505050505050565b5f33905090565b5f81614756600e5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16336137ca565b10159050919050565b5f614789828473ffffffffffffffffffffffffffffffffffffffff166147f490919063ffffffff16565b90505f8151141580156147ad5750808060200190518101906147ab91906156d9565b155b156147ef57826040517f5274afe70000000000000000000000000000000000000000000000000000000081526004016147e69190614b7b565b60405180910390fd5b505050565b606061480183835f614809565b905092915050565b60608147101561485057306040517fcd7860590000000000000000000000000000000000000000000000000000000081526004016148479190614b7b565b60405180910390fd5b5f808573ffffffffffffffffffffffffffffffffffffffff1684866040516148789190615770565b5f6040518083038185875af1925050503d805f81146148b2576040519150601f19603f3d011682016040523d82523d5f602084013e6148b7565b606091505b50915091506148c78683836148d2565b925050509392505050565b6060826148e7576148e28261495f565b614957565b5f825114801561490d57505f8473ffffffffffffffffffffffffffffffffffffffff163b145b1561494f57836040517f9996b3150000000000000000000000000000000000000000000000000000000081526004016149469190614b7b565b60405180910390fd5b819050614958565b5b9392505050565b5f815111156149715780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80fd5b5f819050919050565b6149b9816149a7565b81146149c3575f80fd5b50565b5f813590506149d4816149b0565b92915050565b5f602082840312156149ef576149ee6149a3565b5b5f6149fc848285016149c6565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f614a2e82614a05565b9050919050565b614a3e81614a24565b8114614a48575f80fd5b50565b5f81359050614a5981614a35565b92915050565b5f60208284031215614a7457614a736149a3565b5b5f614a8184828501614a4b565b91505092915050565b614a93816149a7565b82525050565b5f602082019050614aac5f830184614a8a565b92915050565b5f8060408385031215614ac857614ac76149a3565b5b5f614ad585828601614a4b565b9250506020614ae6858286016149c6565b9150509250929050565b5f8060408385031215614b0657614b056149a3565b5b5f614b1385828601614a4b565b9250506020614b2485828601614a4b565b9150509250929050565b5f8060408385031215614b4457614b436149a3565b5b5f614b51858286016149c6565b9250506020614b62858286016149c6565b9150509250929050565b614b7581614a24565b82525050565b5f602082019050614b8e5f830184614b6c565b92915050565b5f60c082019050614ba75f830189614a8a565b614bb46020830188614b6c565b614bc16040830187614b6c565b614bce6060830186614a8a565b614bdb6080830185614a8a565b614be860a0830184614a8a565b979650505050505050565b5f819050919050565b5f614c16614c11614c0c84614a05565b614bf3565b614a05565b9050919050565b5f614c2782614bfc565b9050919050565b5f614c3882614c1d565b9050919050565b614c4881614c2e565b82525050565b5f602082019050614c615f830184614c3f565b92915050565b5f805f805f8060c08789031215614c8157614c806149a3565b5b5f614c8e89828a01614a4b565b9650506020614c9f89828a016149c6565b9550506040614cb089828a01614a4b565b9450506060614cc189828a016149c6565b9350506080614cd289828a016149c6565b92505060a0614ce389828a016149c6565b9150509295509295509295565b5f61018082019050614d045f83018f614a8a565b614d11602083018e614b6c565b614d1e604083018d614b6c565b614d2b606083018c614b6c565b614d38608083018b614a8a565b614d4560a083018a614b6c565b614d5260c0830189614a8a565b614d5f60e0830188614a8a565b614d6d610100830187614a8a565b614d7b610120830186614a8a565b614d89610140830185614b6c565b614d97610160830184614a8a565b9d9c50505050505050505050505050565b5f69ffffffffffffffffffff82169050919050565b614dc681614da8565b8114614dd0575f80fd5b50565b5f81519050614de181614dbd565b92915050565b5f819050919050565b614df981614de7565b8114614e03575f80fd5b50565b5f81519050614e1481614df0565b92915050565b5f81519050614e28816149b0565b92915050565b5f805f805f60a08688031215614e4757614e466149a3565b5b5f614e5488828901614dd3565b9550506020614e6588828901614e06565b9450506040614e7688828901614e1a565b9350506060614e8788828901614e1a565b9250506080614e9888828901614dd3565b9150509295509295909350565b5f60ff82169050919050565b614eba81614ea5565b8114614ec4575f80fd5b50565b5f81519050614ed581614eb1565b92915050565b5f60208284031215614ef057614eef6149a3565b5b5f614efd84828501614ec7565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f614f3d826149a7565b9150614f48836149a7565b9250828203905081811115614f6057614f5f614f06565b5b92915050565b5f8160011c9050919050565b5f808291508390505b6001851115614fbb57808604811115614f9757614f96614f06565b5b6001851615614fa65780820291505b8081029050614fb485614f66565b9450614f7b565b94509492505050565b5f82614fd3576001905061508e565b81614fe0575f905061508e565b8160018114614ff657600281146150005761502f565b600191505061508e565b60ff84111561501257615011614f06565b5b8360020a91508482111561502957615028614f06565b5b5061508e565b5060208310610133831016604e8410600b84101617156150645782820a90508381111561505f5761505e614f06565b5b61508e565b6150718484846001614f72565b9250905081840481111561508857615087614f06565b5b81810290505b9392505050565b5f61509f826149a7565b91506150aa836149a7565b92506150d77fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484614fc4565b905092915050565b5f6150e9826149a7565b91506150f4836149a7565b9250828202615102816149a7565b9150828204841483151761511957615118614f06565b5b5092915050565b5f61512a826149a7565b9150615135836149a7565b925082820190508082111561514d5761514c614f06565b5b92915050565b5f610180820190506151675f83018f614a8a565b615174602083018e614b6c565b615181604083018d614b6c565b61518e606083018c614b6c565b61519b608083018b614a8a565b6151a860a083018a614b6c565b6151b560c0830189614b6c565b6151c260e0830188614a8a565b6151d0610100830187614a8a565b6151de610120830186614a8a565b6151ec610140830185614a8a565b6151fa610160830184614a8a565b9d9c50505050505050505050505050565b5f602082840312156152205761521f6149a3565b5b5f61522d84828501614e1a565b91505092915050565b5f60a0820190506152495f830188614a8a565b6152566020830187614b6c565b6152636040830186614b6c565b6152706060830185614a8a565b61527d6080830184614a8a565b9695505050505050565b5f615291826149a7565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036152c3576152c2614f06565b5b600182019050919050565b5f819050919050565b5f6152f16152ec6152e7846152ce565b614bf3565b6149a7565b9050919050565b615301816152d7565b82525050565b5f6101808201905061531b5f83018f614a8a565b615328602083018e614b6c565b615335604083018d614b6c565b615342606083018c614b6c565b61534f608083018b614a8a565b61535c60a083018a614b6c565b61536960c0830189614b6c565b61537660e0830188614a8a565b615384610100830187614a8a565b615392610120830186614a8a565b6153a06101408301856152f8565b6153ae610160830184614a8a565b9d9c50505050505050505050505050565b5f819050919050565b5f6153e26153dd6153d8846153bf565b614bf3565b6149a7565b9050919050565b6153f2816153c8565b82525050565b5f6101808201905061540c5f83018f614a8a565b615419602083018e614b6c565b615426604083018d614b6c565b615433606083018c614b6c565b615440608083018b614a8a565b61544d60a083018a614b6c565b61545a60c0830189614b6c565b61546760e0830188614a8a565b615475610100830187614a8a565b615483610120830186614a8a565b6154916101408301856153e9565b61549f610160830184614a8a565b9d9c50505050505050505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f6154e7826149a7565b91506154f2836149a7565b925082615502576155016154b0565b5b828204905092915050565b5f615517826149a7565b915061552283614ea5565b925061554f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484614fc4565b905092915050565b5f60608201905061556a5f830186614b6c565b6155776020830185614b6c565b6155846040830184614a8a565b949350505050565b5f60408201905061559f5f830185614b6c565b6155ac6020830184614a8a565b9392505050565b5f819050919050565b5f6155d66155d16155cc846155b3565b614bf3565b6149a7565b9050919050565b6155e6816155bc565b82525050565b5f610180820190506156005f83018f614a8a565b61560d602083018e614b6c565b61561a604083018d614b6c565b615627606083018c614b6c565b615634608083018b614a8a565b61564160a083018a614b6c565b61564e60c0830189614b6c565b61565b60e0830188614a8a565b615669610100830187614a8a565b615677610120830186614a8a565b6156856101408301856155dd565b615693610160830184614a8a565b9d9c50505050505050505050505050565b5f8115159050919050565b6156b8816156a4565b81146156c2575f80fd5b50565b5f815190506156d3816156af565b92915050565b5f602082840312156156ee576156ed6149a3565b5b5f6156fb848285016156c5565b91505092915050565b5f81519050919050565b5f81905092915050565b5f5b8381101561573557808201518184015260208101905061571a565b5f8484015250505050565b5f61574a82615704565b615754818561570e565b9350615764818560208601615718565b80840191505092915050565b5f61577b8284615740565b91508190509291505056fea2646970667358221220af5a0ae2c27b8386bed1a02ef36a5deff53347387a1556aadc32e8a208c2416c64736f6c63430008140033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000002726ffe32ad10b8264b9c44494d5f319caf92d76
-----Decoded View---------------
Arg [0] : initialOwner (address): 0x2726fFE32Ad10b8264b9C44494d5f319caf92D76
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000002726ffe32ad10b8264b9c44494d5f319caf92d76
Deployed Bytecode Sourcemap
46177:26983:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;72320:118;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;71023:548;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;68360:1846;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;66449:1903;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;52791:1446;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;72446:104;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;47526:61;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;70306:619;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;48555:25;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;62385:873;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;41778:103;;;:::i;:::-;;72826:167;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;48701:25;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;49392:38;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;60181:2196;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;41103:87;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;49274:30;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;73001:156;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;48043:45;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;48186:59;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;54411:938;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;48949:27;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;49137:50;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;59053:1120;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;48329:28;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;72694:124;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;47901:43;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;55492:1155;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;47671:37;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;48445:32;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;72130:182;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;72558:128;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;42036:220;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;48791:21;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;55357:127;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;56655:1138;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;72320:118;40989:13;:11;:13::i;:::-;72401:1:::1;72392:6;;:10;72384:19;;;::::0;::::1;;72423:7;72414:6;:16;;;;72320:118:::0;:::o;71023:548::-;71094:7;71115:14;71131:9;71144:17;71163:22;71189:10;:52;71214:16;71189:52;;;;;;;;;;;;;;;;;;;;;;;;;:68;;;:70;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;71114:145;;;;;;;;;71272:20;71295:10;:28;71306:16;71295:28;;;;;;;;;;;;;;;;;;;;;;;;;:37;;;:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;71272:62;;;;71398:1;71390:5;:9;:39;;;;;71422:7;71403:26;;:15;:26;;;;71390:39;:57;;;;;71446:1;71433:9;:14;;71390:57;71382:66;;;;;;71497:12;71492:2;:17;;;;:::i;:::-;71485:2;:25;;;;:::i;:::-;71476:5;71468:42;;;;:::i;:::-;71461:49;;;;;;;71023:548;;;:::o;68360:1846::-;45056:21;:19;:21::i;:::-;68465:18:::1;68486:5;:10;68492:3;68486:10;;;;;;;;;;;68465:31;;68614:10;68589:35;;68597:5;:12;;;;;;;;;;;;68589:35;;;68581:44;;;::::0;::::1;;68694:1;68675:5;:15;;;:20;68667:29;;;::::0;::::1;;68709:11;68723:19;68736:5;68723:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;:12;:19::i;:::-;68709:33;;68850:12;;68844:3;:18;68836:27;;;::::0;::::1;;68978:22;69003:160;69035:5;:24;;;69074:5;:18;;;69107:5;:15;;;69137;69003:17;:160::i;:::-;68978:185;;69176:11;69190:43;69203:14;69219:8;:13;69228:3;69219:13;;;;;;;;;;;;69190:12;:43::i;:::-;69176:57;;69309:55;69342:5;69309:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;69349:14;69309:32;:55::i;:::-;69305:862;;;69381:47;69401:5;69381:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;69408:14;69424:3;69381:19;:47::i;:::-;69305:862;;;69620:5;:27;;;69573:6;:29;69580:5;:21;;;;;;;;;;;;69573:29;;;;;;;;;;;;;;;:43;69603:5;:12;;;;;;;;;;;;69573:43;;;;;;;;;;;;;;;;:74;;;;;;;:::i;:::-;;;;;;;;69696:459;69726:5;:8;;;69753:10;69782:5;:12;;;;;;;;;;;;69813:5;:18;;;;;;;;;;;;69850:5;:24;;;69893:5;:14;;;;;;;;;;;;69926:5;:21;;;;;;;;;;;;69966:5;:27;;;70012:5;:18;;;70049:5;:18;;;70103:3;70086:14;:20;;;;:::i;:::-;70125:15;69696:459;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;69305:862;70197:1;70179:5;:15;;:19;;;;68431:1775;;;;45100:20:::0;:18;:20::i;:::-;68360:1846;:::o;66449:1903::-;45056:21;:19;:21::i;:::-;66551:18:::1;66572:5;:10;66578:3;66572:10;;;;;;;;;;;66551:31;;66700:10;66675:35;;66683:5;:12;;;;;;;;;;;;66675:35;;;66667:44;;;::::0;::::1;;66780:1;66761:5;:15;;;:20;66753:29;;;::::0;::::1;;66993:15;66974:16;;66953:5;:18;;;66935:5;:15;;;:36;;;;:::i;:::-;:55;;;;:::i;:::-;:73;66927:82;;;::::0;::::1;;67124:22;67149:160;67181:5;:24;;;67220:5;:18;;;67253:5;:15;;;67283;67149:17;:160::i;:::-;67124:185;;67322:11;67336:43;67349:14;67365:8;:13;67374:3;67365:13;;;;;;;;;;;;67336:12;:43::i;:::-;67322:57;;67455:55;67488:5;67455:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;67495:14;67455:32;:55::i;:::-;67451:862;;;67527:47;67547:5;67527:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;67554:14;67570:3;67527:19;:47::i;:::-;67451:862;;;67766:5;:27;;;67719:6;:29;67726:5;:21;;;;;;;;;;;;67719:29;;;;;;;;;;;;;;;:43;67749:5;:12;;;;;;;;;;;;67719:43;;;;;;;;;;;;;;;;:74;;;;;;;:::i;:::-;;;;;;;;67842:459;67872:5;:8;;;67899:10;67928:5;:12;;;;;;;;;;;;67959:5;:18;;;;;;;;;;;;67996:5;:24;;;68039:5;:14;;;;;;;;;;;;68072:5;:21;;;;;;;;;;;;68112:5;:27;;;68158:5;:18;;;68195:5;:18;;;68249:3;68232:14;:20;;;;:::i;:::-;68271:15;67842:459;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;67451:862;68343:1;68325:5;:15;;:19;;;;66517:1835;;;45100:20:::0;:18;:20::i;:::-;66449:1903;:::o;52791:1446::-;45056:21;:19;:21::i;:::-;52997:1:::1;52972:22;52987:6;52972:14;:22::i;:::-;:26;52964:35;;;::::0;::::1;;53077:1;53067:7;:11;53059:20;;;::::0;::::1;;53092:21;53123:6;53116:24;;;53149:4;53116:39;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;53092:63;;53206:282;53254:6;53334:10;53391:4;53438:7;53206:26;:282::i;:::-;53554:20;53584:6;53577:24;;;53610:4;53577:39;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;53554:62;;53627:19;53664:13;53649:12;:28;;;;:::i;:::-;53627:50;;53706:7;53692:11;:21;53688:75;;;53740:11;53730:21;;53688:75;53865:7;53836:6;:14;53843:6;53836:14;;;;;;;;;;;;;;;:26;53851:10;53836:26;;;;;;;;;;;;;;;;:36;;;;:::i;:::-;53807:6;:14;53814:6;53807:14;;;;;;;;;;;;;;;:26;53822:10;53807:26;;;;;;;;;;;;;;;:65;;;;53912:161;;;;;;;;53935:13;;53912:161;;;;53963:10;53912:161;;;;;;53988:6;53912:161;;;;;;54009:7;53912:161;;;;54031:1;53912:161;;;;54047:15;53912:161;;::::0;53885:9:::1;:24;53895:13;;53885:24;;;;;;;;;;;:188;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;54122:79;54130:13;;54145:6;54153:10;54165:7;54174:6;:14;54181:6;54174:14;;;;;;;;;;;;;;;:26;54189:10;54174:26;;;;;;;;;;;;;;;;54122:79;;;;;;;;;;:::i;:::-;;;;;;;;54214:13;;:15;;;;;;;;;:::i;:::-;;;;;;52866:1371;;;45100:20:::0;:18;:20::i;:::-;52791:1446;;:::o;72446:104::-;40989:13;:11;:13::i;:::-;72531:11:::1;72518:10;;:24;;;;;;;;;;;;;;;;;;72446:104:::0;:::o;47526:61::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;70306:619::-;45056:21;:19;:21::i;:::-;70418:18:::1;70439:5;:10;70445:3;70439:10;;;;;;;;;;;70418:31;;70571:10;70544:37;;70552:5;:14;;;;;;;;;;;;70544:37;;;70536:46;;;::::0;::::1;;70651:1;70632:5;:15;;;:20;70624:29;;;::::0;::::1;;70789:7;70744:6;:29;70751:5;:21;;;;;;;;;;;;70744:29;;;;;;;;;;;;;;;:41;70774:10;70744:41;;;;;;;;;;;;;;;;:52;;70736:61;;;::::0;::::1;;70859:7;70810:6;:29;70817:5;:21;;;;;;;;;;;;70810:29;;;;;;;;;;;;;;;:45;70840:5;:14;;;;;;;;;;;;70810:45;;;;;;;;;;;;;;;;:56;;;;;;;:::i;:::-;;;;;;;;70910:7;70879:5;:27;;;:38;;;;;;;:::i;:::-;;;;;;;;70384:541;45100:20:::0;:18;:20::i;:::-;70306:619;;:::o;48555:25::-;;;;;;;;;;;;;:::o;62385:873::-;45056:21;:19;:21::i;:::-;62473:18:::1;62494:5;:10;62500:3;62494:10;;;;;;;;;;;62473:31;;62623:10;62596:37;;62604:5;:14;;;;;;;;;;;;62596:37;;;62588:46;;;::::0;::::1;;62721:1;62702:5;:15;;;:20;62694:29;;;::::0;::::1;;62754:1;62736:5;:15;;:19;;;;62799:22;62824:160;62856:5;:24;;;62895:5;:18;;;62928:5;:15;;;62958;62824:17;:160::i;:::-;62799:185;;62997:11;63011:43;63024:14;63040:8;:13;63049:3;63040:13;;;;;;;;;;;;63011:12;:43::i;:::-;62997:57;;63134:55;63167:5;63134:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;63174:14;63134:32;:55::i;:::-;63126:64;;;::::0;::::1;;63203:47;63223:5;63203:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;63230:14;63246:3;63203:19;:47::i;:::-;62439:819;;;45100:20:::0;:18;:20::i;:::-;62385:873;:::o;41778:103::-;40989:13;:11;:13::i;:::-;41843:30:::1;41870:1;41843:18;:30::i;:::-;41778:103::o:0;72826:167::-;40989:13;:11;:13::i;:::-;72921:4:::1;72906:11;:19;;72898:28;;;::::0;::::1;;72974:11;72961:10;:24;;;;72826:167:::0;:::o;48701:25::-;;;;:::o;49392:38::-;;;;:::o;60181:2196::-;45056:21;:19;:21::i;:::-;60266:18:::1;60287:5;:10;60293:3;60287:10;;;;;;;;;;;60266:31;;60358:3;60346:5;:8;;;:15;60338:24;;;::::0;::::1;;60461:1;60442:5;:15;;;:20;60434:29;;;::::0;::::1;;60585:1;60559:28;;:5;:14;;;;;;;;;;;;:28;;::::0;60555:145:::1;;60660:5;:27;;;60612:44;60622:5;:21;;;;;;;;;;;;60645:10;60612:9;:44::i;:::-;:75;;60604:84;;;::::0;::::1;;60555:145;60834:1;60810:26;;:5;:12;;;;;;;;;;;;:26;;::::0;60806:137:::1;;60906:5;:24;;;60861:41;60871:5;:18;;;;;;;;;;;;60891:10;60861:9;:41::i;:::-;:69;;60853:78;;;::::0;::::1;;60806:137;60973:1;60955:5;:15;;:19;;;;61003:15;60985:5;:15;;:33;;;;61089:1;61063:28;;:5;:14;;;;;;;;;;;;:28;;::::0;61059:884:::1;;61316:5;:27;;;61271:6;:29;61278:5;:21;;;;;;;;;;;;61271:29;;;;;;;;;;;;;;;:41;61301:10;61271:41;;;;;;;;;;;;;;;;:72;;;;;;;:::i;:::-;;;;;;;;61454:5;:24;;;61412:6;:26;61419:5;:18;;;;;;;;;;;;61412:26;;;;;;;;;;;;;;;:38;61439:10;61412:38;;;;;;;;;;;;;;;;:66;;;;;;;:::i;:::-;;;;;;;;61512:10;61495:5;:14;;;:27;;;;;;;;;;;;;;;;;;61059:884;;;61568:1;61544:26;;:5;:12;;;;;;;;;;;;:26;;::::0;61540:403:::1;;61730:5;:24;;;61684:6;:26;61691:5;:18;;;;;;;;;;;;61684:26;;;;;;;;;;;;;;;:42;61711:5;:14;;;;;;;;;;;;61684:42;;;;;;;;;;;;;;;;:70;;;;;;;:::i;:::-;;;;;;;;61865:5;:24;;;61823:6;:26;61830:5;:18;;;;;;;;;;;;61823:26;;;;;;;;;;;;;;;:38;61850:10;61823:38;;;;;;;;;;;;;;;;:66;;;;;;;:::i;:::-;;;;;;;;61921:10;61906:5;:12;;;:25;;;;;;;;;;;;;;;;;;61540:403;61059:884;61983:386;62007:5;:8;;;62030:10;62055:5;:12;;;;;;;;;;;;62082:5;:18;;;;;;;;;;;;62115:5;:24;;;62154:5;:14;;;;;;;;;;;;62183:5;:21;;;;;;;;;;;;62219:5;:27;;;62261:5;:18;;;62294:5;:18;;;62327:1;62343:15;61983:386;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;60232:2145;45100:20:::0;:18;:20::i;:::-;60181:2196;:::o;41103:87::-;41149:7;41176:6;;;;;;;;;;;41169:13;;41103:87;:::o;49274:30::-;;;;;;;;;;;;;:::o;73001:156::-;40989:13;:11;:13::i;:::-;73125:24:::1;73099:23;:50;;;;73001:156:::0;:::o;48043:45::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;48186:59::-;;;;;;;;;;;;;;;;;;;;;;:::o;54411:938::-;45056:21;:19;:21::i;:::-;54592:7:::1;54562:6;:14;54569:6;54562:14;;;;;;;;;;;;;;;:26;54577:10;54562:26;;;;;;;;;;;;;;;;:37;;54554:46;;;::::0;::::1;;54649:223;54693:6;54773:10;54822:7;54649:22;:223::i;:::-;54975:7;54946:6;:14;54953:6;54946:14;;;;;;;;;;;;;;;:26;54961:10;54946:26;;;;;;;;;;;;;;;;:36;;;;:::i;:::-;54917:6;:14;54924:6;54917:14;;;;;;;;;;;;;;;:26;54932:10;54917:26;;;;;;;;;;;;;;;:65;;;;55022:161;;;;;;;;55045:13;;55022:161;;;;55073:10;55022:161;;;;;;55098:6;55022:161;;;;;;55119:7;55022:161;;;;55141:1;55022:161;;;;55157:15;55022:161;;::::0;54995:9:::1;:24;55005:13;;54995:24;;;;;;;;;;;:188;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;55233:80;55242:13;;55257:6;55265:10;55277:7;55286:6;:14;55293:6;55286:14;;;;;;;;;;;;;;;:26;55301:10;55286:26;;;;;;;;;;;;;;;;55233:80;;;;;;;;;;:::i;:::-;;;;;;;;55326:13;;:15;;;;;;;;;:::i;:::-;;;;;;45100:20:::0;:18;:20::i;:::-;54411:938;;:::o;48949:27::-;;;;:::o;49137:50::-;;;;:::o;59053:1120::-;45056:21;:19;:21::i;:::-;59140:18:::1;59161:5;:10;59167:3;59161:10;;;;;;;;;;;59140:31;;59286:10;59263:33;;59271:5;:10;;;;;;;;;;;;59263:33;;;59255:42;;;::::0;::::1;;59381:1;59362:5;:15;;;:20;59354:29;;;::::0;::::1;;59444:1;59426:5;:15;;:19;;;;59488:1;59462:28;;:5;:14;;;;;;;;;;;;:28;;::::0;59458:270:::1;;59551:5;:24;;;59507:6;:26;59514:5;:18;;;;;;;;;;;;59507:26;;;;;;;;;;;;;;;:40;59534:5;:12;;;;;;;;;;;;59507:40;;;;;;;;;;;;;;;;:68;;;;;;;:::i;:::-;;;;;;;;59458:270;;;59621:1;59597:26;;:5;:12;;;;;;;;;;;;:26;;::::0;59593:135:::1;;59689:5;:27;;;59640:6;:29;59647:5;:21;;;;;;;;;;;;59640:29;;;;;;;;;;;;;;;:45;59670:5;:14;;;;;;;;;;;;59640:45;;;;;;;;;;;;;;;;:76;;;;;;;:::i;:::-;;;;;;;;59593:135;59458:270;59768:397;59803:5;:8;;;59826:10;59851:5;:12;;;;;;;;;;;;59878:5;:18;;;;;;;;;;;;59911:5;:24;;;59950:5;:14;;;;;;;;;;;;59979:5;:21;;;;;;;;;;;;60015:5;:27;;;60057:5;:18;;;60090:5;:18;;;60123:1;60139:15;59768:397;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;59106:1067;45100:20:::0;:18;:20::i;:::-;59053:1120;:::o;48329:28::-;;;;:::o;72694:124::-;40989:13;:11;:13::i;:::-;72794:16:::1;72776:15;;:34;;;;;;;;;;;;;;;;;;72694:124:::0;:::o;47901:43::-;;;;;;;;;;;;;;;;;:::o;55492:1155::-;45056:21;:19;:21::i;:::-;55796:1:::1;55789:4;:8;:26;;;;;55809:6;;55801:4;:14;;55789:26;55781:35;;;::::0;::::1;;55852:1;55835:13;:18;;:44;;;;;55874:5;55857:13;:22;;55835:44;55827:53;;;::::0;::::1;;55960:1;55941:16;:20;55933:29;;;::::0;::::1;;55997:1;55981:13;:17;:41;;;;;56018:4;56002:13;:20;55981:41;55973:50;;;::::0;::::1;;56081:16;56044:33;56054:10;56066;56044:9;:33::i;:::-;:53;;56036:62;;;::::0;::::1;;56111:29;56232:32;56247:16;56232:14;:32::i;:::-;56212:4;56169:26;56184:10;56169:14;:26::i;:::-;56163:3;56144:16;:22;;;;:::i;:::-;:51;;;;:::i;:::-;56143:73;;;;:::i;:::-;:121;;;;:::i;:::-;56111:153;;56311:16;56277:6;:18;56284:10;56277:18;;;;;;;;;;;;;;;:30;56296:10;56277:30;;;;;;;;;;;;;;;;:50;;;;;;;:::i;:::-;;;;;;;;56340:299;56373:10;56414;56439;56464:16;56503:1;56520:16;56551:21;56587:13;56615;56340:18;:299::i;:::-;55770:877;45100:20:::0;:18;:20::i;:::-;55492:1155;;;;;;:::o;47671:37::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;48445:32::-;;;;:::o;72130:182::-;40989:13;:11;:13::i;:::-;72286:17:::1;72233:10;:28;72244:16;72233:28;;;;;;;;;;;;;;;;:71;;;;;;;;;;;;;;;;;;72130:182:::0;;:::o;72558:128::-;40989:13;:11;:13::i;:::-;72661:17:::1;72642:16;:36;;;;72558:128:::0;:::o;42036:220::-;40989:13;:11;:13::i;:::-;42141:1:::1;42121:22;;:8;:22;;::::0;42117:93:::1;;42195:1;42167:31;;;;;;;;;;;:::i;:::-;;;;;;;;42117:93;42220:28;42239:8;42220:18;:28::i;:::-;42036:220:::0;:::o;48791:21::-;;;;:::o;55357:127::-;55428:7;55455:6;:14;55462:6;55455:14;;;;;;;;;;;;;;;:21;55470:5;55455:21;;;;;;;;;;;;;;;;55448:28;;55357:127;;;;:::o;56655:1138::-;45056:21;:19;:21::i;:::-;56920:1:::1;56913:4;:8;:26;;;;;56933:6;;56925:4;:14;;56913:26;56905:35;;;::::0;::::1;;56976:1;56959:13;:18;;:44;;;;;56998:5;56981:13;:22;;56959:44;56951:53;;;::::0;::::1;;57084:1;57065:16;:20;57057:29;;;::::0;::::1;;57121:1;57105:13;:17;:41;;;;;57142:4;57126:13;:20;57105:41;57097:50;;;::::0;::::1;;57160:29;57281:32;57296:16;57281:14;:32::i;:::-;57261:4;57218:26;57233:10;57218:14;:26::i;:::-;57212:3;57193:16;:22;;;;:::i;:::-;:51;;;;:::i;:::-;57192:73;;;;:::i;:::-;:121;;;;:::i;:::-;57160:153;;57377:21;57334:39;57344:16;57362:10;57334:9;:39::i;:::-;:64;;57326:73;;;::::0;::::1;;57452:21;57412:6;:24;57419:16;57412:24;;;;;;;;;;;;;;;:36;57437:10;57412:36;;;;;;;;;;;;;;;;:61;;;;;;;:::i;:::-;;;;;;;;57486:299;57519:10;57568:1;57585:10;57610:16;57641:10;57666:16;57697:21;57733:13;57761;57486:18;:299::i;:::-;56894:899;45100:20:::0;:18;:20::i;:::-;56655:1138;;;;;;:::o;41268:166::-;41339:12;:10;:12::i;:::-;41328:23;;:7;:5;:7::i;:::-;:23;;;41324:103;;41402:12;:10;:12::i;:::-;41375:40;;;;;;;;;;;:::i;:::-;;;;;;;;41324:103;41268:166::o;45136:315::-;44434:1;45265:7;;:18;45261:88;;45307:30;;;;;;;;;;;;;;45261:88;44434:1;45426:7;:17;;;;45136:315::o;71712:410::-;71776:7;71796:30;71880:5;:24;;;71830:34;71845:5;:18;;;71830:14;:34::i;:::-;:74;;;;:::i;:::-;71796:109;;71918:33;72008:5;:27;;;71955:37;71970:5;:21;;;71955:14;:37::i;:::-;:80;;;;:::i;:::-;71918:118;;72089:25;72082:3;72057:22;:28;;;;:::i;:::-;72056:58;;;;:::i;:::-;72049:65;;;;71712:410;;;:::o;65698:545::-;65881:7;65980:10;65969:8;:21;65961:30;;;;;;66002:22;66195:5;66177:2;66159;66141;66122:3;66094:10;66083:8;:21;;;;:::i;:::-;66052:13;66030:19;:35;;;;:::i;:::-;66029:76;;;;:::i;:::-;66028:97;;;;:::i;:::-;:115;;;;:::i;:::-;:133;;;;:::i;:::-;:151;;;;:::i;:::-;:172;;;;:::i;:::-;66002:199;;66221:14;66214:21;;;65698:545;;;;;;:::o;66251:190::-;66367:7;66428:5;66413:11;66395:15;:29;;;;:::i;:::-;66394:39;;;;:::i;:::-;66387:46;;66251:190;;;;:::o;65237:280::-;65371:4;65494:15;65467:5;:24;;;:42;;;;:::i;:::-;65408:6;:26;65415:5;:18;;;65408:26;;;;;;;;;;;;;;;:42;65435:5;:14;;;65408:42;;;;;;;;;;;;;;;;:101;;65388:121;;65237:280;;;;:::o;63266:1963::-;63372:16;63550:3;63509:23;;63503:3;:29;;;;:::i;:::-;63466:5;:18;;;63460:34;;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;63453:2;:44;;;;:::i;:::-;63401:34;63416:5;:18;;;63401:14;:34::i;:::-;63394:4;:41;;;;:::i;:::-;63393:105;;;;:::i;:::-;63392:141;;;;:::i;:::-;63391:162;;;;:::i;:::-;63372:181;;63604:27;63634:40;63665:8;63634:30;:40::i;:::-;63604:70;;63691:22;63687:181;;;63769:8;63730:6;:23;63737:15;;;;;;;;;;;63730:23;;;;;;;;;;;;;;;:35;63754:10;;;;;;;;;;;63730:35;;;;;;;;;;;;;;;;:47;;;;;;;:::i;:::-;;;;;;;;63687:181;;;63852:4;63810:6;:26;63817:5;:18;;;63810:26;;;;;;;;;;;;;;;:38;63837:10;;;;;;;;;;;63810:38;;;;;;;;;;;;;;;;:46;;;;;;;:::i;:::-;;;;;;;;63687:181;63880:30;63931:4;63913:15;:22;;;;:::i;:::-;63880:55;;64090:22;64050:5;:24;;;:62;;;;:::i;:::-;63993:6;:26;64000:5;:18;;;63993:26;;;;;;;;;;;;;;;:40;64020:5;:12;;;63993:40;;;;;;;;;;;;;;;;:119;;;;;;;:::i;:::-;;;;;;;;64129:22;64125:527;;;64211:8;64168:6;:23;64175:15;;;;;;;;;;;64168:23;;;;;;;;;;;;;;;:39;64192:5;:14;;;64168:39;;;;;;;;;;;;;;;;:51;;;;;;;:::i;:::-;;;;;;;;64401:22;64357:5;:24;;;:66;;;;:::i;:::-;64310:6;:26;64317:5;:18;;;64310:26;;;;;;;;;;;;;;;:42;64337:5;:14;;;64310:42;;;;;;;;;;;;;;;;:114;;;;;;;:::i;:::-;;;;;;;;64125:527;;;64624:15;64580:5;:24;;;:59;;;;:::i;:::-;64533:6;:26;64540:5;:18;;;64533:26;;;;;;;;;;;;;;;:42;64560:5;:14;;;64533:42;;;;;;;;;;;;;;;;:107;;;;;;;:::i;:::-;;;;;;;;64125:527;64744:5;:27;;;64695:6;:29;64702:5;:21;;;64695:29;;;;;;;;;;;;;;;:45;64725:5;:14;;;64695:45;;;;;;;;;;;;;;;;:76;;;;;;;:::i;:::-;;;;;;;;64812:409;64838:5;:8;;;64861:10;64886:5;:12;;;64913:5;:18;;;64946:5;:24;;;64985:5;:14;;;65014:5;:21;;;65050:5;:27;;;65092:5;:18;;;65125:5;:18;;;65158:22;65195:15;64812:409;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;63361:1868;;;63266:1963;;;:::o;45459:212::-;44391:1;45642:7;:21;;;;45459:212::o;22355:190::-;22456:81;22476:5;22498;:18;;;22519:4;22525:2;22529:5;22483:53;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22456:19;:81::i;:::-;22355:190;;;;:::o;42416:191::-;42490:16;42509:6;;;;;;;;;;;42490:25;;42535:8;42526:6;;:17;;;;;;;;;;;;;;;;;;42590:8;42559:40;;42580:8;42559:40;;;;;;;;;;;;42479:128;42416:191;:::o;21948:162::-;22031:71;22051:5;22073;:14;;;22090:2;22094:5;22058:43;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22031:19;:71::i;:::-;21948:162;;;:::o;57801:1244::-;58225:337;;;;;;;;58244:9;;58225:337;;;;58268:5;58225:337;;;;;;58288:7;58225:337;;;;;;58310:13;58225:337;;;;;;58338:19;58225:337;;;;58372:16;58225:337;;;;;;58403:22;58225:337;;;;58440:13;58225:337;;;;58468:13;58225:337;;;;58496:1;58225:337;;;;58512:9;58225:337;;;;;;58536:15;58225:337;;;58206:5;:16;58212:9;;58206:16;;;;;;;;;;;:356;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;58597:10;;58575:8;:19;58584:9;;58575:19;;;;;;;;;;;:32;;;;58646:367;58679:9;;58703:5;58739:7;58761:13;58789:19;58823:9;58847:16;58878:22;58915:13;58943;58971:1;58987:15;58646:367;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;59026:9;;:11;;;;;;;;;:::i;:::-;;;;;;57801:1244;;;;;;;;;:::o;27945:98::-;27998:7;28025:10;28018:17;;27945:98;:::o;65525:165::-;65607:4;65673:9;65631:38;65641:15;;;;;;;;;;;65658:10;65631:9;:38::i;:::-;:51;;65624:58;;65525:165;;;:::o;24759:638::-;25183:23;25209:33;25237:4;25217:5;25209:27;;;;:33;;;;:::i;:::-;25183:59;;25278:1;25257:10;:17;:22;;:57;;;;;25295:10;25284:30;;;;;;;;;;;;:::i;:::-;25283:31;25257:57;25253:137;;;25371:5;25338:40;;;;;;;;;;;:::i;:::-;;;;;;;;25253:137;24829:568;24759:638;;:::o;9527:153::-;9602:12;9634:38;9656:6;9664:4;9670:1;9634:21;:38::i;:::-;9627:45;;9527:153;;;;:::o;10015:398::-;10114:12;10167:5;10143:21;:29;10139:110;;;10231:4;10196:41;;;;;;;;;;;:::i;:::-;;;;;;;;10139:110;10260:12;10274:23;10301:6;:11;;10320:5;10327:4;10301:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10259:73;;;;10350:55;10377:6;10385:7;10394:10;10350:26;:55::i;:::-;10343:62;;;;10015:398;;;;;:::o;11491:597::-;11639:12;11669:7;11664:417;;11693:19;11701:10;11693:7;:19::i;:::-;11664:417;;;11942:1;11921:10;:17;:22;:49;;;;;11969:1;11947:6;:18;;;:23;11921:49;11917:121;;;12015:6;11998:24;;;;;;;;;;;:::i;:::-;;;;;;;;11917:121;12059:10;12052:17;;;;11664:417;11491:597;;;;;;:::o;12641:528::-;12794:1;12774:10;:17;:21;12770:392;;;13006:10;13000:17;13063:15;13050:10;13046:2;13042:19;13035:44;12770:392;13133:17;;;;;;;;;;;;;;88:117:1;197:1;194;187:12;334:77;371:7;400:5;389:16;;334:77;;;:::o;417:122::-;490:24;508:5;490:24;:::i;:::-;483:5;480:35;470:63;;529:1;526;519:12;470:63;417:122;:::o;545:139::-;591:5;629:6;616:20;607:29;;645:33;672:5;645:33;:::i;:::-;545:139;;;;:::o;690:329::-;749:6;798:2;786:9;777:7;773:23;769:32;766:119;;;804:79;;:::i;:::-;766:119;924:1;949:53;994:7;985:6;974:9;970:22;949:53;:::i;:::-;939:63;;895:117;690:329;;;;:::o;1025:126::-;1062:7;1102:42;1095:5;1091:54;1080:65;;1025:126;;;:::o;1157:96::-;1194:7;1223:24;1241:5;1223:24;:::i;:::-;1212:35;;1157:96;;;:::o;1259:122::-;1332:24;1350:5;1332:24;:::i;:::-;1325:5;1322:35;1312:63;;1371:1;1368;1361:12;1312:63;1259:122;:::o;1387:139::-;1433:5;1471:6;1458:20;1449:29;;1487:33;1514:5;1487:33;:::i;:::-;1387:139;;;;:::o;1532:329::-;1591:6;1640:2;1628:9;1619:7;1615:23;1611:32;1608:119;;;1646:79;;:::i;:::-;1608:119;1766:1;1791:53;1836:7;1827:6;1816:9;1812:22;1791:53;:::i;:::-;1781:63;;1737:117;1532:329;;;;:::o;1867:118::-;1954:24;1972:5;1954:24;:::i;:::-;1949:3;1942:37;1867:118;;:::o;1991:222::-;2084:4;2122:2;2111:9;2107:18;2099:26;;2135:71;2203:1;2192:9;2188:17;2179:6;2135:71;:::i;:::-;1991:222;;;;:::o;2219:474::-;2287:6;2295;2344:2;2332:9;2323:7;2319:23;2315:32;2312:119;;;2350:79;;:::i;:::-;2312:119;2470:1;2495:53;2540:7;2531:6;2520:9;2516:22;2495:53;:::i;:::-;2485:63;;2441:117;2597:2;2623:53;2668:7;2659:6;2648:9;2644:22;2623:53;:::i;:::-;2613:63;;2568:118;2219:474;;;;;:::o;2699:::-;2767:6;2775;2824:2;2812:9;2803:7;2799:23;2795:32;2792:119;;;2830:79;;:::i;:::-;2792:119;2950:1;2975:53;3020:7;3011:6;3000:9;2996:22;2975:53;:::i;:::-;2965:63;;2921:117;3077:2;3103:53;3148:7;3139:6;3128:9;3124:22;3103:53;:::i;:::-;3093:63;;3048:118;2699:474;;;;;:::o;3179:::-;3247:6;3255;3304:2;3292:9;3283:7;3279:23;3275:32;3272:119;;;3310:79;;:::i;:::-;3272:119;3430:1;3455:53;3500:7;3491:6;3480:9;3476:22;3455:53;:::i;:::-;3445:63;;3401:117;3557:2;3583:53;3628:7;3619:6;3608:9;3604:22;3583:53;:::i;:::-;3573:63;;3528:118;3179:474;;;;;:::o;3659:118::-;3746:24;3764:5;3746:24;:::i;:::-;3741:3;3734:37;3659:118;;:::o;3783:222::-;3876:4;3914:2;3903:9;3899:18;3891:26;;3927:71;3995:1;3984:9;3980:17;3971:6;3927:71;:::i;:::-;3783:222;;;;:::o;4011:775::-;4244:4;4282:3;4271:9;4267:19;4259:27;;4296:71;4364:1;4353:9;4349:17;4340:6;4296:71;:::i;:::-;4377:72;4445:2;4434:9;4430:18;4421:6;4377:72;:::i;:::-;4459;4527:2;4516:9;4512:18;4503:6;4459:72;:::i;:::-;4541;4609:2;4598:9;4594:18;4585:6;4541:72;:::i;:::-;4623:73;4691:3;4680:9;4676:19;4667:6;4623:73;:::i;:::-;4706;4774:3;4763:9;4759:19;4750:6;4706:73;:::i;:::-;4011:775;;;;;;;;;:::o;4792:60::-;4820:3;4841:5;4834:12;;4792:60;;;:::o;4858:142::-;4908:9;4941:53;4959:34;4968:24;4986:5;4968:24;:::i;:::-;4959:34;:::i;:::-;4941:53;:::i;:::-;4928:66;;4858:142;;;:::o;5006:126::-;5056:9;5089:37;5120:5;5089:37;:::i;:::-;5076:50;;5006:126;;;:::o;5138:155::-;5217:9;5250:37;5281:5;5250:37;:::i;:::-;5237:50;;5138:155;;;:::o;5299:189::-;5415:66;5475:5;5415:66;:::i;:::-;5410:3;5403:79;5299:189;;:::o;5494:280::-;5616:4;5654:2;5643:9;5639:18;5631:26;;5667:100;5764:1;5753:9;5749:17;5740:6;5667:100;:::i;:::-;5494:280;;;;:::o;5780:1057::-;5884:6;5892;5900;5908;5916;5924;5973:3;5961:9;5952:7;5948:23;5944:33;5941:120;;;5980:79;;:::i;:::-;5941:120;6100:1;6125:53;6170:7;6161:6;6150:9;6146:22;6125:53;:::i;:::-;6115:63;;6071:117;6227:2;6253:53;6298:7;6289:6;6278:9;6274:22;6253:53;:::i;:::-;6243:63;;6198:118;6355:2;6381:53;6426:7;6417:6;6406:9;6402:22;6381:53;:::i;:::-;6371:63;;6326:118;6483:2;6509:53;6554:7;6545:6;6534:9;6530:22;6509:53;:::i;:::-;6499:63;;6454:118;6611:3;6638:53;6683:7;6674:6;6663:9;6659:22;6638:53;:::i;:::-;6628:63;;6582:119;6740:3;6767:53;6812:7;6803:6;6792:9;6788:22;6767:53;:::i;:::-;6757:63;;6711:119;5780:1057;;;;;;;;:::o;6843:1445::-;7246:4;7284:3;7273:9;7269:19;7261:27;;7298:71;7366:1;7355:9;7351:17;7342:6;7298:71;:::i;:::-;7379:72;7447:2;7436:9;7432:18;7423:6;7379:72;:::i;:::-;7461;7529:2;7518:9;7514:18;7505:6;7461:72;:::i;:::-;7543;7611:2;7600:9;7596:18;7587:6;7543:72;:::i;:::-;7625:73;7693:3;7682:9;7678:19;7669:6;7625:73;:::i;:::-;7708;7776:3;7765:9;7761:19;7752:6;7708:73;:::i;:::-;7791;7859:3;7848:9;7844:19;7835:6;7791:73;:::i;:::-;7874;7942:3;7931:9;7927:19;7918:6;7874:73;:::i;:::-;7957;8025:3;8014:9;8010:19;8001:6;7957:73;:::i;:::-;8040;8108:3;8097:9;8093:19;8084:6;8040:73;:::i;:::-;8123:74;8192:3;8181:9;8177:19;8167:7;8123:74;:::i;:::-;8207;8276:3;8265:9;8261:19;8251:7;8207:74;:::i;:::-;6843:1445;;;;;;;;;;;;;;;:::o;8294:105::-;8330:7;8370:22;8363:5;8359:34;8348:45;;8294:105;;;:::o;8405:120::-;8477:23;8494:5;8477:23;:::i;:::-;8470:5;8467:34;8457:62;;8515:1;8512;8505:12;8457:62;8405:120;:::o;8531:141::-;8587:5;8618:6;8612:13;8603:22;;8634:32;8660:5;8634:32;:::i;:::-;8531:141;;;;:::o;8678:76::-;8714:7;8743:5;8732:16;;8678:76;;;:::o;8760:120::-;8832:23;8849:5;8832:23;:::i;:::-;8825:5;8822:34;8812:62;;8870:1;8867;8860:12;8812:62;8760:120;:::o;8886:141::-;8942:5;8973:6;8967:13;8958:22;;8989:32;9015:5;8989:32;:::i;:::-;8886:141;;;;:::o;9033:143::-;9090:5;9121:6;9115:13;9106:22;;9137:33;9164:5;9137:33;:::i;:::-;9033:143;;;;:::o;9182:971::-;9285:6;9293;9301;9309;9317;9366:3;9354:9;9345:7;9341:23;9337:33;9334:120;;;9373:79;;:::i;:::-;9334:120;9493:1;9518:63;9573:7;9564:6;9553:9;9549:22;9518:63;:::i;:::-;9508:73;;9464:127;9630:2;9656:63;9711:7;9702:6;9691:9;9687:22;9656:63;:::i;:::-;9646:73;;9601:128;9768:2;9794:64;9850:7;9841:6;9830:9;9826:22;9794:64;:::i;:::-;9784:74;;9739:129;9907:2;9933:64;9989:7;9980:6;9969:9;9965:22;9933:64;:::i;:::-;9923:74;;9878:129;10046:3;10073:63;10128:7;10119:6;10108:9;10104:22;10073:63;:::i;:::-;10063:73;;10017:129;9182:971;;;;;;;;:::o;10159:86::-;10194:7;10234:4;10227:5;10223:16;10212:27;;10159:86;;;:::o;10251:118::-;10322:22;10338:5;10322:22;:::i;:::-;10315:5;10312:33;10302:61;;10359:1;10356;10349:12;10302:61;10251:118;:::o;10375:139::-;10430:5;10461:6;10455:13;10446:22;;10477:31;10502:5;10477:31;:::i;:::-;10375:139;;;;:::o;10520:347::-;10588:6;10637:2;10625:9;10616:7;10612:23;10608:32;10605:119;;;10643:79;;:::i;:::-;10605:119;10763:1;10788:62;10842:7;10833:6;10822:9;10818:22;10788:62;:::i;:::-;10778:72;;10734:126;10520:347;;;;:::o;10873:180::-;10921:77;10918:1;10911:88;11018:4;11015:1;11008:15;11042:4;11039:1;11032:15;11059:194;11099:4;11119:20;11137:1;11119:20;:::i;:::-;11114:25;;11153:20;11171:1;11153:20;:::i;:::-;11148:25;;11197:1;11194;11190:9;11182:17;;11221:1;11215:4;11212:11;11209:37;;;11226:18;;:::i;:::-;11209:37;11059:194;;;;:::o;11259:102::-;11301:8;11348:5;11345:1;11341:13;11320:34;;11259:102;;;:::o;11367:848::-;11428:5;11435:4;11459:6;11450:15;;11483:5;11474:14;;11497:712;11518:1;11508:8;11505:15;11497:712;;;11613:4;11608:3;11604:14;11598:4;11595:24;11592:50;;;11622:18;;:::i;:::-;11592:50;11672:1;11662:8;11658:16;11655:451;;;12087:4;12080:5;12076:16;12067:25;;11655:451;12137:4;12131;12127:15;12119:23;;12167:32;12190:8;12167:32;:::i;:::-;12155:44;;11497:712;;;11367:848;;;;;;;:::o;12221:1073::-;12275:5;12466:8;12456:40;;12487:1;12478:10;;12489:5;;12456:40;12515:4;12505:36;;12532:1;12523:10;;12534:5;;12505:36;12601:4;12649:1;12644:27;;;;12685:1;12680:191;;;;12594:277;;12644:27;12662:1;12653:10;;12664:5;;;12680:191;12725:3;12715:8;12712:17;12709:43;;;12732:18;;:::i;:::-;12709:43;12781:8;12778:1;12774:16;12765:25;;12816:3;12809:5;12806:14;12803:40;;;12823:18;;:::i;:::-;12803:40;12856:5;;;12594:277;;12980:2;12970:8;12967:16;12961:3;12955:4;12952:13;12948:36;12930:2;12920:8;12917:16;12912:2;12906:4;12903:12;12899:35;12883:111;12880:246;;;13036:8;13030:4;13026:19;13017:28;;13071:3;13064:5;13061:14;13058:40;;;13078:18;;:::i;:::-;13058:40;13111:5;;12880:246;13151:42;13189:3;13179:8;13173:4;13170:1;13151:42;:::i;:::-;13136:57;;;;13225:4;13220:3;13216:14;13209:5;13206:25;13203:51;;;13234:18;;:::i;:::-;13203:51;13283:4;13276:5;13272:16;13263:25;;12221:1073;;;;;;:::o;13300:285::-;13360:5;13384:23;13402:4;13384:23;:::i;:::-;13376:31;;13428:27;13446:8;13428:27;:::i;:::-;13416:39;;13474:104;13511:66;13501:8;13495:4;13474:104;:::i;:::-;13465:113;;13300:285;;;;:::o;13591:410::-;13631:7;13654:20;13672:1;13654:20;:::i;:::-;13649:25;;13688:20;13706:1;13688:20;:::i;:::-;13683:25;;13743:1;13740;13736:9;13765:30;13783:11;13765:30;:::i;:::-;13754:41;;13944:1;13935:7;13931:15;13928:1;13925:22;13905:1;13898:9;13878:83;13855:139;;13974:18;;:::i;:::-;13855:139;13639:362;13591:410;;;;:::o;14007:191::-;14047:3;14066:20;14084:1;14066:20;:::i;:::-;14061:25;;14100:20;14118:1;14100:20;:::i;:::-;14095:25;;14143:1;14140;14136:9;14129:16;;14164:3;14161:1;14158:10;14155:36;;;14171:18;;:::i;:::-;14155:36;14007:191;;;;:::o;14204:1445::-;14607:4;14645:3;14634:9;14630:19;14622:27;;14659:71;14727:1;14716:9;14712:17;14703:6;14659:71;:::i;:::-;14740:72;14808:2;14797:9;14793:18;14784:6;14740:72;:::i;:::-;14822;14890:2;14879:9;14875:18;14866:6;14822:72;:::i;:::-;14904;14972:2;14961:9;14957:18;14948:6;14904:72;:::i;:::-;14986:73;15054:3;15043:9;15039:19;15030:6;14986:73;:::i;:::-;15069;15137:3;15126:9;15122:19;15113:6;15069:73;:::i;:::-;15152;15220:3;15209:9;15205:19;15196:6;15152:73;:::i;:::-;15235;15303:3;15292:9;15288:19;15279:6;15235:73;:::i;:::-;15318;15386:3;15375:9;15371:19;15362:6;15318:73;:::i;:::-;15401;15469:3;15458:9;15454:19;15445:6;15401:73;:::i;:::-;15484:74;15553:3;15542:9;15538:19;15528:7;15484:74;:::i;:::-;15568;15637:3;15626:9;15622:19;15612:7;15568:74;:::i;:::-;14204:1445;;;;;;;;;;;;;;;:::o;15655:351::-;15725:6;15774:2;15762:9;15753:7;15749:23;15745:32;15742:119;;;15780:79;;:::i;:::-;15742:119;15900:1;15925:64;15981:7;15972:6;15961:9;15957:22;15925:64;:::i;:::-;15915:74;;15871:128;15655:351;;;;:::o;16012:664::-;16217:4;16255:3;16244:9;16240:19;16232:27;;16269:71;16337:1;16326:9;16322:17;16313:6;16269:71;:::i;:::-;16350:72;16418:2;16407:9;16403:18;16394:6;16350:72;:::i;:::-;16432;16500:2;16489:9;16485:18;16476:6;16432:72;:::i;:::-;16514;16582:2;16571:9;16567:18;16558:6;16514:72;:::i;:::-;16596:73;16664:3;16653:9;16649:19;16640:6;16596:73;:::i;:::-;16012:664;;;;;;;;:::o;16682:233::-;16721:3;16744:24;16762:5;16744:24;:::i;:::-;16735:33;;16790:66;16783:5;16780:77;16777:103;;16860:18;;:::i;:::-;16777:103;16907:1;16900:5;16896:13;16889:20;;16682:233;;;:::o;16921:85::-;16966:7;16995:5;16984:16;;16921:85;;;:::o;17012:158::-;17070:9;17103:61;17121:42;17130:32;17156:5;17130:32;:::i;:::-;17121:42;:::i;:::-;17103:61;:::i;:::-;17090:74;;17012:158;;;:::o;17176:147::-;17271:45;17310:5;17271:45;:::i;:::-;17266:3;17259:58;17176:147;;:::o;17329:1461::-;17740:4;17778:3;17767:9;17763:19;17755:27;;17792:71;17860:1;17849:9;17845:17;17836:6;17792:71;:::i;:::-;17873:72;17941:2;17930:9;17926:18;17917:6;17873:72;:::i;:::-;17955;18023:2;18012:9;18008:18;17999:6;17955:72;:::i;:::-;18037;18105:2;18094:9;18090:18;18081:6;18037:72;:::i;:::-;18119:73;18187:3;18176:9;18172:19;18163:6;18119:73;:::i;:::-;18202;18270:3;18259:9;18255:19;18246:6;18202:73;:::i;:::-;18285;18353:3;18342:9;18338:19;18329:6;18285:73;:::i;:::-;18368;18436:3;18425:9;18421:19;18412:6;18368:73;:::i;:::-;18451;18519:3;18508:9;18504:19;18495:6;18451:73;:::i;:::-;18534;18602:3;18591:9;18587:19;18578:6;18534:73;:::i;:::-;18617:82;18694:3;18683:9;18679:19;18669:7;18617:82;:::i;:::-;18709:74;18778:3;18767:9;18763:19;18753:7;18709:74;:::i;:::-;17329:1461;;;;;;;;;;;;;;;:::o;18796:85::-;18841:7;18870:5;18859:16;;18796:85;;;:::o;18887:158::-;18945:9;18978:61;18996:42;19005:32;19031:5;19005:32;:::i;:::-;18996:42;:::i;:::-;18978:61;:::i;:::-;18965:74;;18887:158;;;:::o;19051:147::-;19146:45;19185:5;19146:45;:::i;:::-;19141:3;19134:58;19051:147;;:::o;19204:1461::-;19615:4;19653:3;19642:9;19638:19;19630:27;;19667:71;19735:1;19724:9;19720:17;19711:6;19667:71;:::i;:::-;19748:72;19816:2;19805:9;19801:18;19792:6;19748:72;:::i;:::-;19830;19898:2;19887:9;19883:18;19874:6;19830:72;:::i;:::-;19912;19980:2;19969:9;19965:18;19956:6;19912:72;:::i;:::-;19994:73;20062:3;20051:9;20047:19;20038:6;19994:73;:::i;:::-;20077;20145:3;20134:9;20130:19;20121:6;20077:73;:::i;:::-;20160;20228:3;20217:9;20213:19;20204:6;20160:73;:::i;:::-;20243;20311:3;20300:9;20296:19;20287:6;20243:73;:::i;:::-;20326;20394:3;20383:9;20379:19;20370:6;20326:73;:::i;:::-;20409;20477:3;20466:9;20462:19;20453:6;20409:73;:::i;:::-;20492:82;20569:3;20558:9;20554:19;20544:7;20492:82;:::i;:::-;20584:74;20653:3;20642:9;20638:19;20628:7;20584:74;:::i;:::-;19204:1461;;;;;;;;;;;;;;;:::o;20671:180::-;20719:77;20716:1;20709:88;20816:4;20813:1;20806:15;20840:4;20837:1;20830:15;20857:185;20897:1;20914:20;20932:1;20914:20;:::i;:::-;20909:25;;20948:20;20966:1;20948:20;:::i;:::-;20943:25;;20987:1;20977:35;;20992:18;;:::i;:::-;20977:35;21034:1;21031;21027:9;21022:14;;20857:185;;;;:::o;21048:281::-;21106:5;21130:23;21148:4;21130:23;:::i;:::-;21122:31;;21174:25;21190:8;21174:25;:::i;:::-;21162:37;;21218:104;21255:66;21245:8;21239:4;21218:104;:::i;:::-;21209:113;;21048:281;;;;:::o;21335:442::-;21484:4;21522:2;21511:9;21507:18;21499:26;;21535:71;21603:1;21592:9;21588:17;21579:6;21535:71;:::i;:::-;21616:72;21684:2;21673:9;21669:18;21660:6;21616:72;:::i;:::-;21698;21766:2;21755:9;21751:18;21742:6;21698:72;:::i;:::-;21335:442;;;;;;:::o;21783:332::-;21904:4;21942:2;21931:9;21927:18;21919:26;;21955:71;22023:1;22012:9;22008:17;21999:6;21955:71;:::i;:::-;22036:72;22104:2;22093:9;22089:18;22080:6;22036:72;:::i;:::-;21783:332;;;;;:::o;22121:85::-;22166:7;22195:5;22184:16;;22121:85;;;:::o;22212:158::-;22270:9;22303:61;22321:42;22330:32;22356:5;22330:32;:::i;:::-;22321:42;:::i;:::-;22303:61;:::i;:::-;22290:74;;22212:158;;;:::o;22376:147::-;22471:45;22510:5;22471:45;:::i;:::-;22466:3;22459:58;22376:147;;:::o;22529:1461::-;22940:4;22978:3;22967:9;22963:19;22955:27;;22992:71;23060:1;23049:9;23045:17;23036:6;22992:71;:::i;:::-;23073:72;23141:2;23130:9;23126:18;23117:6;23073:72;:::i;:::-;23155;23223:2;23212:9;23208:18;23199:6;23155:72;:::i;:::-;23237;23305:2;23294:9;23290:18;23281:6;23237:72;:::i;:::-;23319:73;23387:3;23376:9;23372:19;23363:6;23319:73;:::i;:::-;23402;23470:3;23459:9;23455:19;23446:6;23402:73;:::i;:::-;23485;23553:3;23542:9;23538:19;23529:6;23485:73;:::i;:::-;23568;23636:3;23625:9;23621:19;23612:6;23568:73;:::i;:::-;23651;23719:3;23708:9;23704:19;23695:6;23651:73;:::i;:::-;23734;23802:3;23791:9;23787:19;23778:6;23734:73;:::i;:::-;23817:82;23894:3;23883:9;23879:19;23869:7;23817:82;:::i;:::-;23909:74;23978:3;23967:9;23963:19;23953:7;23909:74;:::i;:::-;22529:1461;;;;;;;;;;;;;;;:::o;23996:90::-;24030:7;24073:5;24066:13;24059:21;24048:32;;23996:90;;;:::o;24092:116::-;24162:21;24177:5;24162:21;:::i;:::-;24155:5;24152:32;24142:60;;24198:1;24195;24188:12;24142:60;24092:116;:::o;24214:137::-;24268:5;24299:6;24293:13;24284:22;;24315:30;24339:5;24315:30;:::i;:::-;24214:137;;;;:::o;24357:345::-;24424:6;24473:2;24461:9;24452:7;24448:23;24444:32;24441:119;;;24479:79;;:::i;:::-;24441:119;24599:1;24624:61;24677:7;24668:6;24657:9;24653:22;24624:61;:::i;:::-;24614:71;;24570:125;24357:345;;;;:::o;24708:98::-;24759:6;24793:5;24787:12;24777:22;;24708:98;;;:::o;24812:147::-;24913:11;24950:3;24935:18;;24812:147;;;;:::o;24965:246::-;25046:1;25056:113;25070:6;25067:1;25064:13;25056:113;;;25155:1;25150:3;25146:11;25140:18;25136:1;25131:3;25127:11;25120:39;25092:2;25089:1;25085:10;25080:15;;25056:113;;;25203:1;25194:6;25189:3;25185:16;25178:27;25027:184;24965:246;;;:::o;25217:386::-;25321:3;25349:38;25381:5;25349:38;:::i;:::-;25403:88;25484:6;25479:3;25403:88;:::i;:::-;25396:95;;25500:65;25558:6;25553:3;25546:4;25539:5;25535:16;25500:65;:::i;:::-;25590:6;25585:3;25581:16;25574:23;;25325:278;25217:386;;;;:::o;25609:271::-;25739:3;25761:93;25850:3;25841:6;25761:93;:::i;:::-;25754:100;;25871:3;25864:10;;25609:271;;;;:::o
Swarm Source
ipfs://af5a0ae2c27b8386bed1a02ef36a5deff53347387a1556aadc32e8a208c2416c
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ 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.