Overview
POL Balance
0 POL
POL Value
$0.00Token Holdings
Latest 25 from a total of 93,510 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Remove Liquidity... | 66154300 | 6 days ago | IN | 0 POL | 0.00705347 | ||||
Remove Liquidity... | 66154079 | 6 days ago | IN | 0 POL | 0.00886984 | ||||
Remove Liquidity... | 66154026 | 6 days ago | IN | 0 POL | 0.00990731 | ||||
Remove Liquidity... | 66153642 | 6 days ago | IN | 0 POL | 0.00509897 | ||||
Remove Liquidity... | 66153206 | 6 days ago | IN | 0 POL | 0.00600594 | ||||
Remove Liquidity... | 66153106 | 6 days ago | IN | 0 POL | 0.00636957 | ||||
Remove Liquidity... | 66153077 | 6 days ago | IN | 0 POL | 0.00628718 | ||||
Remove Liquidity... | 66153056 | 6 days ago | IN | 0 POL | 0.006129 | ||||
Remove Liquidity... | 66152941 | 6 days ago | IN | 0 POL | 0.00572719 | ||||
Remove Liquidity... | 66152680 | 6 days ago | IN | 0 POL | 0.00532337 | ||||
Remove Liquidity... | 66144985 | 6 days ago | IN | 0 POL | 0.00578114 | ||||
Remove Liquidity... | 66144948 | 6 days ago | IN | 0 POL | 0.00563662 | ||||
Remove Liquidity... | 63681802 | 68 days ago | IN | 0 POL | 0.00205798 | ||||
Remove Liquidity... | 62411084 | 100 days ago | IN | 0 POL | 0.00150918 | ||||
Remove Liquidity... | 62410985 | 100 days ago | IN | 0 POL | 0.00510624 | ||||
Remove Liquidity... | 62410985 | 100 days ago | IN | 0 POL | 0.00359795 | ||||
Remove Liquidity... | 59439563 | 174 days ago | IN | 0 POL | 0.00520116 | ||||
Remove Liquidity... | 56644094 | 245 days ago | IN | 0 POL | 0.00520188 | ||||
Remove Liquidity... | 53994487 | 315 days ago | IN | 0 POL | 0.00519444 | ||||
Remove Liquidity... | 51437376 | 381 days ago | IN | 0 POL | 0.00225516 | ||||
Remove Liquidity... | 51436723 | 381 days ago | IN | 0 POL | 0.00283407 | ||||
Remove Liquidity... | 51436471 | 381 days ago | IN | 0 POL | 0.0043108 | ||||
Remove Liquidity... | 51128969 | 389 days ago | IN | 0 POL | 0.01923725 | ||||
Remove Liquidity... | 51128233 | 389 days ago | IN | 0 POL | 0.01301941 | ||||
Remove Liquidity... | 51128050 | 389 days ago | IN | 0 POL | 0.01150258 |
Latest 1 internal transaction
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
16557601 | 1281 days ago | Contract Creation | 0 POL |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
IronSwap
Compiler Version
v0.8.4+commit.c7e474f2
Contract Source Code (Solidity)
/** *Submitted for verification at polygonscan.com on 2021-07-06 */ // Sources flattened with hardhat v2.4.1 https://hardhat.org // File @openzeppelin/contracts/security/[email protected] // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor () { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } } // File @openzeppelin/contracts/proxy/utils/[email protected] // solhint-disable-next-line compiler-version pragma solidity ^0.8.0; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Modifier to protect an initializer function from being invoked twice. */ modifier initializer() { require(_initializing || !_initialized, "Initializable: contract is already initialized"); bool isTopLevelCall = !_initializing; if (isTopLevelCall) { _initializing = true; _initialized = true; } _; if (isTopLevelCall) { _initializing = false; } } } // File @openzeppelin/contracts/token/ERC20/[email protected] pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } // File @openzeppelin/contracts/utils/[email protected] pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain`call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: value }(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } } // File @openzeppelin/contracts/token/ERC20/utils/[email protected] pragma solidity ^0.8.0; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // solhint-disable-next-line max-line-length require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } // File @openzeppelin/contracts/utils/[email protected] pragma solidity ^0.8.0; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } // File @openzeppelin/contracts/access/[email protected] pragma solidity ^0.8.0; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor () { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } // File @openzeppelin/contracts/security/[email protected] pragma solidity ^0.8.0; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor () { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { require(!paused(), "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { require(paused(), "Pausable: not paused"); _; } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } } // File contracts/base/OwnerPausable.sol pragma solidity 0.8.4; abstract contract OwnerPausable is Ownable, Pausable { function pause() external onlyOwner { _pause(); } function unpause() external onlyOwner { _unpause(); } } // File @openzeppelin/contracts/token/ERC20/extensions/[email protected] pragma solidity ^0.8.0; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); } // File @openzeppelin/contracts/token/ERC20/[email protected] pragma solidity ^0.8.0; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin guidelines: functions revert instead * of returning `false` on failure. This behavior is nonetheless conventional * and does not conflict with the expectations of ERC20 applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * The defaut value of {decimals} is 18. To select a different value for * {decimals} you should overload it. * * All two of these values are immutable: they can only be set once during * construction. */ constructor (string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless this function is * overridden; * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * Requirements: * * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for ``sender``'s tokens of at least * `amount`. */ function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { _transfer(sender, recipient, amount); uint256 currentAllowance = _allowances[sender][_msgSender()]; require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); _approve(sender, _msgSender(), currentAllowance - amount); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { uint256 currentAllowance = _allowances[_msgSender()][spender]; require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); _approve(_msgSender(), spender, currentAllowance - subtractedValue); return true; } /** * @dev Moves tokens `amount` from `sender` to `recipient`. * * This is internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer(address sender, address recipient, uint256 amount) internal virtual { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(sender, recipient, amount); uint256 senderBalance = _balances[sender]; require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); _balances[sender] = senderBalance - amount; _balances[recipient] += amount; emit Transfer(sender, recipient, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `to` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; _balances[account] += amount; emit Transfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); _balances[account] = accountBalance - amount; _totalSupply -= amount; emit Transfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve(address owner, address spender, uint256 amount) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be to transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } } // File @openzeppelin/contracts/token/ERC20/extensions/[email protected] pragma solidity ^0.8.0; /** * @dev Extension of {ERC20} that allows token holders to destroy both their own * tokens and those that they have an allowance for, in a way that can be * recognized off-chain (via event analysis). */ abstract contract ERC20Burnable is Context, ERC20 { /** * @dev Destroys `amount` tokens from the caller. * * See {ERC20-_burn}. */ function burn(uint256 amount) public virtual { _burn(_msgSender(), amount); } /** * @dev Destroys `amount` tokens from `account`, deducting from the caller's * allowance. * * See {ERC20-_burn} and {ERC20-allowance}. * * Requirements: * * - the caller must have allowance for ``accounts``'s tokens of at least * `amount`. */ function burnFrom(address account, uint256 amount) public virtual { uint256 currentAllowance = allowance(account, _msgSender()); require(currentAllowance >= amount, "ERC20: burn amount exceeds allowance"); _approve(account, _msgSender(), currentAllowance - amount); _burn(account, amount); } } // File contracts/interfaces/IIronSwap.sol pragma solidity 0.8.4; interface IIronSwap { /// EVENTS event AddLiquidity( address indexed provider, uint256[] tokenAmounts, uint256[] fees, uint256 invariant, uint256 tokenSupply ); event TokenExchange( address indexed buyer, uint256 soldId, uint256 tokensSold, uint256 boughtId, uint256 tokensBought ); event RemoveLiquidity(address indexed provider, uint256[] tokenAmounts, uint256[] fees, uint256 tokenSupply); event RemoveLiquidityOne(address indexed provider, uint256 tokenIndex, uint256 tokenAmount, uint256 coinAmount); event RemoveLiquidityImbalance( address indexed provider, uint256[] tokenAmounts, uint256[] fees, uint256 invariant, uint256 tokenSupply ); event RampA(uint256 oldA, uint256 newA, uint256 initialTime, uint256 futureTime); event StopRampA(uint256 A, uint256 timestamp); event NewFee(uint256 fee, uint256 adminFee, uint256 withdrawFee); event CollectProtocolFee(address token, uint256 amount); event FeeControllerChanged(address newController); event FeeDistributorChanged(address newController); // pool data view functions function getLpToken() external view returns (IERC20 lpToken); function getA() external view returns (uint256); function getAPrecise() external view returns (uint256); function getToken(uint8 index) external view returns (IERC20); function getTokens() external view returns (IERC20[] memory); function getTokenIndex(address tokenAddress) external view returns (uint8); function getTokenBalance(uint8 index) external view returns (uint256); function getTokenBalances() external view returns (uint256[] memory); function getNumberOfTokens() external view returns (uint256); function getVirtualPrice() external view returns (uint256); function calculateTokenAmount(uint256[] calldata amounts, bool deposit) external view returns (uint256); function calculateSwap( uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx ) external view returns (uint256); function calculateRemoveLiquidity(address account, uint256 amount) external view returns (uint256[] memory); function calculateRemoveLiquidityOneToken( address account, uint256 tokenAmount, uint8 tokenIndex ) external view returns (uint256 availableTokenAmount); function getAdminBalances() external view returns (uint256[] memory adminBalances); function getAdminBalance(uint8 index) external view returns (uint256); function calculateCurrentWithdrawFee(address account) external view returns (uint256); // state modifying functions function swap( uint8 tokenIndexFrom, uint8 tokenIndexTo, uint256 dx, uint256 minDy, uint256 deadline ) external returns (uint256); function addLiquidity( uint256[] calldata amounts, uint256 minToMint, uint256 deadline ) external returns (uint256); function removeLiquidity( uint256 amount, uint256[] calldata minAmounts, uint256 deadline ) external returns (uint256[] memory); function removeLiquidityOneToken( uint256 tokenAmount, uint8 tokenIndex, uint256 minAmount, uint256 deadline ) external returns (uint256); function removeLiquidityImbalance( uint256[] calldata amounts, uint256 maxBurnAmount, uint256 deadline ) external returns (uint256); function updateUserWithdrawFee(address recipient, uint256 transferAmount) external; } // File contracts/tokens/LPToken.sol pragma solidity ^0.8.4; contract LPToken is Ownable, ERC20Burnable { IIronSwap public swap; constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) { swap = IIronSwap(msg.sender); } function mint(address _to, uint256 _amount) external onlyOwner { require(_amount > 0, "zeroMintAmount"); _mint(_to, _amount); } /** * @dev Overrides ERC20._beforeTokenTransfer() which get called on every transfers including * minting and burning. This ensures that swap.updateUserWithdrawFees are called everytime. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal override(ERC20) { super._beforeTokenTransfer(from, to, amount); swap.updateUserWithdrawFee(to, amount); } } // File contracts/IronSwapLib.sol pragma solidity 0.8.4; /** * StableSwap main algorithm */ library IronSwapLib { using SafeERC20 for IERC20; event AddLiquidity( address indexed provider, uint256[] token_amounts, uint256[] fees, uint256 invariant, uint256 token_supply ); event TokenExchange( address indexed buyer, uint256 sold_id, uint256 tokens_sold, uint256 bought_id, uint256 tokens_bought ); event RemoveLiquidity(address indexed provider, uint256[] token_amounts, uint256[] fees, uint256 token_supply); event RemoveLiquidityOne(address indexed provider, uint256 index, uint256 token_amount, uint256 coin_amount); event RemoveLiquidityImbalance( address indexed provider, uint256[] token_amounts, uint256[] fees, uint256 invariant, uint256 token_supply ); uint256 public constant FEE_DENOMINATOR = 1e10; // uint256 public constant PRECISION = 1e18; /// @dev protect from division loss when run approximation loop. We cannot divide at the end because of overflow, /// so we add some (small) PRECISION when divide in each iteration uint256 public constant A_PRECISION = 100; /// @dev max iteration of converge calccuate uint256 internal constant MAX_ITERATION = 256; uint256 public constant POOL_TOKEN_COMMON_DECIMALS = 18; struct SwapStorage { IERC20[] pooledTokens; LPToken lpToken; /// @dev token i multiplier to reach POOL_TOKEN_COMMON_DECIMALS uint256[] tokenMultipliers; /// @dev effective balance which might different from token balance of the contract 'cause it hold admin fee as well uint256[] balances; /// @dev swap fee ratio. Charge on any action which move balance state far from the ideal state uint256 fee; /// @dev admin fee in ratio of swap fee. uint256 adminFee; /// @dev observation of A, multiplied with A_PRECISION uint256 initialA; uint256 futureA; uint256 initialATime; uint256 futureATime; // withdrawal fee control uint256 defaultWithdrawFee; mapping(address => uint256) depositTimestamp; mapping(address => uint256) withdrawFeeMultiplier; } /** * @notice Deposit coins into the pool * @param amounts List of amounts of coins to deposit * @param minMintAmount Minimum amount of LP tokens to mint from the deposit * @return mintAmount Amount of LP tokens received by depositing */ function addLiquidity( SwapStorage storage self, uint256[] memory amounts, uint256 minMintAmount ) external returns (uint256 mintAmount) { uint256 nCoins = self.pooledTokens.length; require(amounts.length == nCoins, "invalidAmountsLength"); uint256[] memory fees = new uint256[](nCoins); uint256 _fee = _feePerToken(self); uint256 tokenSupply = self.lpToken.totalSupply(); uint256 amp = _getAPrecise(self); uint256 D0 = 0; if (tokenSupply > 0) { D0 = _getD(_xp(self.balances, self.tokenMultipliers), amp); } uint256[] memory newBalances = self.balances; for (uint256 i = 0; i < nCoins; i++) { if (tokenSupply == 0) { require(amounts[i] > 0, "initialDepositRequireAllTokens"); } // get real transfer in amount newBalances[i] += _doTransferIn(self.pooledTokens[i], amounts[i]); } uint256 D1 = _getD(_xp(newBalances, self.tokenMultipliers), amp); assert(D1 > D0); // double check if (tokenSupply == 0) { self.balances = newBalances; mintAmount = D1; } else { uint256 diff = 0; for (uint256 i = 0; i < nCoins; i++) { diff = _distance((D1 * self.balances[i]) / D0, newBalances[i]); fees[i] = (_fee * diff) / FEE_DENOMINATOR; self.balances[i] = newBalances[i] - ((fees[i] * self.adminFee) / FEE_DENOMINATOR); newBalances[i] -= fees[i]; } D1 = _getD(_xp(newBalances, self.tokenMultipliers), amp); mintAmount = (tokenSupply * (D1 - D0)) / D0; } require(mintAmount >= minMintAmount, "> slippage"); self.lpToken.mint(msg.sender, mintAmount); emit AddLiquidity(msg.sender, amounts, fees, D1, mintAmount); } function swap( SwapStorage storage self, uint256 i, uint256 j, uint256 inAmount, uint256 minOutAmount ) external returns (uint256) { IERC20 inCoin = self.pooledTokens[i]; uint256[] memory normalizedBalances = _xp(self); inAmount = _doTransferIn(inCoin, inAmount); uint256 x = normalizedBalances[i] + (inAmount * self.tokenMultipliers[i]); uint256 y = _getY(self, i, j, x, normalizedBalances); uint256 dy = normalizedBalances[j] - y - 1; // iliminate rouding errors uint256 dy_fee = (dy * self.fee) / FEE_DENOMINATOR; dy = (dy - dy_fee) / self.tokenMultipliers[j]; // denormalize require(dy >= minOutAmount, "> slippage"); uint256 _adminFee = (dy_fee * self.adminFee) / FEE_DENOMINATOR / self.tokenMultipliers[j]; // update balances self.balances[i] += inAmount; self.balances[j] -= dy + _adminFee; self.pooledTokens[j].safeTransfer(msg.sender, dy); emit TokenExchange(msg.sender, i, inAmount, j, dy); return dy; } function removeLiquidity( SwapStorage storage self, uint256 lpAmount, uint256[] memory minAmounts ) external returns (uint256[] memory amounts) { uint256 totalSupply = self.lpToken.totalSupply(); require(lpAmount <= totalSupply); uint256 nCoins = self.pooledTokens.length; uint256[] memory fees = new uint256[](nCoins); amounts = _calculateRemoveLiquidity(self, msg.sender, lpAmount); for (uint256 i = 0; i < amounts.length; i++) { require(amounts[i] >= minAmounts[i], "> slippage"); self.balances[i] = self.balances[i] - amounts[i]; self.pooledTokens[i].safeTransfer(msg.sender, amounts[i]); } self.lpToken.burnFrom(msg.sender, lpAmount); emit RemoveLiquidity(msg.sender, amounts, fees, totalSupply - lpAmount); } function removeLiquidityOneToken( SwapStorage storage self, uint256 lpAmount, uint256 index, uint256 minAmount ) external returns (uint256) { uint256 totalSupply = self.lpToken.totalSupply(); require(totalSupply > 0, "totalSupply = 0"); uint256 numTokens = self.pooledTokens.length; require(lpAmount <= self.lpToken.balanceOf(msg.sender), "> balance"); require(lpAmount <= totalSupply, "> totalSupply"); require(index < numTokens, "tokenNotFound"); uint256 dyFee; uint256 dy; (dy, dyFee) = _calculateRemoveLiquidityOneToken(self, msg.sender, lpAmount, index); require(dy >= minAmount, "> slippage"); self.balances[index] -= (dy + (dyFee * self.adminFee) / FEE_DENOMINATOR); self.lpToken.burnFrom(msg.sender, lpAmount); self.pooledTokens[index].safeTransfer(msg.sender, dy); emit RemoveLiquidityOne(msg.sender, index, lpAmount, dy); return dy; } function removeLiquidityImbalance( SwapStorage storage self, uint256[] memory amounts, uint256 maxBurnAmount ) external returns (uint256 burnAmount) { uint256 nCoins = self.pooledTokens.length; require(amounts.length == nCoins, "invalidAmountsLength"); uint256 totalSupply = self.lpToken.totalSupply(); require(totalSupply != 0, "totalSupply = 0"); uint256 _fee = _feePerToken(self); uint256 amp = _getAPrecise(self); uint256[] memory newBalances = self.balances; uint256 D0 = _getD(_xp(self), amp); for (uint256 i = 0; i < nCoins; i++) { newBalances[i] -= amounts[i]; } uint256 D1 = _getD(_xp(newBalances, self.tokenMultipliers), amp); uint256[] memory fees = new uint256[](nCoins); for (uint256 i = 0; i < nCoins; i++) { uint256 idealBalance = (D1 * self.balances[i]) / D0; uint256 diff = _distance(newBalances[i], idealBalance); fees[i] = (_fee * diff) / FEE_DENOMINATOR; self.balances[i] = newBalances[i] - ((fees[i] * self.adminFee) / FEE_DENOMINATOR); newBalances[i] -= fees[i]; } // recalculate invariant with fee charged balances D1 = _getD(_xp(newBalances, self.tokenMultipliers), amp); burnAmount = ((D0 - D1) * totalSupply) / D0; assert(burnAmount > 0); burnAmount = (burnAmount + 1) * (FEE_DENOMINATOR - _calculateCurrentWithdrawFee(self, msg.sender)); //In case of rounding errors - make it unfavorable for the "attacker" require(burnAmount <= maxBurnAmount, "> slippage"); self.lpToken.burnFrom(msg.sender, burnAmount); for (uint256 i = 0; i < nCoins; i++) { if (amounts[i] != 0) { self.pooledTokens[i].safeTransfer(msg.sender, amounts[i]); } } emit RemoveLiquidityImbalance(msg.sender, amounts, fees, D1, totalSupply - burnAmount); } /// VIEW FUNCTIONS function getAPrecise(SwapStorage storage self) external view returns (uint256) { return _getAPrecise(self); } /** * Returns portfolio virtual price (for calculating profit) * scaled up by 1e18 */ function getVirtualPrice(SwapStorage storage self) external view returns (uint256) { uint256 D = _getD(_xp(self), _getAPrecise(self)); uint256 tokenSupply = self.lpToken.totalSupply(); return (D * 10**POOL_TOKEN_COMMON_DECIMALS) / tokenSupply; } function getAdminBalance(SwapStorage storage self, uint256 index) external view returns (uint256) { require(index < self.pooledTokens.length, "indexOutOfRange"); return self.pooledTokens[index].balanceOf(address(this)) - (self.balances[index]); } /** * Estimate amount of LP token minted or burned at deposit or withdrawal * without taking fees into account */ function calculateTokenAmount( SwapStorage storage self, uint256[] memory amounts, bool deposit ) external view returns (uint256) { uint256 nCoins = self.pooledTokens.length; require(amounts.length == nCoins, "invalidAmountsLength"); uint256 amp = _getAPrecise(self); uint256 D0 = _getD(_xp(self), amp); uint256[] memory newBalances = self.balances; for (uint256 i = 0; i < nCoins; i++) { if (deposit) { newBalances[i] += amounts[i]; } else { newBalances[i] -= amounts[i]; } } uint256 D1 = _getD(_xp(newBalances, self.tokenMultipliers), amp); uint256 totalSupply = self.lpToken.totalSupply(); if (totalSupply == 0) { return D1; // first depositor take it all } uint256 diff = deposit ? D1 - D0 : D0 - D1; return (diff * self.lpToken.totalSupply()) / D0; } function getA(SwapStorage storage self) external view returns (uint256) { return _getAPrecise(self) / A_PRECISION; } function calculateSwap( SwapStorage storage self, uint256 inIndex, uint256 outIndex, uint256 inAmount ) external view returns (uint256) { uint256[] memory normalizedBalances = _xp(self); uint256 newInBalance = normalizedBalances[inIndex] + (inAmount * self.tokenMultipliers[inIndex]); uint256 outBalance = _getY(self, inIndex, outIndex, newInBalance, normalizedBalances); uint256 outAmount = (normalizedBalances[outIndex] - outBalance - 1) / self.tokenMultipliers[outIndex]; uint256 _fee = (self.fee * outAmount) / FEE_DENOMINATOR; return outAmount - _fee; } function calculateRemoveLiquidity( SwapStorage storage self, address account, uint256 amount ) external view returns (uint256[] memory) { return _calculateRemoveLiquidity(self, account, amount); } function calculateRemoveLiquidityOneToken( SwapStorage storage self, address account, uint256 lpAmount, uint256 tokenIndex ) external view returns (uint256 amount) { (amount, ) = _calculateRemoveLiquidityOneToken(self, account, lpAmount, tokenIndex); } /** * @notice Update the withdraw fee for `user`. If the user is currently * not providing liquidity in the pool, sets to default value. If not, recalculate * the starting withdraw fee based on the last deposit's time & amount relative * to the new deposit. * * @param self Swap struct to read from and write to * @param user address of the user depositing tokens * @param toMint amount of pool tokens to be minted */ function updateUserWithdrawFee( SwapStorage storage self, address user, uint256 toMint ) external { _updateUserWithdrawFee(self, user, toMint); } /// INTERNAL FUNCTIONS /** * Ramping A up or down, return A with precision of A_PRECISION */ function _getAPrecise(SwapStorage storage self) internal view returns (uint256) { if (block.timestamp >= self.futureATime) { return self.futureA; } if (self.futureA > self.initialA) { return self.initialA + ((self.futureA - self.initialA) * (block.timestamp - self.initialATime)) / (self.futureATime - self.initialATime); } return self.initialA - ((self.initialA - self.futureA) * (block.timestamp - self.initialATime)) / (self.futureATime - self.initialATime); } /** * normalized balances of each tokens. */ function _xp(uint256[] memory balances, uint256[] memory rates) internal pure returns (uint256[] memory) { for (uint256 i = 0; i < balances.length; i++) { rates[i] = (rates[i] * balances[i]); } return rates; } function _xp(SwapStorage storage self) internal view returns (uint256[] memory) { return _xp(self.balances, self.tokenMultipliers); } /** * Calculate D for *NORMALIZED* balances of each tokens * @param xp normalized balances of token */ function _getD(uint256[] memory xp, uint256 amp) internal pure returns (uint256) { uint256 nCoins = xp.length; uint256 sum = _sumOf(xp); if (sum == 0) { return 0; } uint256 Dprev = 0; uint256 D = sum; uint256 Ann = amp * nCoins; for (uint256 i = 0; i < MAX_ITERATION; i++) { uint256 D_P = D; for (uint256 j = 0; j < xp.length; j++) { D_P = (D_P * D) / (xp[j] * nCoins); } Dprev = D; D = (((Ann * sum) / A_PRECISION + D_P * nCoins) * D) / (((Ann - A_PRECISION) * D) / A_PRECISION + (nCoins + 1) * D_P); if (_distance(D, Dprev) <= 1) { return D; } } // Convergence should occur in 4 loops or less. If this is reached, there may be something wrong // with the pool. If this were to occur repeatedly, LPs should withdraw via `removeLiquidity()` // function which does not rely on D. revert("invariantCalculationFailed"); } /** * calculate new balance of when swap * Done by solving quadratic equation iteratively. * x_1**2 + x_1 * (sum' - (A*n**n - 1) * D / (A * n**n)) = D ** (n + 1) / (n ** (2 * n) * prod' * A) * x_1**2 + b*x_1 = c * x_1 = (x_1**2 + c) / (2*x_1 + b) * @param inIndex index of token to swap in * @param outIndex index of token to swap out * @param inBalance new balance (normalized) of input token if the swap success * @return NORMALIZED balance of output token if the swap success */ function _getY( SwapStorage storage self, uint256 inIndex, uint256 outIndex, uint256 inBalance, uint256[] memory normalizedBalances ) internal view returns (uint256) { require(inIndex != outIndex, "sameToken"); uint256 nCoins = self.pooledTokens.length; require(inIndex < nCoins && outIndex < nCoins, "indexOutOfRange"); uint256 amp = _getAPrecise(self); uint256 Ann = amp * nCoins; uint256 D = _getD(normalizedBalances, amp); uint256 sum = 0; // sum of new balances except output token uint256 c = D; for (uint256 i = 0; i < nCoins; i++) { if (i == outIndex) { continue; } uint256 x = i == inIndex ? inBalance : normalizedBalances[i]; sum += x; c = (c * D) / (x * nCoins); } c = (c * D * A_PRECISION) / (Ann * nCoins); uint256 b = sum + (D * A_PRECISION) / Ann; uint256 lastY = 0; uint256 y = D; for (uint256 index = 0; index < MAX_ITERATION; index++) { lastY = y; y = (y * y + c) / (2 * y + b - D); if (_distance(lastY, y) <= 1) { return y; } } revert("yCalculationFailed"); } function _calculateRemoveLiquidity( SwapStorage storage self, address account, uint256 amount ) internal view returns (uint256[] memory) { uint256 totalSupply = self.lpToken.totalSupply(); require(amount <= totalSupply, "Cannot exceed total supply"); uint256 feeAdjustedAmount = (amount * (FEE_DENOMINATOR - _calculateCurrentWithdrawFee(self, account))) / FEE_DENOMINATOR; uint256[] memory amounts = new uint256[](self.pooledTokens.length); for (uint256 i = 0; i < self.pooledTokens.length; i++) { amounts[i] = (self.balances[i] * (feeAdjustedAmount)) / (totalSupply); } return amounts; } function _calculateRemoveLiquidityOneToken( SwapStorage storage self, address account, uint256 tokenAmount, uint256 index ) internal view returns (uint256 dy, uint256 fee) { require(index < self.pooledTokens.length, "indexOutOfRange"); uint256 amp = _getAPrecise(self); uint256[] memory xp = _xp(self); uint256 D0 = _getD(xp, amp); uint256 D1 = D0 - (tokenAmount * D0) / self.lpToken.totalSupply(); uint256 newY = _getYD(self, amp, index, xp, D1); uint256[] memory reducedXP = xp; uint256 _fee = _feePerToken(self); for (uint256 i = 0; i < self.pooledTokens.length; i++) { uint256 expectedDx = 0; if (i == index) { expectedDx = (xp[i] * D1) / D0 - newY; } else { expectedDx = xp[i] - (xp[i] * D1) / D0; } reducedXP[i] -= (_fee * expectedDx) / FEE_DENOMINATOR; } dy = reducedXP[index] - _getYD(self, amp, index, reducedXP, D1); dy = (dy - 1) / self.tokenMultipliers[index]; fee = ((xp[index] - newY) / self.tokenMultipliers[index]) - dy; dy = (dy * (FEE_DENOMINATOR - _calculateCurrentWithdrawFee(self, account))) / FEE_DENOMINATOR; } function _feePerToken(SwapStorage storage self) internal view returns (uint256) { uint256 nCoins = self.pooledTokens.length; return (self.fee * nCoins) / (4 * (nCoins - 1)); } function _getYD( SwapStorage storage self, uint256 A, uint256 index, uint256[] memory xp, uint256 D ) internal view returns (uint256) { uint256 nCoins = self.pooledTokens.length; assert(index < nCoins); uint256 Ann = A * nCoins; uint256 c = D; uint256 s = 0; uint256 _x = 0; uint256 yPrev = 0; for (uint256 i = 0; i < nCoins; i++) { if (i == index) { continue; } _x = xp[i]; s += _x; c = (c * D) / (_x * nCoins); } c = (c * D * A_PRECISION) / (Ann * nCoins); uint256 b = s + (D * A_PRECISION) / Ann; uint256 y = D; for (uint256 i = 0; i < MAX_ITERATION; i++) { yPrev = y; y = (y * y + c) / (2 * y + b - D); if (_distance(yPrev, y) <= 1) { return y; } } revert("invariantCalculationFailed"); } function _updateUserWithdrawFee( SwapStorage storage self, address user, uint256 toMint ) internal { // If token is transferred to address 0 (or burned), don't update the fee. if (user == address(0)) { return; } if (self.defaultWithdrawFee == 0) { // If current fee is set to 0%, set multiplier to FEE_DENOMINATOR self.withdrawFeeMultiplier[user] = FEE_DENOMINATOR; } else { // Otherwise, calculate appropriate discount based on last deposit amount uint256 currentFee = _calculateCurrentWithdrawFee(self, user); uint256 currentBalance = self.lpToken.balanceOf(user); // ((currentBalance * currentFee) + (toMint * defaultWithdrawFee)) * FEE_DENOMINATOR / // ((toMint + currentBalance) * defaultWithdrawFee) if ((toMint + currentBalance) * self.defaultWithdrawFee != 0) { self.withdrawFeeMultiplier[user] = (((currentBalance * currentFee) + (toMint * self.defaultWithdrawFee)) * (FEE_DENOMINATOR)) / ((toMint + currentBalance) * self.defaultWithdrawFee); } } self.depositTimestamp[user] = block.timestamp; } /** * @notice Calculate the fee that is applied when the given user withdraws. * Withdraw fee decays linearly over 4 weeks. * @param user address you want to calculate withdraw fee of * @return current withdraw fee of the user */ function _calculateCurrentWithdrawFee(SwapStorage storage self, address user) internal view returns (uint256) { uint256 endTime = self.depositTimestamp[user] + (4 weeks); if (endTime > block.timestamp) { uint256 timeLeftover = endTime - block.timestamp; return (self.defaultWithdrawFee * self.withdrawFeeMultiplier[user] * timeLeftover) / (4 weeks) / FEE_DENOMINATOR; } return 0; } function _doTransferIn(IERC20 token, uint256 amount) internal returns (uint256) { uint256 priorBalance = token.balanceOf(address(this)); token.safeTransferFrom(msg.sender, address(this), amount); return token.balanceOf(address(this)) - priorBalance; } function _sumOf(uint256[] memory x) internal pure returns (uint256 sum) { sum = 0; for (uint256 i = 0; i < x.length; i++) { sum += x[i]; } } function _distance(uint256 x, uint256 y) internal pure returns (uint256) { return x > y ? x - y : y - x; } } // File contracts/IronSwap.sol pragma solidity 0.8.4; contract IronSwap is OwnerPausable, ReentrancyGuard, Initializable, IIronSwap { using IronSwapLib for IronSwapLib.SwapStorage; using SafeERC20 for IERC20; /// constants uint256 public constant MIN_RAMP_TIME = 1 days; uint256 public constant MAX_A = 1e10; // max_a with precision uint256 public constant MAX_A_CHANGE = 10; uint256 public constant MAX_ADMIN_FEE = 1e10; // 100% uint256 public constant MAX_SWAP_FEE = 1e8; // 1% uint256 public constant MAX_WITHDRAW_FEE = 1e8; // 1% /// STATE VARS IronSwapLib.SwapStorage public swapStorage; address public feeDistributor; address public feeController; mapping(address => uint8) public tokenIndexes; modifier deadlineCheck(uint256 _deadline) { require(block.timestamp <= _deadline, "timeout"); _; } modifier onlyFeeControllerOrOwner() { require(msg.sender == feeController || msg.sender == owner(), "!feeControllerOrOwner"); _; } function initialize( address[] memory _coins, uint8[] memory _decimals, string memory lpTokenName, string memory lpTokenSymbol, uint256 _A, uint256 _fee, uint256 _adminFee, uint256 _withdrawFee, address _feeDistributor ) external onlyOwner initializer { require(_coins.length == _decimals.length, "coinsLength != decimalsLength"); require(_feeDistributor != address(0), "feeDistributor = empty"); uint256 numberOfCoins = _coins.length; uint256[] memory rates = new uint256[](numberOfCoins); IERC20[] memory coins = new IERC20[](numberOfCoins); for (uint256 i = 0; i < numberOfCoins; i++) { require(_coins[i] != address(0), "invalidTokenAddress"); require(_decimals[i] <= IronSwapLib.POOL_TOKEN_COMMON_DECIMALS, "invalidDecimals"); rates[i] = 10**(IronSwapLib.POOL_TOKEN_COMMON_DECIMALS - _decimals[i]); coins[i] = IERC20(_coins[i]); tokenIndexes[address(coins[i])] = uint8(i); } require(_A < MAX_A, "> maxA"); require(_fee <= MAX_SWAP_FEE, "> maxSwapFee"); require(_adminFee <= MAX_ADMIN_FEE, "> maxAdminFee"); require(_withdrawFee <= MAX_WITHDRAW_FEE, "> maxWithdrawFee"); swapStorage.lpToken = new LPToken(lpTokenName, lpTokenSymbol); swapStorage.balances = new uint256[](numberOfCoins); swapStorage.tokenMultipliers = rates; swapStorage.pooledTokens = coins; swapStorage.initialA = _A * IronSwapLib.A_PRECISION; swapStorage.futureA = _A * IronSwapLib.A_PRECISION; swapStorage.fee = _fee; swapStorage.adminFee = _adminFee; swapStorage.defaultWithdrawFee = _withdrawFee; feeDistributor = _feeDistributor; } /// PUBLIC FUNCTIONS function addLiquidity( uint256[] memory amounts, uint256 minMintAmount, uint256 deadline ) external override whenNotPaused nonReentrant deadlineCheck(deadline) returns (uint256) { return swapStorage.addLiquidity(amounts, minMintAmount); } function swap( uint8 fromIndex, uint8 toIndex, uint256 inAmount, uint256 minOutAmount, uint256 deadline ) external override whenNotPaused nonReentrant deadlineCheck(deadline) returns (uint256) { return swapStorage.swap(fromIndex, toIndex, inAmount, minOutAmount); } function removeLiquidity( uint256 lpAmount, uint256[] memory minAmounts, uint256 deadline ) external override nonReentrant deadlineCheck(deadline) returns (uint256[] memory) { return swapStorage.removeLiquidity(lpAmount, minAmounts); } function removeLiquidityOneToken( uint256 lpAmount, uint8 index, uint256 minAmount, uint256 deadline ) external override nonReentrant whenNotPaused deadlineCheck(deadline) returns (uint256) { return swapStorage.removeLiquidityOneToken(lpAmount, index, minAmount); } function removeLiquidityImbalance( uint256[] memory amounts, uint256 maxBurnAmount, uint256 deadline ) external override nonReentrant whenNotPaused deadlineCheck(deadline) returns (uint256) { return swapStorage.removeLiquidityImbalance(amounts, maxBurnAmount); } /// VIEW FUNCTIONS function getVirtualPrice() external view override returns (uint256) { return swapStorage.getVirtualPrice(); } function getA() external view override returns (uint256) { return swapStorage.getA(); } function getAPrecise() external view override returns (uint256) { return swapStorage.getAPrecise(); } function getTokens() external view override returns (IERC20[] memory) { return swapStorage.pooledTokens; } function getToken(uint8 index) external view override returns (IERC20) { return swapStorage.pooledTokens[index]; } function getLpToken() external view override returns (IERC20) { return swapStorage.lpToken; } function getTokenIndex(address token) external view override returns (uint8 index) { index = tokenIndexes[token]; require(address(swapStorage.pooledTokens[index]) == token, "tokenNotFound"); } function getTokenPrecisionMultipliers() external view returns (uint256[] memory) { return swapStorage.tokenMultipliers; } function getTokenBalances() external view override returns (uint256[] memory) { return swapStorage.balances; } function getTokenBalance(uint8 index) external view override returns (uint256) { return swapStorage.balances[index]; } function getNumberOfTokens() external view override returns (uint256) { return swapStorage.pooledTokens.length; } function getAdminBalances() external view override returns (uint256[] memory adminBalances) { uint256 length = swapStorage.pooledTokens.length; adminBalances = new uint256[](length); for (uint256 i = 0; i < length; i++) { adminBalances[i] = swapStorage.getAdminBalance(i); } } function getAdminBalance(uint8 index) external view override returns (uint256) { return swapStorage.getAdminBalance((index)); } function calculateTokenAmount(uint256[] calldata amounts, bool deposit) external view override returns (uint256) { return swapStorage.calculateTokenAmount(amounts, deposit); } function calculateSwap( uint8 inIndex, uint8 outIndex, uint256 inAmount ) external view override returns (uint256) { return swapStorage.calculateSwap(inIndex, outIndex, inAmount); } function calculateRemoveLiquidity(address account, uint256 amount) external view override returns (uint256[] memory) { return swapStorage.calculateRemoveLiquidity(account, amount); } function calculateRemoveLiquidityOneToken( address account, uint256 amount, uint8 index ) external view override returns (uint256) { return swapStorage.calculateRemoveLiquidityOneToken(account, amount, index); } function calculateCurrentWithdrawFee(address account) external view override returns (uint256) { return swapStorage._calculateCurrentWithdrawFee(account); } /// RESTRICTED FUNCTION /** * @notice Updates the user withdraw fee. This function can only be called by * the pool token. Should be used to update the withdraw fee on transfer of pool tokens. * Transferring your pool token will reset the 4 weeks period. If the recipient is already * holding some pool tokens, the withdraw fee will be discounted in respective amounts. * @param recipient address of the recipient of pool token * @param transferAmount amount of pool token to transfer */ function updateUserWithdrawFee(address recipient, uint256 transferAmount) external override { require(msg.sender == address(swapStorage.lpToken), "!lpToken"); swapStorage.updateUserWithdrawFee(recipient, transferAmount); } /** * @notice Sets the admin fee * @dev adminFee cannot be higher than 100% of the swap fee * swap fee cannot be higher than 1% of each swap * @param newSwapFee new swap fee to be applied on future transactions * @param newAdminFee new admin fee to be applied on future transactions * @param newWithdrawFee new initial withdraw fee to be applied on future withdrawal transactions */ function setFee( uint256 newSwapFee, uint256 newAdminFee, uint256 newWithdrawFee ) external onlyOwner { require(newSwapFee <= MAX_SWAP_FEE, "> maxSwapFee"); require(newAdminFee <= MAX_ADMIN_FEE, "> maxAdminFee"); require(newWithdrawFee <= MAX_WITHDRAW_FEE, "> maxWithdrawFee"); swapStorage.adminFee = newAdminFee; swapStorage.fee = newSwapFee; swapStorage.defaultWithdrawFee = newWithdrawFee; emit NewFee(newSwapFee, newAdminFee, newWithdrawFee); } /** * @notice Start ramping up or down A parameter towards given futureA_ and futureTime_ * Checks if the change is too rapid, and commits the new A value only when it falls under * the limit range. * @param futureA the new A to ramp towards * @param futureATime timestamp when the new A should be reached */ function rampA(uint256 futureA, uint256 futureATime) external onlyOwner { require(block.timestamp >= swapStorage.initialATime + (1 days), "< rampDelay"); // please wait 1 days before start a new ramping require(futureATime >= block.timestamp + (MIN_RAMP_TIME), "< minRampTime"); require(0 < futureA && futureA < MAX_A, "outOfRange"); uint256 initialAPrecise = swapStorage.getAPrecise(); uint256 futureAPrecise = futureA * IronSwapLib.A_PRECISION; if (futureAPrecise < initialAPrecise) { require(futureAPrecise * (MAX_A_CHANGE) >= initialAPrecise, "> maxChange"); } else { require(futureAPrecise <= initialAPrecise * (MAX_A_CHANGE), "> maxChange"); } swapStorage.initialA = initialAPrecise; swapStorage.futureA = futureAPrecise; swapStorage.initialATime = block.timestamp; swapStorage.futureATime = futureATime; emit RampA(initialAPrecise, futureAPrecise, block.timestamp, futureATime); } function stopRampA() external onlyOwner { require(swapStorage.futureATime > block.timestamp, "alreadyStopped"); uint256 currentA = swapStorage.getA(); swapStorage.initialA = currentA; swapStorage.futureA = currentA; swapStorage.initialATime = block.timestamp; swapStorage.futureATime = block.timestamp; emit StopRampA(currentA, block.timestamp); } function setFeeController(address _feeController) external onlyOwner() { require(_feeController != address(0), "zeroAddress"); feeController = _feeController; emit FeeControllerChanged(_feeController); } function setFeeDistributor(address _feeDistributor) external onlyOwner() { require(_feeDistributor != address(0), "zeroAddress"); feeDistributor = _feeDistributor; emit FeeDistributorChanged(_feeDistributor); } function withdrawAdminFee() external onlyFeeControllerOrOwner { for (uint256 i = 0; i < swapStorage.pooledTokens.length; i++) { IERC20 token = swapStorage.pooledTokens[i]; uint256 balance = token.balanceOf(address(this)) - (swapStorage.balances[i]); if (balance != 0) { token.safeTransfer(feeDistributor, balance); emit CollectProtocolFee(address(token), balance); } } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"provider","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"tokenAmounts","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"fees","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"invariant","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenSupply","type":"uint256"}],"name":"AddLiquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"CollectProtocolFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newController","type":"address"}],"name":"FeeControllerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newController","type":"address"}],"name":"FeeDistributorChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"adminFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"withdrawFee","type":"uint256"}],"name":"NewFee","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":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldA","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newA","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"initialTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"futureTime","type":"uint256"}],"name":"RampA","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"provider","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"tokenAmounts","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"fees","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"tokenSupply","type":"uint256"}],"name":"RemoveLiquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"provider","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"tokenAmounts","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"fees","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"invariant","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenSupply","type":"uint256"}],"name":"RemoveLiquidityImbalance","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"provider","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"coinAmount","type":"uint256"}],"name":"RemoveLiquidityOne","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"A","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"StopRampA","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"uint256","name":"soldId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokensSold","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"boughtId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokensBought","type":"uint256"}],"name":"TokenExchange","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"MAX_A","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_ADMIN_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_A_CHANGE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_SWAP_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_WITHDRAW_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_RAMP_TIME","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"uint256","name":"minMintAmount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"calculateCurrentWithdrawFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"calculateRemoveLiquidity","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint8","name":"index","type":"uint8"}],"name":"calculateRemoveLiquidityOneToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"inIndex","type":"uint8"},{"internalType":"uint8","name":"outIndex","type":"uint8"},{"internalType":"uint256","name":"inAmount","type":"uint256"}],"name":"calculateSwap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bool","name":"deposit","type":"bool"}],"name":"calculateTokenAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeController","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeDistributor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getA","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAPrecise","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"index","type":"uint8"}],"name":"getAdminBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAdminBalances","outputs":[{"internalType":"uint256[]","name":"adminBalances","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLpToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNumberOfTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"index","type":"uint8"}],"name":"getToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"index","type":"uint8"}],"name":"getTokenBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTokenBalances","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getTokenIndex","outputs":[{"internalType":"uint8","name":"index","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTokenPrecisionMultipliers","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTokens","outputs":[{"internalType":"contract IERC20[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVirtualPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_coins","type":"address[]"},{"internalType":"uint8[]","name":"_decimals","type":"uint8[]"},{"internalType":"string","name":"lpTokenName","type":"string"},{"internalType":"string","name":"lpTokenSymbol","type":"string"},{"internalType":"uint256","name":"_A","type":"uint256"},{"internalType":"uint256","name":"_fee","type":"uint256"},{"internalType":"uint256","name":"_adminFee","type":"uint256"},{"internalType":"uint256","name":"_withdrawFee","type":"uint256"},{"internalType":"address","name":"_feeDistributor","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"futureA","type":"uint256"},{"internalType":"uint256","name":"futureATime","type":"uint256"}],"name":"rampA","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"lpAmount","type":"uint256"},{"internalType":"uint256[]","name":"minAmounts","type":"uint256[]"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidity","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"uint256","name":"maxBurnAmount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityImbalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"lpAmount","type":"uint256"},{"internalType":"uint8","name":"index","type":"uint8"},{"internalType":"uint256","name":"minAmount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityOneToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newSwapFee","type":"uint256"},{"internalType":"uint256","name":"newAdminFee","type":"uint256"},{"internalType":"uint256","name":"newWithdrawFee","type":"uint256"}],"name":"setFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeController","type":"address"}],"name":"setFeeController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeDistributor","type":"address"}],"name":"setFeeDistributor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stopRampA","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"fromIndex","type":"uint8"},{"internalType":"uint8","name":"toIndex","type":"uint8"},{"internalType":"uint256","name":"inAmount","type":"uint256"},{"internalType":"uint256","name":"minOutAmount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapStorage","outputs":[{"internalType":"contract LPToken","name":"lpToken","type":"address"},{"internalType":"uint256","name":"fee","type":"uint256"},{"internalType":"uint256","name":"adminFee","type":"uint256"},{"internalType":"uint256","name":"initialA","type":"uint256"},{"internalType":"uint256","name":"futureA","type":"uint256"},{"internalType":"uint256","name":"initialATime","type":"uint256"},{"internalType":"uint256","name":"futureATime","type":"uint256"},{"internalType":"uint256","name":"defaultWithdrawFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokenIndexes","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"transferAmount","type":"uint256"}],"name":"updateUserWithdrawFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawAdminFee","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50600080546001600160a01b031916339081178255604051909182917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3506000805460ff60a01b1916905560018055614868806100726000396000f3fe60806040523480156200001157600080fd5b5060043610620002cd5760003560e01c806384cdd9bc1162000185578063c4db7fa011620000df578063e25aa5fa1162000092578063e25aa5fa146200067d578063e6ab28061462000687578063efeecb51146200069e578063f2fde38b14620006a7578063f3de03621462000390578063fe49abe314620006be57600080fd5b8063c4db7fa01462000631578063ccfc2e8d146200063b578063d41f65681462000652578063d46300fd146200065c578063d4b0de2f1462000605578063df3ed68d146200066657600080fd5b8063a1dc90311162000138578063a1dc903114620005cb578063a95b089f14620005d5578063aa6ca80814620005ec578063ab3d85441462000605578063ab5ac0611462000611578063c00c125c146200061a57600080fd5b806384cdd9bc14620005465780638554a7d4146200055d5780638da5cb5b146200057457806391695586146200058657806391ceb3eb146200059d57806398899f4014620005b457600080fd5b80634d49e87d11620002375780636999b37711620001ea5780636999b37714620004de578063715018a614620004f25780637c61e56114620004fc5780638214f5a4146200051357806382b8660014620005255780638456cb59146200053c57600080fd5b80634d49e87d14620003ee578063593d132c14620004055780635b65b9ab146200041c5780635c975abb14620004335780635fd65f0f146200045157806366c0bd2414620004c757600080fd5b806331cd52b0116200029057806331cd52b014620003795780633969841514620003905780633e3a1560146200039d5780633ed4c67814620003b45780633f4ba83a14620003cd5780634a1b0d5714620003d757600080fd5b806304bc3b1c14620002d257806306e9481c146200030f5780630ba8195914620003295780630d43e8ad146200033357806318f52ce21462000360575b600080fd5b620002f8620002e336600462002c36565b60126020526000908152604090205460ff1681565b60405160ff90911681526020015b60405180910390f35b6200031a6201518081565b60405190815260200162000306565b6200031a620006c8565b60105462000347906001600160a01b031681565b6040516001600160a01b03909116815260200162000306565b6200036a62000758565b604051620003069190620031bc565b6200036a6200038a36600462002f5a565b62000893565b6200031a6402540be40081565b6200031a620003ae36600462002ffa565b62000990565b620003cb620003c536600462002c36565b62000aba565b005b620003cb62000b82565b6200031a620003e836600462002c36565b62000bbb565b6200031a620003ff36600462002ed2565b62000bd0565b620003cb6200041636600462002fac565b62000cdf565b620003cb6200042d36600462002fce565b62000fa3565b600054600160a01b900460ff16604051901515815260200162000306565b600454600754600854600954600a54600b54600c54600d5462000481976001600160a01b03169695949392919088565b604080516001600160a01b0390991689526020890197909752958701949094526060860192909252608085015260a084015260c083015260e08201526101000162000306565b620002f8620004d836600462002c36565b620010fa565b60115462000347906001600160a01b031681565b620003cb62001196565b6200036a6200050d36600462002c53565b6200120d565b6004546001600160a01b031662000347565b620003476200053636600462003037565b620012b8565b620003cb620012fd565b6200031a6200055736600462002ed2565b62001334565b6200031a6200056e36600462003037565b620013f0565b6000546001600160a01b031662000347565b6200031a6200059736600462003094565b62001483565b6200031a620005ae36600462003037565b620015b5565b6200031a620005c536600462002c7f565b620015f0565b6200036a620016a2565b6200031a620005e636600462003054565b620016fe565b620005f662001752565b6040516200030691906200316d565b6200031a6305f5e10081565b6200031a600a81565b620003cb6200062b36600462002c53565b620017b8565b620003cb6200187e565b620003cb6200064c36600462002c36565b620019c9565b6200036a62001a8b565b6200031a62001ae6565b620003cb6200067736600462002cbf565b62001b22565b6200031a62002210565b6200031a6200069836600462002dae565b6200224c565b6003546200031a565b620003cb620006b836600462002c36565b6200228f565b620003cb6200237e565b60405163da2a54b160e01b815260036004820152600090737e812ca56574ed578640daedfe2cb3ef93937ee99063da2a54b1906024015b60206040518083038186803b1580156200071857600080fd5b505af41580156200072d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000753919062002f41565b905090565b6003546060908067ffffffffffffffff8111156200078657634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015620007b0578160200160208202803683370190505b50915060005b818110156200088e57604051632c08163160e21b81526003600482015260248101829052737e812ca56574ed578640daedfe2cb3ef93937ee99063b02058c49060440160206040518083038186803b1580156200081257600080fd5b505af415801562000827573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200084d919062002f41565b8382815181106200086e57634e487b7160e01b600052603260045260246000fd5b602090810291909101015280620008858162003595565b915050620007b6565b505090565b606060026001541415620008c45760405162461bcd60e51b8152600401620008bb90620032bd565b60405180910390fd5b60026001558142811015620008ed5760405162461bcd60e51b8152600401620008bb906200329c565b6040516332751fb560e21b8152737e812ca56574ed578640daedfe2cb3ef93937ee99063c9d47ed4906200092b906003908990899060040162003369565b60006040518083038186803b1580156200094457600080fd5b505af415801562000959573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000983919081019062002e36565b6001805595945050505050565b600060026001541415620009b85760405162461bcd60e51b8152600401620008bb90620032bd565b6002600155600054600160a01b900460ff1615620009ea5760405162461bcd60e51b8152600401620008bb906200323d565b818042111562000a0e5760405162461bcd60e51b8152600401620008bb906200329c565b60405163db41b10b60e01b8152600360048201526024810187905260ff8616604482015260648101859052737e812ca56574ed578640daedfe2cb3ef93937ee99063db41b10b9060840160206040518083038186803b15801562000a7157600080fd5b505af415801562000a86573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000aac919062002f41565b600180559695505050505050565b6000546001600160a01b0316331462000ae75760405162461bcd60e51b8152600401620008bb9062003267565b6001600160a01b03811662000b2d5760405162461bcd60e51b815260206004820152600b60248201526a7a65726f4164647265737360a81b6044820152606401620008bb565b601180546001600160a01b0319166001600160a01b0383169081179091556040519081527f4c3f3b9852ccceadd50f16518f348e2624c8f0240acdd5bc81911c0fba83ec67906020015b60405180910390a150565b6000546001600160a01b0316331462000baf5760405162461bcd60e51b8152600401620008bb9062003267565b62000bb96200256f565b565b600062000bca6003836200260e565b92915050565b60008054600160a01b900460ff161562000bfe5760405162461bcd60e51b8152600401620008bb906200323d565b6002600154141562000c245760405162461bcd60e51b8152600401620008bb90620032bd565b6002600155814281101562000c4d5760405162461bcd60e51b8152600401620008bb906200329c565b604051636601432f60e01b8152737e812ca56574ed578640daedfe2cb3ef93937ee990636601432f9062000c8b90600390899089906004016200333e565b60206040518083038186803b15801562000ca457600080fd5b505af415801562000cb9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000983919062002f41565b6000546001600160a01b0316331462000d0c5760405162461bcd60e51b8152600401620008bb9062003267565b600b5462000d1e9062015180620033e5565b42101562000d5d5760405162461bcd60e51b815260206004820152600b60248201526a3c2072616d7044656c617960a81b6044820152606401620008bb565b62000d6c6201518042620033e5565b81101562000dad5760405162461bcd60e51b815260206004820152600d60248201526c3c206d696e52616d7054696d6560981b6044820152606401620008bb565b81600010801562000dc257506402540be40082105b62000dfd5760405162461bcd60e51b815260206004820152600a6024820152696f75744f6652616e676560b01b6044820152606401620008bb565b60405163da2a54b160e01b815260036004820152600090737e812ca56574ed578640daedfe2cb3ef93937ee99063da2a54b19060240160206040518083038186803b15801562000e4c57600080fd5b505af415801562000e61573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000e87919062002f41565b9050600062000e9860648562003526565b90508181101562000ef5578162000eb1600a8362003526565b101562000eef5760405162461bcd60e51b815260206004820152600b60248201526a3e206d61784368616e676560a81b6044820152606401620008bb565b62000f41565b62000f02600a8362003526565b81111562000f415760405162461bcd60e51b815260206004820152600b60248201526a3e206d61784368616e676560a81b6044820152606401620008bb565b6009829055600a81905542600b819055600c84905560408051848152602081018490528082019290925260608201859052517fa2b71ec6df949300b59aab36b55e189697b750119dd349fcfa8c0f779e83c2549181900360800190a150505050565b6000546001600160a01b0316331462000fd05760405162461bcd60e51b8152600401620008bb9062003267565b6305f5e100831115620010155760405162461bcd60e51b815260206004820152600c60248201526b3e206d61785377617046656560a01b6044820152606401620008bb565b6402540be4008211156200105c5760405162461bcd60e51b815260206004820152600d60248201526c3e206d617841646d696e46656560981b6044820152606401620008bb565b6305f5e100811115620010a55760405162461bcd60e51b815260206004820152601060248201526f3e206d6178576974686472617746656560801b6044820152606401620008bb565b60088290556007839055600d81905560408051848152602081018490529081018290527fcfca96e0fef3432146913b2a5a2268a55d3f475fe057e7ffde1082b77693f4f39060600160405180910390a1505050565b6001600160a01b0381166000818152601260205260409020546003805460ff9092169291839081106200113d57634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b031614620011915760405162461bcd60e51b815260206004820152600d60248201526c1d1bdad95b939bdd119bdd5b99609a1b6044820152606401620008bb565b919050565b6000546001600160a01b03163314620011c35760405162461bcd60e51b8152600401620008bb9062003267565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b60405163a93f034160e01b8152600360048201526001600160a01b038316602482015260448101829052606090737e812ca56574ed578640daedfe2cb3ef93937ee99063a93f03419060640160006040518083038186803b1580156200127257600080fd5b505af415801562001287573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620012b1919081019062002e36565b9392505050565b600060036000018260ff1681548110620012e257634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b031692915050565b6000546001600160a01b031633146200132a5760405162461bcd60e51b8152600401620008bb9062003267565b62000bb9620026c8565b6000600260015414156200135c5760405162461bcd60e51b8152600401620008bb90620032bd565b6002600155600054600160a01b900460ff16156200138e5760405162461bcd60e51b8152600401620008bb906200323d565b8180421115620013b25760405162461bcd60e51b8152600401620008bb906200329c565b60405163e92ad71560e01b8152737e812ca56574ed578640daedfe2cb3ef93937ee99063e92ad7159062000c8b90600390899089906004016200333e565b604051632c08163160e21b81526003600482015260ff82166024820152600090737e812ca56574ed578640daedfe2cb3ef93937ee99063b02058c49060440160206040518083038186803b1580156200144857600080fd5b505af41580156200145d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000bca919062002f41565b60008054600160a01b900460ff1615620014b15760405162461bcd60e51b8152600401620008bb906200323d565b60026001541415620014d75760405162461bcd60e51b8152600401620008bb90620032bd565b60026001558142811015620015005760405162461bcd60e51b8152600401620008bb906200329c565b60405163080e7d2960e41b81526003600482015260ff8089166024830152871660448201526064810186905260848101859052737e812ca56574ed578640daedfe2cb3ef93937ee9906380e7d2909060a40160206040518083038186803b1580156200156b57600080fd5b505af415801562001580573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620015a6919062002f41565b60018055979650505050505050565b6000600380018260ff1681548110620015de57634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050919050565b604051632a4f48ef60e01b8152600360048201526001600160a01b03841660248201526044810183905260ff82166064820152600090737e812ca56574ed578640daedfe2cb3ef93937ee990632a4f48ef906084015b60206040518083038186803b1580156200165f57600080fd5b505af415801562001674573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200169a919062002f41565b949350505050565b606060038001805480602002602001604051908101604052809291908181526020018280548015620016f457602002820191906000526020600020905b815481526020019060010190808311620016df575b5050505050905090565b6040516373ee2be560e11b81526003600482015260ff80851660248301528316604482015260648101829052600090737e812ca56574ed578640daedfe2cb3ef93937ee99063e7dc57ca9060840162001646565b60606003600001805480602002602001604051908101604052809291908181526020018280548015620016f457602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831162001790575050505050905090565b6004546001600160a01b03163314620017ff5760405162461bcd60e51b815260206004820152600860248201526710b6382a37b5b2b760c11b6044820152606401620008bb565b60405163699638a560e01b8152600360048201526001600160a01b038316602482015260448101829052737e812ca56574ed578640daedfe2cb3ef93937ee99063699638a59060640160006040518083038186803b1580156200186157600080fd5b505af415801562001876573d6000803e3d6000fd5b505050505050565b6000546001600160a01b03163314620018ab5760405162461bcd60e51b8152600401620008bb9062003267565b600c544210620018ef5760405162461bcd60e51b815260206004820152600e60248201526d185b1c9958591e54dd1bdc1c195960921b6044820152606401620008bb565b60405163329b20ed60e01b815260036004820152600090737e812ca56574ed578640daedfe2cb3ef93937ee99063329b20ed9060240160206040518083038186803b1580156200193e57600080fd5b505af415801562001953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001979919062002f41565b6009819055600a81905542600b819055600c8190556040519192507f46e22fb3709ad289f62ce63d469248536dbc78d82b84a3d7e74ad606dc2019389162000b7791848252602082015260400190565b6000546001600160a01b03163314620019f65760405162461bcd60e51b8152600401620008bb9062003267565b6001600160a01b03811662001a3c5760405162461bcd60e51b815260206004820152600b60248201526a7a65726f4164647265737360a81b6044820152606401620008bb565b601080546001600160a01b0319166001600160a01b0383169081179091556040519081527fae5a12c29e496b092467a620746b9eaf4e0e231a631a4370c233b1fac38e8e269060200162000b77565b60606003600201805480602002602001604051908101604052809291908181526020018280548015620016f45760200282019190600052602060002090815481526020019060010190808311620016df575050505050905090565b60405163329b20ed60e01b815260036004820152600090737e812ca56574ed578640daedfe2cb3ef93937ee99063329b20ed90602401620006ff565b6000546001600160a01b0316331462001b4f5760405162461bcd60e51b8152600401620008bb9062003267565b600254610100900460ff168062001b69575060025460ff16155b62001bce5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401620008bb565b600254610100900460ff1615801562001bf1576002805461ffff19166101011790555b88518a511462001c445760405162461bcd60e51b815260206004820152601d60248201527f636f696e734c656e67746820213d20646563696d616c734c656e6774680000006044820152606401620008bb565b6001600160a01b03821662001c955760405162461bcd60e51b81526020600482015260166024820152756665654469737472696275746f72203d20656d70747960501b6044820152606401620008bb565b895160008167ffffffffffffffff81111562001cc157634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801562001ceb578160200160208202803683370190505b50905060008267ffffffffffffffff81111562001d1857634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801562001d42578160200160208202803683370190505b50905060005b8381101562001f9e5760006001600160a01b03168e828151811062001d7d57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316141562001dd45760405162461bcd60e51b8152602060048201526013602482015272696e76616c6964546f6b656e4164647265737360681b6044820152606401620008bb565b60128d828151811062001df757634e487b7160e01b600052603260045260246000fd5b602002602001015160ff16111562001e445760405162461bcd60e51b815260206004820152600f60248201526e696e76616c6964446563696d616c7360881b6044820152606401620008bb565b8c818151811062001e6557634e487b7160e01b600052603260045260246000fd5b602002602001015160ff16601262001e7e919062003548565b62001e8b90600a6200346a565b83828151811062001eac57634e487b7160e01b600052603260045260246000fd5b6020026020010181815250508d818151811062001ed957634e487b7160e01b600052603260045260246000fd5b602002602001015182828151811062001f0257634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b031681525050806012600084848151811062001f4857634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908360ff160217905550808062001f959062003595565b91505062001d48565b506402540be400891062001fde5760405162461bcd60e51b81526020600482015260066024820152653e206d61784160d01b6044820152606401620008bb565b6305f5e100881115620020235760405162461bcd60e51b815260206004820152600c60248201526b3e206d61785377617046656560a01b6044820152606401620008bb565b6402540be4008711156200206a5760405162461bcd60e51b815260206004820152600d60248201526c3e206d617841646d696e46656560981b6044820152606401620008bb565b6305f5e100861115620020b35760405162461bcd60e51b815260206004820152601060248201526f3e206d6178576974686472617746656560801b6044820152606401620008bb565b8a8a604051620020c3906200297c565b620020d09291906200320b565b604051809103906000f080158015620020ed573d6000803e3d6000fd5b50600480546001600160a01b0319166001600160a01b03929092169190911790558267ffffffffffffffff8111156200213657634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801562002160578160200160208202803683370190505b50805162002177916006916020909101906200298a565b5081516200218d9060059060208501906200298a565b508051620021a3906003906020840190620029da565b50620021b160648a62003526565b600955620021c160648a62003526565b600a5550505060078590556008849055600d839055601080546001600160a01b0319166001600160a01b038416179055801562002204576002805461ff00191690555b50505050505050505050565b604051632946144b60e21b815260036004820152600090737e812ca56574ed578640daedfe2cb3ef93937ee99063a518512c90602401620006ff565b604051631ce8027360e31b8152600090737e812ca56574ed578640daedfe2cb3ef93937ee99063e7401398906200164690600390889088908890600401620032f4565b6000546001600160a01b03163314620022bc5760405162461bcd60e51b8152600401620008bb9062003267565b6001600160a01b038116620023235760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401620008bb565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6011546001600160a01b0316331480620023a257506000546001600160a01b031633145b620023e85760405162461bcd60e51b815260206004820152601560248201527410b332b2a1b7b73a3937b63632b927b927bbb732b960591b6044820152606401620008bb565b60005b6003548110156200256c576000600360000182815481106200241d57634e487b7160e01b600052603260045260246000fd5b6000918252602082200154600680546001600160a01b03909216935090849081106200245957634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546040516370a0823160e01b81523060048201526001600160a01b038416906370a082319060240160206040518083038186803b158015620024a557600080fd5b505afa158015620024ba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620024e0919062002f41565b620024ec919062003548565b90508015620025545760105462002511906001600160a01b0384811691168362002731565b604080516001600160a01b0384168152602081018390527fee3859efa95e525bc2bcb149b51b60a8bb4e89c647392d9d4112e03c3e73bdd6910160405180910390a15b50508080620025639062003595565b915050620023eb565b50565b600054600160a01b900460ff16620025c15760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401620008bb565b6000805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b0381166000908152600b8301602052604081205481906200263a906224ea00620033e5565b905042811115620026be57600062002653428362003548565b6001600160a01b0385166000908152600c87016020526040902054600a8701549192506402540be400916224ea0091849162002690919062003526565b6200269c919062003526565b620026a8919062003400565b620026b4919062003400565b9250505062000bca565b5060009392505050565b600054600160a01b900460ff1615620026f55760405162461bcd60e51b8152600401620008bb906200323d565b6000805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258620025f13390565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052620027859084906200278a565b505050565b6000620027e1826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316620028639092919063ffffffff16565b80519091501562002785578080602001905181019062002802919062002f22565b620027855760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401620008bb565b60606200169a848460008585843b620028bf5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620008bb565b600080866001600160a01b03168587604051620028dd91906200314f565b60006040518083038185875af1925050503d80600081146200291c576040519150601f19603f3d011682016040523d82523d6000602084013e62002921565b606091505b5091509150620029338282866200293e565b979650505050505050565b606083156200294f575081620012b1565b825115620029605782518084602001fd5b8160405162461bcd60e51b8152600401620008bb9190620031f6565b61124480620035ef83390190565b828054828255906000526020600020908101928215620029c8579160200282015b82811115620029c8578251825591602001919060010190620029ab565b50620029d692915062002a32565b5090565b828054828255906000526020600020908101928215620029c8579160200282015b82811115620029c857825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190620029fb565b5b80821115620029d6576000815560010162002a33565b80356001600160a01b03811681146200119157600080fd5b600082601f83011262002a72578081fd5b8135602062002a8b62002a8583620033be565b6200338a565b80838252828201915082860187848660051b890101111562002aab578586fd5b855b8581101562002ad45762002ac18262002a49565b8452928401929084019060010162002aad565b5090979650505050505050565b600082601f83011262002af2578081fd5b8135602062002b0562002a8583620033be565b80838252828201915082860187848660051b890101111562002b25578586fd5b855b8581101562002ad45781358452928401929084019060010162002b27565b600082601f83011262002b56578081fd5b8135602062002b6962002a8583620033be565b80838252828201915082860187848660051b890101111562002b89578586fd5b855b8581101562002ad45762002b9f8262002c24565b8452928401929084019060010162002b8b565b600082601f83011262002bc3578081fd5b813567ffffffffffffffff81111562002be05762002be0620035c9565b62002bf5601f8201601f19166020016200338a565b81815284602083860101111562002c0a578283fd5b816020850160208301379081016020019190915292915050565b803560ff811681146200119157600080fd5b60006020828403121562002c48578081fd5b620012b18262002a49565b6000806040838503121562002c66578081fd5b62002c718362002a49565b946020939093013593505050565b60008060006060848603121562002c94578081fd5b62002c9f8462002a49565b92506020840135915062002cb66040850162002c24565b90509250925092565b60008060008060008060008060006101208a8c03121562002cde578485fd5b893567ffffffffffffffff8082111562002cf6578687fd5b62002d048d838e0162002a61565b9a5060208c013591508082111562002d1a578687fd5b62002d288d838e0162002b45565b995060408c013591508082111562002d3e578687fd5b62002d4c8d838e0162002bb2565b985060608c013591508082111562002d62578687fd5b5062002d718c828d0162002bb2565b96505060808a0135945060a08a0135935060c08a0135925060e08a0135915062002d9f6101008b0162002a49565b90509295985092959850929598565b60008060006040848603121562002dc3578081fd5b833567ffffffffffffffff8082111562002ddb578283fd5b818601915086601f83011262002def578283fd5b81358181111562002dfe578384fd5b8760208260051b850101111562002e13578384fd5b6020928301955093505084013562002e2b81620035df565b809150509250925092565b6000602080838503121562002e49578182fd5b825167ffffffffffffffff81111562002e60578283fd5b8301601f8101851362002e71578283fd5b805162002e8262002a8582620033be565b80828252848201915084840188868560051b870101111562002ea2578687fd5b8694505b8385101562002ec657805183526001949094019391850191850162002ea6565b50979650505050505050565b60008060006060848603121562002ee7578081fd5b833567ffffffffffffffff81111562002efe578182fd5b62002f0c8682870162002ae1565b9660208601359650604090950135949350505050565b60006020828403121562002f34578081fd5b8151620012b181620035df565b60006020828403121562002f53578081fd5b5051919050565b60008060006060848603121562002f6f578081fd5b83359250602084013567ffffffffffffffff81111562002f8d578182fd5b62002f9b8682870162002ae1565b925050604084013590509250925092565b6000806040838503121562002fbf578182fd5b50508035926020909101359150565b60008060006060848603121562002fe3578081fd5b505081359360208301359350604090920135919050565b6000806000806080858703121562003010578182fd5b84359350620030226020860162002c24565b93969395505050506040820135916060013590565b60006020828403121562003049578081fd5b620012b18262002c24565b60008060006060848603121562003069578081fd5b620030748462002c24565b9250620030846020850162002c24565b9150604084013590509250925092565b600080600080600060a08688031215620030ac578283fd5b620030b78662002c24565b9450620030c76020870162002c24565b94979496505050506040830135926060810135926080909101359150565b6000815180845260208085019450808401835b838110156200311657815187529582019590820190600101620030f8565b509495945050505050565b600081518084526200313b81602086016020860162003562565b601f01601f19169290920160200192915050565b600082516200316381846020870162003562565b9190910192915050565b6020808252825182820181905260009190848201906040850190845b81811015620031b05783516001600160a01b03168352928401929184019160010162003189565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015620031b057835183529284019291840191600101620031d8565b602081526000620012b1602083018462003121565b60408152600062003220604083018562003121565b828103602084015262003234818562003121565b95945050505050565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252600790820152661d1a5b595bdd5d60ca1b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b848152606060208201819052810183905260006001600160fb1b038411156200331b578081fd5b8360051b8086608085013782016080019081529115156040909101529392505050565b838152606060208201526000620033596060830185620030e5565b9050826040830152949350505050565b838152826020820152606060408201526000620032346060830184620030e5565b604051601f8201601f1916810167ffffffffffffffff81118282101715620033b657620033b6620035c9565b604052919050565b600067ffffffffffffffff821115620033db57620033db620035c9565b5060051b60200190565b60008219821115620033fb57620033fb620035b3565b500190565b6000826200341c57634e487b7160e01b81526012600452602481fd5b500490565b600181815b8085111562003462578160001904821115620034465762003446620035b3565b808516156200345457918102915b93841c939080029062003426565b509250929050565b6000620012b18383600082620034835750600162000bca565b81620034925750600062000bca565b8160018114620034ab5760028114620034b657620034d6565b600191505062000bca565b60ff841115620034ca57620034ca620035b3565b50506001821b62000bca565b5060208310610133831016604e8410600b8410161715620034fb575081810a62000bca565b62003507838362003421565b80600019048211156200351e576200351e620035b3565b029392505050565b6000816000190483118215151615620035435762003543620035b3565b500290565b6000828210156200355d576200355d620035b3565b500390565b60005b838110156200357f57818101518382015260200162003565565b838111156200358f576000848401525b50505050565b6000600019821415620035ac57620035ac620035b3565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b80151581146200256c57600080fdfe60806040523480156200001157600080fd5b50604051620012443803806200124483398101604081905262000034916200021b565b600080546001600160a01b03191633908117825560405184928492918291907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35081516200008e906004906020850190620000c2565b508051620000a4906005906020840190620000c2565b5050600680546001600160a01b0319163317905550620002d5915050565b828054620000d09062000282565b90600052602060002090601f016020900481019282620000f457600085556200013f565b82601f106200010f57805160ff19168380011785556200013f565b828001600101855582156200013f579182015b828111156200013f57825182559160200191906001019062000122565b506200014d92915062000151565b5090565b5b808211156200014d576000815560010162000152565b600082601f83011262000179578081fd5b81516001600160401b0380821115620001965762000196620002bf565b604051601f8301601f19908116603f01168101908282118183101715620001c157620001c1620002bf565b81604052838152602092508683858801011115620001dd578485fd5b8491505b83821015620002005785820183015181830184015290820190620001e1565b838211156200021157848385830101525b9695505050505050565b600080604083850312156200022e578182fd5b82516001600160401b038082111562000245578384fd5b620002538683870162000168565b9350602085015191508082111562000269578283fd5b50620002788582860162000168565b9150509250929050565b600181811c908216806200029757607f821691505b60208210811415620002b957634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052604160045260246000fd5b610f5f80620002e56000396000f3fe608060405234801561001057600080fd5b50600436106101165760003560e01c8063715018a6116100a257806395d89b411161007157806395d89b411461024b578063a457c2d714610253578063a9059cbb14610266578063dd62ed3e14610279578063f2fde38b146102b257600080fd5b8063715018a6146101f457806379cc6790146101fc5780638119c0651461020f5780638da5cb5b1461023a57600080fd5b8063313ce567116100e9578063313ce56714610181578063395093511461019057806340c10f19146101a357806342966c68146101b857806370a08231146101cb57600080fd5b806306fdde031461011b578063095ea7b31461013957806318160ddd1461015c57806323b872dd1461016e575b600080fd5b6101236102c5565b6040516101309190610e21565b60405180910390f35b61014c610147366004610de0565b610357565b6040519015158152602001610130565b6003545b604051908152602001610130565b61014c61017c366004610da5565b61036d565b60405160128152602001610130565b61014c61019e366004610de0565b610423565b6101b66101b1366004610de0565b61045a565b005b6101b66101c6366004610e09565b6104d3565b6101606101d9366004610d52565b6001600160a01b031660009081526001602052604090205490565b6101b66104e0565b6101b661020a366004610de0565b610554565b600654610222906001600160a01b031681565b6040516001600160a01b039091168152602001610130565b6000546001600160a01b0316610222565b6101236105dc565b61014c610261366004610de0565b6105eb565b61014c610274366004610de0565b610686565b610160610287366004610d73565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b6101b66102c0366004610d52565b610693565b6060600480546102d490610ed8565b80601f016020809104026020016040519081016040528092919081815260200182805461030090610ed8565b801561034d5780601f106103225761010080835404028352916020019161034d565b820191906000526020600020905b81548152906001019060200180831161033057829003601f168201915b5050505050905090565b600061036433848461077d565b50600192915050565b600061037a8484846108a2565b6001600160a01b0384166000908152600260209081526040808320338452909152902054828110156104045760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b60648201526084015b60405180910390fd5b61041885336104138685610ec1565b61077d565b506001949350505050565b3360008181526002602090815260408083206001600160a01b03871684529091528120549091610364918590610413908690610ea9565b6000546001600160a01b031633146104845760405162461bcd60e51b81526004016103fb90610e74565b600081116104c55760405162461bcd60e51b815260206004820152600e60248201526d1e995c9bd35a5b9d105b5bdd5b9d60921b60448201526064016103fb565b6104cf8282610a85565b5050565b6104dd3382610b70565b50565b6000546001600160a01b0316331461050a5760405162461bcd60e51b81526004016103fb90610e74565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b60006105608333610287565b9050818110156105be5760405162461bcd60e51b8152602060048201526024808201527f45524332303a206275726e20616d6f756e74206578636565647320616c6c6f77604482015263616e636560e01b60648201526084016103fb565b6105cd83336104138585610ec1565b6105d78383610b70565b505050565b6060600580546102d490610ed8565b3360009081526002602090815260408083206001600160a01b03861684529091528120548281101561066d5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084016103fb565b61067c33856104138685610ec1565b5060019392505050565b60006103643384846108a2565b6000546001600160a01b031633146106bd5760405162461bcd60e51b81526004016103fb90610e74565b6001600160a01b0381166107225760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016103fb565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0383166107df5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016103fb565b6001600160a01b0382166108405760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016103fb565b6001600160a01b0383811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6001600160a01b0383166109065760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016103fb565b6001600160a01b0382166109685760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016103fb565b610973838383610ccb565b6001600160a01b038316600090815260016020526040902054818110156109eb5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016103fb565b6109f58282610ec1565b6001600160a01b038086166000908152600160205260408082209390935590851681529081208054849290610a2b908490610ea9565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610a7791815260200190565b60405180910390a350505050565b6001600160a01b038216610adb5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016103fb565b610ae760008383610ccb565b8060036000828254610af99190610ea9565b90915550506001600160a01b03821660009081526001602052604081208054839290610b26908490610ea9565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6001600160a01b038216610bd05760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b60648201526084016103fb565b610bdc82600083610ccb565b6001600160a01b03821660009081526001602052604090205481811015610c505760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b60648201526084016103fb565b610c5a8282610ec1565b6001600160a01b03841660009081526001602052604081209190915560038054849290610c88908490610ec1565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610895565b600654604051633003049760e21b81526001600160a01b038481166004830152602482018490529091169063c00c125c90604401600060405180830381600087803b158015610d1957600080fd5b505af1158015610d2d573d6000803e3d6000fd5b50505050505050565b80356001600160a01b0381168114610d4d57600080fd5b919050565b600060208284031215610d63578081fd5b610d6c82610d36565b9392505050565b60008060408385031215610d85578081fd5b610d8e83610d36565b9150610d9c60208401610d36565b90509250929050565b600080600060608486031215610db9578081fd5b610dc284610d36565b9250610dd060208501610d36565b9150604084013590509250925092565b60008060408385031215610df2578182fd5b610dfb83610d36565b946020939093013593505050565b600060208284031215610e1a578081fd5b5035919050565b6000602080835283518082850152825b81811015610e4d57858101830151858201604001528201610e31565b81811115610e5e5783604083870101525b50601f01601f1916929092016040019392505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60008219821115610ebc57610ebc610f13565b500190565b600082821015610ed357610ed3610f13565b500390565b600181811c90821680610eec57607f821691505b60208210811415610f0d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fdfea264697066735822122054d2d632431a128fb66854fe890a2ec0166d749d10fbd21e9585d3cbfc9551c064736f6c63430008040033a264697066735822122088e6e6b51718287bd3fd106f820ff5cd9c072c769afed263493316cac7968ed064736f6c63430008040033
Deployed Bytecode
0x60806040523480156200001157600080fd5b5060043610620002cd5760003560e01c806384cdd9bc1162000185578063c4db7fa011620000df578063e25aa5fa1162000092578063e25aa5fa146200067d578063e6ab28061462000687578063efeecb51146200069e578063f2fde38b14620006a7578063f3de03621462000390578063fe49abe314620006be57600080fd5b8063c4db7fa01462000631578063ccfc2e8d146200063b578063d41f65681462000652578063d46300fd146200065c578063d4b0de2f1462000605578063df3ed68d146200066657600080fd5b8063a1dc90311162000138578063a1dc903114620005cb578063a95b089f14620005d5578063aa6ca80814620005ec578063ab3d85441462000605578063ab5ac0611462000611578063c00c125c146200061a57600080fd5b806384cdd9bc14620005465780638554a7d4146200055d5780638da5cb5b146200057457806391695586146200058657806391ceb3eb146200059d57806398899f4014620005b457600080fd5b80634d49e87d11620002375780636999b37711620001ea5780636999b37714620004de578063715018a614620004f25780637c61e56114620004fc5780638214f5a4146200051357806382b8660014620005255780638456cb59146200053c57600080fd5b80634d49e87d14620003ee578063593d132c14620004055780635b65b9ab146200041c5780635c975abb14620004335780635fd65f0f146200045157806366c0bd2414620004c757600080fd5b806331cd52b0116200029057806331cd52b014620003795780633969841514620003905780633e3a1560146200039d5780633ed4c67814620003b45780633f4ba83a14620003cd5780634a1b0d5714620003d757600080fd5b806304bc3b1c14620002d257806306e9481c146200030f5780630ba8195914620003295780630d43e8ad146200033357806318f52ce21462000360575b600080fd5b620002f8620002e336600462002c36565b60126020526000908152604090205460ff1681565b60405160ff90911681526020015b60405180910390f35b6200031a6201518081565b60405190815260200162000306565b6200031a620006c8565b60105462000347906001600160a01b031681565b6040516001600160a01b03909116815260200162000306565b6200036a62000758565b604051620003069190620031bc565b6200036a6200038a36600462002f5a565b62000893565b6200031a6402540be40081565b6200031a620003ae36600462002ffa565b62000990565b620003cb620003c536600462002c36565b62000aba565b005b620003cb62000b82565b6200031a620003e836600462002c36565b62000bbb565b6200031a620003ff36600462002ed2565b62000bd0565b620003cb6200041636600462002fac565b62000cdf565b620003cb6200042d36600462002fce565b62000fa3565b600054600160a01b900460ff16604051901515815260200162000306565b600454600754600854600954600a54600b54600c54600d5462000481976001600160a01b03169695949392919088565b604080516001600160a01b0390991689526020890197909752958701949094526060860192909252608085015260a084015260c083015260e08201526101000162000306565b620002f8620004d836600462002c36565b620010fa565b60115462000347906001600160a01b031681565b620003cb62001196565b6200036a6200050d36600462002c53565b6200120d565b6004546001600160a01b031662000347565b620003476200053636600462003037565b620012b8565b620003cb620012fd565b6200031a6200055736600462002ed2565b62001334565b6200031a6200056e36600462003037565b620013f0565b6000546001600160a01b031662000347565b6200031a6200059736600462003094565b62001483565b6200031a620005ae36600462003037565b620015b5565b6200031a620005c536600462002c7f565b620015f0565b6200036a620016a2565b6200031a620005e636600462003054565b620016fe565b620005f662001752565b6040516200030691906200316d565b6200031a6305f5e10081565b6200031a600a81565b620003cb6200062b36600462002c53565b620017b8565b620003cb6200187e565b620003cb6200064c36600462002c36565b620019c9565b6200036a62001a8b565b6200031a62001ae6565b620003cb6200067736600462002cbf565b62001b22565b6200031a62002210565b6200031a6200069836600462002dae565b6200224c565b6003546200031a565b620003cb620006b836600462002c36565b6200228f565b620003cb6200237e565b60405163da2a54b160e01b815260036004820152600090737e812ca56574ed578640daedfe2cb3ef93937ee99063da2a54b1906024015b60206040518083038186803b1580156200071857600080fd5b505af41580156200072d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000753919062002f41565b905090565b6003546060908067ffffffffffffffff8111156200078657634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015620007b0578160200160208202803683370190505b50915060005b818110156200088e57604051632c08163160e21b81526003600482015260248101829052737e812ca56574ed578640daedfe2cb3ef93937ee99063b02058c49060440160206040518083038186803b1580156200081257600080fd5b505af415801562000827573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200084d919062002f41565b8382815181106200086e57634e487b7160e01b600052603260045260246000fd5b602090810291909101015280620008858162003595565b915050620007b6565b505090565b606060026001541415620008c45760405162461bcd60e51b8152600401620008bb90620032bd565b60405180910390fd5b60026001558142811015620008ed5760405162461bcd60e51b8152600401620008bb906200329c565b6040516332751fb560e21b8152737e812ca56574ed578640daedfe2cb3ef93937ee99063c9d47ed4906200092b906003908990899060040162003369565b60006040518083038186803b1580156200094457600080fd5b505af415801562000959573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000983919081019062002e36565b6001805595945050505050565b600060026001541415620009b85760405162461bcd60e51b8152600401620008bb90620032bd565b6002600155600054600160a01b900460ff1615620009ea5760405162461bcd60e51b8152600401620008bb906200323d565b818042111562000a0e5760405162461bcd60e51b8152600401620008bb906200329c565b60405163db41b10b60e01b8152600360048201526024810187905260ff8616604482015260648101859052737e812ca56574ed578640daedfe2cb3ef93937ee99063db41b10b9060840160206040518083038186803b15801562000a7157600080fd5b505af415801562000a86573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000aac919062002f41565b600180559695505050505050565b6000546001600160a01b0316331462000ae75760405162461bcd60e51b8152600401620008bb9062003267565b6001600160a01b03811662000b2d5760405162461bcd60e51b815260206004820152600b60248201526a7a65726f4164647265737360a81b6044820152606401620008bb565b601180546001600160a01b0319166001600160a01b0383169081179091556040519081527f4c3f3b9852ccceadd50f16518f348e2624c8f0240acdd5bc81911c0fba83ec67906020015b60405180910390a150565b6000546001600160a01b0316331462000baf5760405162461bcd60e51b8152600401620008bb9062003267565b62000bb96200256f565b565b600062000bca6003836200260e565b92915050565b60008054600160a01b900460ff161562000bfe5760405162461bcd60e51b8152600401620008bb906200323d565b6002600154141562000c245760405162461bcd60e51b8152600401620008bb90620032bd565b6002600155814281101562000c4d5760405162461bcd60e51b8152600401620008bb906200329c565b604051636601432f60e01b8152737e812ca56574ed578640daedfe2cb3ef93937ee990636601432f9062000c8b90600390899089906004016200333e565b60206040518083038186803b15801562000ca457600080fd5b505af415801562000cb9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000983919062002f41565b6000546001600160a01b0316331462000d0c5760405162461bcd60e51b8152600401620008bb9062003267565b600b5462000d1e9062015180620033e5565b42101562000d5d5760405162461bcd60e51b815260206004820152600b60248201526a3c2072616d7044656c617960a81b6044820152606401620008bb565b62000d6c6201518042620033e5565b81101562000dad5760405162461bcd60e51b815260206004820152600d60248201526c3c206d696e52616d7054696d6560981b6044820152606401620008bb565b81600010801562000dc257506402540be40082105b62000dfd5760405162461bcd60e51b815260206004820152600a6024820152696f75744f6652616e676560b01b6044820152606401620008bb565b60405163da2a54b160e01b815260036004820152600090737e812ca56574ed578640daedfe2cb3ef93937ee99063da2a54b19060240160206040518083038186803b15801562000e4c57600080fd5b505af415801562000e61573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000e87919062002f41565b9050600062000e9860648562003526565b90508181101562000ef5578162000eb1600a8362003526565b101562000eef5760405162461bcd60e51b815260206004820152600b60248201526a3e206d61784368616e676560a81b6044820152606401620008bb565b62000f41565b62000f02600a8362003526565b81111562000f415760405162461bcd60e51b815260206004820152600b60248201526a3e206d61784368616e676560a81b6044820152606401620008bb565b6009829055600a81905542600b819055600c84905560408051848152602081018490528082019290925260608201859052517fa2b71ec6df949300b59aab36b55e189697b750119dd349fcfa8c0f779e83c2549181900360800190a150505050565b6000546001600160a01b0316331462000fd05760405162461bcd60e51b8152600401620008bb9062003267565b6305f5e100831115620010155760405162461bcd60e51b815260206004820152600c60248201526b3e206d61785377617046656560a01b6044820152606401620008bb565b6402540be4008211156200105c5760405162461bcd60e51b815260206004820152600d60248201526c3e206d617841646d696e46656560981b6044820152606401620008bb565b6305f5e100811115620010a55760405162461bcd60e51b815260206004820152601060248201526f3e206d6178576974686472617746656560801b6044820152606401620008bb565b60088290556007839055600d81905560408051848152602081018490529081018290527fcfca96e0fef3432146913b2a5a2268a55d3f475fe057e7ffde1082b77693f4f39060600160405180910390a1505050565b6001600160a01b0381166000818152601260205260409020546003805460ff9092169291839081106200113d57634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b031614620011915760405162461bcd60e51b815260206004820152600d60248201526c1d1bdad95b939bdd119bdd5b99609a1b6044820152606401620008bb565b919050565b6000546001600160a01b03163314620011c35760405162461bcd60e51b8152600401620008bb9062003267565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b60405163a93f034160e01b8152600360048201526001600160a01b038316602482015260448101829052606090737e812ca56574ed578640daedfe2cb3ef93937ee99063a93f03419060640160006040518083038186803b1580156200127257600080fd5b505af415801562001287573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620012b1919081019062002e36565b9392505050565b600060036000018260ff1681548110620012e257634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b031692915050565b6000546001600160a01b031633146200132a5760405162461bcd60e51b8152600401620008bb9062003267565b62000bb9620026c8565b6000600260015414156200135c5760405162461bcd60e51b8152600401620008bb90620032bd565b6002600155600054600160a01b900460ff16156200138e5760405162461bcd60e51b8152600401620008bb906200323d565b8180421115620013b25760405162461bcd60e51b8152600401620008bb906200329c565b60405163e92ad71560e01b8152737e812ca56574ed578640daedfe2cb3ef93937ee99063e92ad7159062000c8b90600390899089906004016200333e565b604051632c08163160e21b81526003600482015260ff82166024820152600090737e812ca56574ed578640daedfe2cb3ef93937ee99063b02058c49060440160206040518083038186803b1580156200144857600080fd5b505af41580156200145d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000bca919062002f41565b60008054600160a01b900460ff1615620014b15760405162461bcd60e51b8152600401620008bb906200323d565b60026001541415620014d75760405162461bcd60e51b8152600401620008bb90620032bd565b60026001558142811015620015005760405162461bcd60e51b8152600401620008bb906200329c565b60405163080e7d2960e41b81526003600482015260ff8089166024830152871660448201526064810186905260848101859052737e812ca56574ed578640daedfe2cb3ef93937ee9906380e7d2909060a40160206040518083038186803b1580156200156b57600080fd5b505af415801562001580573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620015a6919062002f41565b60018055979650505050505050565b6000600380018260ff1681548110620015de57634e487b7160e01b600052603260045260246000fd5b90600052602060002001549050919050565b604051632a4f48ef60e01b8152600360048201526001600160a01b03841660248201526044810183905260ff82166064820152600090737e812ca56574ed578640daedfe2cb3ef93937ee990632a4f48ef906084015b60206040518083038186803b1580156200165f57600080fd5b505af415801562001674573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200169a919062002f41565b949350505050565b606060038001805480602002602001604051908101604052809291908181526020018280548015620016f457602002820191906000526020600020905b815481526020019060010190808311620016df575b5050505050905090565b6040516373ee2be560e11b81526003600482015260ff80851660248301528316604482015260648101829052600090737e812ca56574ed578640daedfe2cb3ef93937ee99063e7dc57ca9060840162001646565b60606003600001805480602002602001604051908101604052809291908181526020018280548015620016f457602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831162001790575050505050905090565b6004546001600160a01b03163314620017ff5760405162461bcd60e51b815260206004820152600860248201526710b6382a37b5b2b760c11b6044820152606401620008bb565b60405163699638a560e01b8152600360048201526001600160a01b038316602482015260448101829052737e812ca56574ed578640daedfe2cb3ef93937ee99063699638a59060640160006040518083038186803b1580156200186157600080fd5b505af415801562001876573d6000803e3d6000fd5b505050505050565b6000546001600160a01b03163314620018ab5760405162461bcd60e51b8152600401620008bb9062003267565b600c544210620018ef5760405162461bcd60e51b815260206004820152600e60248201526d185b1c9958591e54dd1bdc1c195960921b6044820152606401620008bb565b60405163329b20ed60e01b815260036004820152600090737e812ca56574ed578640daedfe2cb3ef93937ee99063329b20ed9060240160206040518083038186803b1580156200193e57600080fd5b505af415801562001953573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001979919062002f41565b6009819055600a81905542600b819055600c8190556040519192507f46e22fb3709ad289f62ce63d469248536dbc78d82b84a3d7e74ad606dc2019389162000b7791848252602082015260400190565b6000546001600160a01b03163314620019f65760405162461bcd60e51b8152600401620008bb9062003267565b6001600160a01b03811662001a3c5760405162461bcd60e51b815260206004820152600b60248201526a7a65726f4164647265737360a81b6044820152606401620008bb565b601080546001600160a01b0319166001600160a01b0383169081179091556040519081527fae5a12c29e496b092467a620746b9eaf4e0e231a631a4370c233b1fac38e8e269060200162000b77565b60606003600201805480602002602001604051908101604052809291908181526020018280548015620016f45760200282019190600052602060002090815481526020019060010190808311620016df575050505050905090565b60405163329b20ed60e01b815260036004820152600090737e812ca56574ed578640daedfe2cb3ef93937ee99063329b20ed90602401620006ff565b6000546001600160a01b0316331462001b4f5760405162461bcd60e51b8152600401620008bb9062003267565b600254610100900460ff168062001b69575060025460ff16155b62001bce5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401620008bb565b600254610100900460ff1615801562001bf1576002805461ffff19166101011790555b88518a511462001c445760405162461bcd60e51b815260206004820152601d60248201527f636f696e734c656e67746820213d20646563696d616c734c656e6774680000006044820152606401620008bb565b6001600160a01b03821662001c955760405162461bcd60e51b81526020600482015260166024820152756665654469737472696275746f72203d20656d70747960501b6044820152606401620008bb565b895160008167ffffffffffffffff81111562001cc157634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801562001ceb578160200160208202803683370190505b50905060008267ffffffffffffffff81111562001d1857634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801562001d42578160200160208202803683370190505b50905060005b8381101562001f9e5760006001600160a01b03168e828151811062001d7d57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316141562001dd45760405162461bcd60e51b8152602060048201526013602482015272696e76616c6964546f6b656e4164647265737360681b6044820152606401620008bb565b60128d828151811062001df757634e487b7160e01b600052603260045260246000fd5b602002602001015160ff16111562001e445760405162461bcd60e51b815260206004820152600f60248201526e696e76616c6964446563696d616c7360881b6044820152606401620008bb565b8c818151811062001e6557634e487b7160e01b600052603260045260246000fd5b602002602001015160ff16601262001e7e919062003548565b62001e8b90600a6200346a565b83828151811062001eac57634e487b7160e01b600052603260045260246000fd5b6020026020010181815250508d818151811062001ed957634e487b7160e01b600052603260045260246000fd5b602002602001015182828151811062001f0257634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b031681525050806012600084848151811062001f4857634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908360ff160217905550808062001f959062003595565b91505062001d48565b506402540be400891062001fde5760405162461bcd60e51b81526020600482015260066024820152653e206d61784160d01b6044820152606401620008bb565b6305f5e100881115620020235760405162461bcd60e51b815260206004820152600c60248201526b3e206d61785377617046656560a01b6044820152606401620008bb565b6402540be4008711156200206a5760405162461bcd60e51b815260206004820152600d60248201526c3e206d617841646d696e46656560981b6044820152606401620008bb565b6305f5e100861115620020b35760405162461bcd60e51b815260206004820152601060248201526f3e206d6178576974686472617746656560801b6044820152606401620008bb565b8a8a604051620020c3906200297c565b620020d09291906200320b565b604051809103906000f080158015620020ed573d6000803e3d6000fd5b50600480546001600160a01b0319166001600160a01b03929092169190911790558267ffffffffffffffff8111156200213657634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801562002160578160200160208202803683370190505b50805162002177916006916020909101906200298a565b5081516200218d9060059060208501906200298a565b508051620021a3906003906020840190620029da565b50620021b160648a62003526565b600955620021c160648a62003526565b600a5550505060078590556008849055600d839055601080546001600160a01b0319166001600160a01b038416179055801562002204576002805461ff00191690555b50505050505050505050565b604051632946144b60e21b815260036004820152600090737e812ca56574ed578640daedfe2cb3ef93937ee99063a518512c90602401620006ff565b604051631ce8027360e31b8152600090737e812ca56574ed578640daedfe2cb3ef93937ee99063e7401398906200164690600390889088908890600401620032f4565b6000546001600160a01b03163314620022bc5760405162461bcd60e51b8152600401620008bb9062003267565b6001600160a01b038116620023235760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401620008bb565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6011546001600160a01b0316331480620023a257506000546001600160a01b031633145b620023e85760405162461bcd60e51b815260206004820152601560248201527410b332b2a1b7b73a3937b63632b927b927bbb732b960591b6044820152606401620008bb565b60005b6003548110156200256c576000600360000182815481106200241d57634e487b7160e01b600052603260045260246000fd5b6000918252602082200154600680546001600160a01b03909216935090849081106200245957634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546040516370a0823160e01b81523060048201526001600160a01b038416906370a082319060240160206040518083038186803b158015620024a557600080fd5b505afa158015620024ba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620024e0919062002f41565b620024ec919062003548565b90508015620025545760105462002511906001600160a01b0384811691168362002731565b604080516001600160a01b0384168152602081018390527fee3859efa95e525bc2bcb149b51b60a8bb4e89c647392d9d4112e03c3e73bdd6910160405180910390a15b50508080620025639062003595565b915050620023eb565b50565b600054600160a01b900460ff16620025c15760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401620008bb565b6000805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b0381166000908152600b8301602052604081205481906200263a906224ea00620033e5565b905042811115620026be57600062002653428362003548565b6001600160a01b0385166000908152600c87016020526040902054600a8701549192506402540be400916224ea0091849162002690919062003526565b6200269c919062003526565b620026a8919062003400565b620026b4919062003400565b9250505062000bca565b5060009392505050565b600054600160a01b900460ff1615620026f55760405162461bcd60e51b8152600401620008bb906200323d565b6000805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258620025f13390565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052620027859084906200278a565b505050565b6000620027e1826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316620028639092919063ffffffff16565b80519091501562002785578080602001905181019062002802919062002f22565b620027855760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401620008bb565b60606200169a848460008585843b620028bf5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620008bb565b600080866001600160a01b03168587604051620028dd91906200314f565b60006040518083038185875af1925050503d80600081146200291c576040519150601f19603f3d011682016040523d82523d6000602084013e62002921565b606091505b5091509150620029338282866200293e565b979650505050505050565b606083156200294f575081620012b1565b825115620029605782518084602001fd5b8160405162461bcd60e51b8152600401620008bb9190620031f6565b61124480620035ef83390190565b828054828255906000526020600020908101928215620029c8579160200282015b82811115620029c8578251825591602001919060010190620029ab565b50620029d692915062002a32565b5090565b828054828255906000526020600020908101928215620029c8579160200282015b82811115620029c857825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190620029fb565b5b80821115620029d6576000815560010162002a33565b80356001600160a01b03811681146200119157600080fd5b600082601f83011262002a72578081fd5b8135602062002a8b62002a8583620033be565b6200338a565b80838252828201915082860187848660051b890101111562002aab578586fd5b855b8581101562002ad45762002ac18262002a49565b8452928401929084019060010162002aad565b5090979650505050505050565b600082601f83011262002af2578081fd5b8135602062002b0562002a8583620033be565b80838252828201915082860187848660051b890101111562002b25578586fd5b855b8581101562002ad45781358452928401929084019060010162002b27565b600082601f83011262002b56578081fd5b8135602062002b6962002a8583620033be565b80838252828201915082860187848660051b890101111562002b89578586fd5b855b8581101562002ad45762002b9f8262002c24565b8452928401929084019060010162002b8b565b600082601f83011262002bc3578081fd5b813567ffffffffffffffff81111562002be05762002be0620035c9565b62002bf5601f8201601f19166020016200338a565b81815284602083860101111562002c0a578283fd5b816020850160208301379081016020019190915292915050565b803560ff811681146200119157600080fd5b60006020828403121562002c48578081fd5b620012b18262002a49565b6000806040838503121562002c66578081fd5b62002c718362002a49565b946020939093013593505050565b60008060006060848603121562002c94578081fd5b62002c9f8462002a49565b92506020840135915062002cb66040850162002c24565b90509250925092565b60008060008060008060008060006101208a8c03121562002cde578485fd5b893567ffffffffffffffff8082111562002cf6578687fd5b62002d048d838e0162002a61565b9a5060208c013591508082111562002d1a578687fd5b62002d288d838e0162002b45565b995060408c013591508082111562002d3e578687fd5b62002d4c8d838e0162002bb2565b985060608c013591508082111562002d62578687fd5b5062002d718c828d0162002bb2565b96505060808a0135945060a08a0135935060c08a0135925060e08a0135915062002d9f6101008b0162002a49565b90509295985092959850929598565b60008060006040848603121562002dc3578081fd5b833567ffffffffffffffff8082111562002ddb578283fd5b818601915086601f83011262002def578283fd5b81358181111562002dfe578384fd5b8760208260051b850101111562002e13578384fd5b6020928301955093505084013562002e2b81620035df565b809150509250925092565b6000602080838503121562002e49578182fd5b825167ffffffffffffffff81111562002e60578283fd5b8301601f8101851362002e71578283fd5b805162002e8262002a8582620033be565b80828252848201915084840188868560051b870101111562002ea2578687fd5b8694505b8385101562002ec657805183526001949094019391850191850162002ea6565b50979650505050505050565b60008060006060848603121562002ee7578081fd5b833567ffffffffffffffff81111562002efe578182fd5b62002f0c8682870162002ae1565b9660208601359650604090950135949350505050565b60006020828403121562002f34578081fd5b8151620012b181620035df565b60006020828403121562002f53578081fd5b5051919050565b60008060006060848603121562002f6f578081fd5b83359250602084013567ffffffffffffffff81111562002f8d578182fd5b62002f9b8682870162002ae1565b925050604084013590509250925092565b6000806040838503121562002fbf578182fd5b50508035926020909101359150565b60008060006060848603121562002fe3578081fd5b505081359360208301359350604090920135919050565b6000806000806080858703121562003010578182fd5b84359350620030226020860162002c24565b93969395505050506040820135916060013590565b60006020828403121562003049578081fd5b620012b18262002c24565b60008060006060848603121562003069578081fd5b620030748462002c24565b9250620030846020850162002c24565b9150604084013590509250925092565b600080600080600060a08688031215620030ac578283fd5b620030b78662002c24565b9450620030c76020870162002c24565b94979496505050506040830135926060810135926080909101359150565b6000815180845260208085019450808401835b838110156200311657815187529582019590820190600101620030f8565b509495945050505050565b600081518084526200313b81602086016020860162003562565b601f01601f19169290920160200192915050565b600082516200316381846020870162003562565b9190910192915050565b6020808252825182820181905260009190848201906040850190845b81811015620031b05783516001600160a01b03168352928401929184019160010162003189565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015620031b057835183529284019291840191600101620031d8565b602081526000620012b1602083018462003121565b60408152600062003220604083018562003121565b828103602084015262003234818562003121565b95945050505050565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252600790820152661d1a5b595bdd5d60ca1b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b848152606060208201819052810183905260006001600160fb1b038411156200331b578081fd5b8360051b8086608085013782016080019081529115156040909101529392505050565b838152606060208201526000620033596060830185620030e5565b9050826040830152949350505050565b838152826020820152606060408201526000620032346060830184620030e5565b604051601f8201601f1916810167ffffffffffffffff81118282101715620033b657620033b6620035c9565b604052919050565b600067ffffffffffffffff821115620033db57620033db620035c9565b5060051b60200190565b60008219821115620033fb57620033fb620035b3565b500190565b6000826200341c57634e487b7160e01b81526012600452602481fd5b500490565b600181815b8085111562003462578160001904821115620034465762003446620035b3565b808516156200345457918102915b93841c939080029062003426565b509250929050565b6000620012b18383600082620034835750600162000bca565b81620034925750600062000bca565b8160018114620034ab5760028114620034b657620034d6565b600191505062000bca565b60ff841115620034ca57620034ca620035b3565b50506001821b62000bca565b5060208310610133831016604e8410600b8410161715620034fb575081810a62000bca565b62003507838362003421565b80600019048211156200351e576200351e620035b3565b029392505050565b6000816000190483118215151615620035435762003543620035b3565b500290565b6000828210156200355d576200355d620035b3565b500390565b60005b838110156200357f57818101518382015260200162003565565b838111156200358f576000848401525b50505050565b6000600019821415620035ac57620035ac620035b3565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b80151581146200256c57600080fdfe60806040523480156200001157600080fd5b50604051620012443803806200124483398101604081905262000034916200021b565b600080546001600160a01b03191633908117825560405184928492918291907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35081516200008e906004906020850190620000c2565b508051620000a4906005906020840190620000c2565b5050600680546001600160a01b0319163317905550620002d5915050565b828054620000d09062000282565b90600052602060002090601f016020900481019282620000f457600085556200013f565b82601f106200010f57805160ff19168380011785556200013f565b828001600101855582156200013f579182015b828111156200013f57825182559160200191906001019062000122565b506200014d92915062000151565b5090565b5b808211156200014d576000815560010162000152565b600082601f83011262000179578081fd5b81516001600160401b0380821115620001965762000196620002bf565b604051601f8301601f19908116603f01168101908282118183101715620001c157620001c1620002bf565b81604052838152602092508683858801011115620001dd578485fd5b8491505b83821015620002005785820183015181830184015290820190620001e1565b838211156200021157848385830101525b9695505050505050565b600080604083850312156200022e578182fd5b82516001600160401b038082111562000245578384fd5b620002538683870162000168565b9350602085015191508082111562000269578283fd5b50620002788582860162000168565b9150509250929050565b600181811c908216806200029757607f821691505b60208210811415620002b957634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052604160045260246000fd5b610f5f80620002e56000396000f3fe608060405234801561001057600080fd5b50600436106101165760003560e01c8063715018a6116100a257806395d89b411161007157806395d89b411461024b578063a457c2d714610253578063a9059cbb14610266578063dd62ed3e14610279578063f2fde38b146102b257600080fd5b8063715018a6146101f457806379cc6790146101fc5780638119c0651461020f5780638da5cb5b1461023a57600080fd5b8063313ce567116100e9578063313ce56714610181578063395093511461019057806340c10f19146101a357806342966c68146101b857806370a08231146101cb57600080fd5b806306fdde031461011b578063095ea7b31461013957806318160ddd1461015c57806323b872dd1461016e575b600080fd5b6101236102c5565b6040516101309190610e21565b60405180910390f35b61014c610147366004610de0565b610357565b6040519015158152602001610130565b6003545b604051908152602001610130565b61014c61017c366004610da5565b61036d565b60405160128152602001610130565b61014c61019e366004610de0565b610423565b6101b66101b1366004610de0565b61045a565b005b6101b66101c6366004610e09565b6104d3565b6101606101d9366004610d52565b6001600160a01b031660009081526001602052604090205490565b6101b66104e0565b6101b661020a366004610de0565b610554565b600654610222906001600160a01b031681565b6040516001600160a01b039091168152602001610130565b6000546001600160a01b0316610222565b6101236105dc565b61014c610261366004610de0565b6105eb565b61014c610274366004610de0565b610686565b610160610287366004610d73565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b6101b66102c0366004610d52565b610693565b6060600480546102d490610ed8565b80601f016020809104026020016040519081016040528092919081815260200182805461030090610ed8565b801561034d5780601f106103225761010080835404028352916020019161034d565b820191906000526020600020905b81548152906001019060200180831161033057829003601f168201915b5050505050905090565b600061036433848461077d565b50600192915050565b600061037a8484846108a2565b6001600160a01b0384166000908152600260209081526040808320338452909152902054828110156104045760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b60648201526084015b60405180910390fd5b61041885336104138685610ec1565b61077d565b506001949350505050565b3360008181526002602090815260408083206001600160a01b03871684529091528120549091610364918590610413908690610ea9565b6000546001600160a01b031633146104845760405162461bcd60e51b81526004016103fb90610e74565b600081116104c55760405162461bcd60e51b815260206004820152600e60248201526d1e995c9bd35a5b9d105b5bdd5b9d60921b60448201526064016103fb565b6104cf8282610a85565b5050565b6104dd3382610b70565b50565b6000546001600160a01b0316331461050a5760405162461bcd60e51b81526004016103fb90610e74565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b60006105608333610287565b9050818110156105be5760405162461bcd60e51b8152602060048201526024808201527f45524332303a206275726e20616d6f756e74206578636565647320616c6c6f77604482015263616e636560e01b60648201526084016103fb565b6105cd83336104138585610ec1565b6105d78383610b70565b505050565b6060600580546102d490610ed8565b3360009081526002602090815260408083206001600160a01b03861684529091528120548281101561066d5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084016103fb565b61067c33856104138685610ec1565b5060019392505050565b60006103643384846108a2565b6000546001600160a01b031633146106bd5760405162461bcd60e51b81526004016103fb90610e74565b6001600160a01b0381166107225760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016103fb565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0383166107df5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016103fb565b6001600160a01b0382166108405760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016103fb565b6001600160a01b0383811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6001600160a01b0383166109065760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016103fb565b6001600160a01b0382166109685760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016103fb565b610973838383610ccb565b6001600160a01b038316600090815260016020526040902054818110156109eb5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016103fb565b6109f58282610ec1565b6001600160a01b038086166000908152600160205260408082209390935590851681529081208054849290610a2b908490610ea9565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610a7791815260200190565b60405180910390a350505050565b6001600160a01b038216610adb5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016103fb565b610ae760008383610ccb565b8060036000828254610af99190610ea9565b90915550506001600160a01b03821660009081526001602052604081208054839290610b26908490610ea9565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6001600160a01b038216610bd05760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b60648201526084016103fb565b610bdc82600083610ccb565b6001600160a01b03821660009081526001602052604090205481811015610c505760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b60648201526084016103fb565b610c5a8282610ec1565b6001600160a01b03841660009081526001602052604081209190915560038054849290610c88908490610ec1565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610895565b600654604051633003049760e21b81526001600160a01b038481166004830152602482018490529091169063c00c125c90604401600060405180830381600087803b158015610d1957600080fd5b505af1158015610d2d573d6000803e3d6000fd5b50505050505050565b80356001600160a01b0381168114610d4d57600080fd5b919050565b600060208284031215610d63578081fd5b610d6c82610d36565b9392505050565b60008060408385031215610d85578081fd5b610d8e83610d36565b9150610d9c60208401610d36565b90509250929050565b600080600060608486031215610db9578081fd5b610dc284610d36565b9250610dd060208501610d36565b9150604084013590509250925092565b60008060408385031215610df2578182fd5b610dfb83610d36565b946020939093013593505050565b600060208284031215610e1a578081fd5b5035919050565b6000602080835283518082850152825b81811015610e4d57858101830151858201604001528201610e31565b81811115610e5e5783604083870101525b50601f01601f1916929092016040019392505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60008219821115610ebc57610ebc610f13565b500190565b600082821015610ed357610ed3610f13565b500390565b600181811c90821680610eec57607f821691505b60208210811415610f0d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fdfea264697066735822122054d2d632431a128fb66854fe890a2ec0166d749d10fbd21e9585d3cbfc9551c064736f6c63430008040033a264697066735822122088e6e6b51718287bd3fd106f820ff5cd9c072c769afed263493316cac7968ed064736f6c63430008040033
Deployed Bytecode Sourcemap
66992:12202:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;67666:45;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;30568:4:1;30556:17;;;30538:36;;30526:2;30511:18;67666:45:0;;;;;;;;67183:46;;67223:6;67183:46;;;;;24754:25:1;;;24742:2;24727:18;67183:46:0;24709:76:1;71728:115:0;;;:::i;67595:29::-;;;;;-1:-1:-1;;;;;67595:29:0;;;;;;-1:-1:-1;;;;;11591:32:1;;;11573:51;;11561:2;11546:18;67595:29:0;11528:102:1;73003:330:0;;;:::i;:::-;;;;;;;:::i;70529:281::-;;;;;;:::i;:::-;;:::i;67236:36::-;;67268:4;67236:36;;70818:320;;;;;;:::i;:::-;;:::i;78219:235::-;;;;;;:::i;:::-;;:::i;:::-;;25120:67;;;:::i;74432:170::-;;;;;;:::i;:::-;;:::i;69900:284::-;;;;;;:::i;:::-;;:::i;76741:1043::-;;;;;;:::i;:::-;;:::i;75833:550::-;;;;;;:::i;:::-;;:::i;23725:86::-;23772:4;23796:7;-1:-1:-1;;;23796:7:0;;;;23725:86;;13399:14:1;;13392:22;13374:41;;13362:2;13347:18;23725:86:0;13329:92:1;67546:42:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;67546:42:0;;;;;;;;;;;;;;-1:-1:-1;;;;;14025:32:1;;;14007:51;;14089:2;14074:18;;14067:34;;;;14117:18;;;14110:34;;;;14175:2;14160:18;;14153:34;;;;14218:3;14203:19;;14196:35;14045:3;14247:19;;14240:35;14306:3;14291:19;;14284:35;14350:3;14335:19;;14328:35;13994:3;13979:19;67546:42:0;13961:408:1;72230:215:0;;;;;;:::i;:::-;;:::i;67631:28::-;;;;;-1:-1:-1;;;;;67631:28:0;;;22090:148;;;:::i;73922:237::-;;;;;;:::i;:::-;;:::i;72115:107::-;72195:19;;-1:-1:-1;;;;;72195:19:0;72115:107;;71979:128;;;;;;:::i;:::-;;:::i;25049:63::-;;;:::i;71146:308::-;;;;;;:::i;:::-;;:::i;73341:141::-;;;;;;:::i;:::-;;:::i;21439:87::-;21485:7;21512:6;-1:-1:-1;;;;;21512:6:0;21439:87;;70192:329;;;;;;:::i;:::-;;:::i;72728:132::-;;;;;;:::i;:::-;;:::i;74167:257::-;;;;;;:::i;:::-;;:::i;72596:124::-;;;:::i;73687:227::-;;;;;;:::i;:::-;;:::i;71851:120::-;;;:::i;:::-;;;;;;;:::i;67410:42::-;;67449:3;67410:42;;67303:41;;67342:2;67303:41;;75150:245;;;;;;:::i;:::-;;:::i;77792:419::-;;;:::i;78462:242::-;;;;;;:::i;:::-;;:::i;72453:135::-;;;:::i;71619:101::-;;;:::i;68010:1856::-;;;;;;:::i;:::-;;:::i;71488:123::-;;;:::i;73490:189::-;;;;;;:::i;:::-;;:::i;72868:127::-;72956:11;:31;72868:127;;22393:244;;;;;;:::i;:::-;;:::i;78712:479::-;;;:::i;71728:115::-;71810:25;;-1:-1:-1;;;71810:25:0;;:11;:25;;;24754::1;71783:7:0;;71810:23;;;;24727:18:1;;71810:25:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;71803:32;;71728:115;:::o;73003:330::-;73123:11;:31;73063:30;;73123:31;73181:21;;;;;;-1:-1:-1;;;73181:21:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;73181:21:0;;73165:37;;73218:9;73213:113;73237:6;73233:1;:10;73213:113;;;73284:30;;-1:-1:-1;;;73284:30:0;;:11;:30;;;26997:25:1;27038:18;;;27031:34;;;73284:27:0;;;;26970:18:1;;73284:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;73265:13;73279:1;73265:16;;;;;;-1:-1:-1;;;73265:16:0;;;;;;;;;;;;;;;;;;:49;73245:3;;;;:::i;:::-;;;;73213:113;;;;73003:330;;:::o;70529:281::-;70717:16;1848:1;2445:7;;:19;;2437:63;;;;-1:-1:-1;;;2437:63:0;;;;;;;:::i;:::-;;;;;;;;;1848:1;2578:7;:18;70698:8;67781:15:::1;:28:::0;-1:-1:-1;67781:28:0::1;67773:48;;;;-1:-1:-1::0;;;67773:48:0::1;;;;;;;:::i;:::-;70753:49:::2;::::0;-1:-1:-1;;;70753:49:0;;:27:::2;::::0;::::2;::::0;:49:::2;::::0;:11:::2;::::0;70781:8;;70791:10;;70753:49:::2;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;::::0;;::::2;-1:-1:-1::0;;70753:49:0::2;::::0;::::2;;::::0;::::2;::::0;;;::::2;::::0;::::2;:::i;:::-;1804:1:::0;2757:22;;70746:56;70529:281;-1:-1:-1;;;;;70529:281:0:o;70818:320::-;71040:7;1848:1;2445:7;;:19;;2437:63;;;;-1:-1:-1;;;2437:63:0;;;;;;;:::i;:::-;1848:1;2578:7;:18;23772:4;23796:7;-1:-1:-1;;;23796:7:0;;;;24050:9:::1;24042:38;;;;-1:-1:-1::0;;;24042:38:0::1;;;;;;;:::i;:::-;71021:8:::2;67800:9;67781:15;:28;;67773:48;;;;-1:-1:-1::0;;;67773:48:0::2;;;;;;;:::i;:::-;71067:63:::3;::::0;-1:-1:-1;;;71067:63:0;;:11:::3;:63;::::0;::::3;27789:25:1::0;27830:18;;;27823:34;;;27905:4;27893:17;;27873:18;;;27866:45;27927:18;;;27920:34;;;71067:35:0::3;::::0;::::3;::::0;27761:19:1;;71067:63:0::3;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1804:1:::0;2757:22;;71060:70;70818:320;-1:-1:-1;;;;;;70818:320:0:o;78219:235::-;21485:7;21512:6;-1:-1:-1;;;;;21512:6:0;20069:10;21659:23;21651:68;;;;-1:-1:-1;;;21651:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;78309:28:0;::::1;78301:52;;;::::0;-1:-1:-1;;;78301:52:0;;19157:2:1;78301:52:0::1;::::0;::::1;19139:21:1::0;19196:2;19176:18;;;19169:30;-1:-1:-1;;;19215:18:1;;;19208:41;19266:18;;78301:52:0::1;19129:161:1::0;78301:52:0::1;78364:13;:30:::0;;-1:-1:-1;;;;;;78364:30:0::1;-1:-1:-1::0;;;;;78364:30:0;::::1;::::0;;::::1;::::0;;;78410:36:::1;::::0;11573:51:1;;;78410:36:0::1;::::0;11561:2:1;11546:18;78410:36:0::1;;;;;;;;78219:235:::0;:::o;25120:67::-;21485:7;21512:6;-1:-1:-1;;;;;21512:6:0;20069:10;21659:23;21651:68;;;;-1:-1:-1;;;21651:68:0;;;;;;;:::i;:::-;25169:10:::1;:8;:10::i;:::-;25120:67::o:0;74432:170::-;74518:7;74545:49;:11;74586:7;74545:40;:49::i;:::-;74538:56;74432:170;-1:-1:-1;;74432:170:0:o;69900:284::-;70101:7;23796;;-1:-1:-1;;;23796:7:0;;;;24050:9;24042:38;;;;-1:-1:-1;;;24042:38:0;;;;;;;:::i;:::-;1848:1:::1;2445:7;;:19;;2437:63;;;;-1:-1:-1::0;;;2437:63:0::1;;;;;;;:::i;:::-;1848:1;2578:7;:18:::0;70082:8;67781:15:::2;:28:::0;-1:-1:-1;67781:28:0::2;67773:48;;;;-1:-1:-1::0;;;67773:48:0::2;;;;;;;:::i;:::-;70128::::3;::::0;-1:-1:-1;;;70128:48:0;;:24:::3;::::0;::::3;::::0;:48:::3;::::0;:11:::3;::::0;70153:7;;70162:13;;70128:48:::3;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;76741:1043::-:0;21485:7;21512:6;-1:-1:-1;;;;;21512:6:0;20069:10;21659:23;21651:68;;;;-1:-1:-1;;;21651:68:0;;;;;;;:::i;:::-;76851:24;;:35:::1;::::0;76879:6:::1;76851:35;:::i;:::-;76832:15;:54;;76824:78;;;::::0;-1:-1:-1;;;76824:78:0;;21238:2:1;76824:78:0::1;::::0;::::1;21220:21:1::0;21277:2;21257:18;;;21250:30;-1:-1:-1;;;21296:18:1;;;21289:41;21347:18;;76824:78:0::1;21210:161:1::0;76824:78:0::1;76985:33;67223:6;76985:15;:33;:::i;:::-;76970:11;:48;;76962:74;;;::::0;-1:-1:-1;;;76962:74:0;;19858:2:1;76962:74:0::1;::::0;::::1;19840:21:1::0;19897:2;19877:18;;;19870:30;-1:-1:-1;;;19916:18:1;;;19909:43;19969:18;;76962:74:0::1;19830:163:1::0;76962:74:0::1;77059:7;77055:1;:11;:30;;;;;67268:4;77070:7;:15;77055:30;77047:53;;;::::0;-1:-1:-1;;;77047:53:0;;23730:2:1;77047:53:0::1;::::0;::::1;23712:21:1::0;23769:2;23749:18;;;23742:30;-1:-1:-1;;;23788:18:1;;;23781:40;23838:18;;77047:53:0::1;23702:160:1::0;77047:53:0::1;77139:25;::::0;-1:-1:-1;;;77139:25:0;;:11:::1;:25;::::0;::::1;24754::1::0;77113:23:0::1;::::0;77139::::1;::::0;::::1;::::0;24727:18:1;;77139:25:0::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;77113:51:::0;-1:-1:-1;77175:22:0::1;77200:33;44048:3;77200:7:::0;:33:::1;:::i;:::-;77175:58;;77267:15;77250:14;:32;77246:246;;;77342:15:::0;77307:31:::1;67342:2;77307:14:::0;:31:::1;:::i;:::-;:50;;77299:74;;;::::0;-1:-1:-1;;;77299:74:0;;23055:2:1;77299:74:0::1;::::0;::::1;23037:21:1::0;23094:2;23074:18;;;23067:30;-1:-1:-1;;;23113:18:1;;;23106:41;23164:18;;77299:74:0::1;23027:161:1::0;77299:74:0::1;77246:246;;;77432:32;67342:2;77432:15:::0;:32:::1;:::i;:::-;77414:14;:50;;77406:74;;;::::0;-1:-1:-1;;;77406:74:0;;23055:2:1;77406:74:0::1;::::0;::::1;23037:21:1::0;23094:2;23074:18;;;23067:30;-1:-1:-1;;;23113:18:1;;;23106:41;23164:18;;77406:74:0::1;23027:161:1::0;77406:74:0::1;77504:20:::0;:38;;;77553:19;:36;;;77627:15:::1;77600:24:::0;:42;;;77653:23;:37;;;77708:68:::1;::::0;;30231:25:1;;;30287:2;30272:18;;30265:34;;;30315:18;;;30308:34;;;;30373:2;30358:18;;30351:34;;;77708:68:0;::::1;::::0;;;;30218:3:1;77708:68:0;;::::1;21730:1;;76741:1043:::0;;:::o;75833:550::-;21485:7;21512:6;-1:-1:-1;;;;;21512:6:0;20069:10;21659:23;21651:68;;;;-1:-1:-1;;;21651:68:0;;;;;;;:::i;:::-;67449:3:::1;75986:10;:26;;75978:51;;;::::0;-1:-1:-1;;;75978:51:0;;16623:2:1;75978:51:0::1;::::0;::::1;16605:21:1::0;16662:2;16642:18;;;16635:30;-1:-1:-1;;;16681:18:1;;;16674:42;16733:18;;75978:51:0::1;16595:162:1::0;75978:51:0::1;67391:4;76048:11;:28;;76040:54;;;::::0;-1:-1:-1;;;76040:54:0;;18052:2:1;76040:54:0::1;::::0;::::1;18034:21:1::0;18091:2;18071:18;;;18064:30;-1:-1:-1;;;18110:18:1;;;18103:43;18163:18;;76040:54:0::1;18024:163:1::0;76040:54:0::1;67508:3;76113:14;:34;;76105:63;;;::::0;-1:-1:-1;;;76105:63:0;;20200:2:1;76105:63:0::1;::::0;::::1;20182:21:1::0;20239:2;20219:18;;;20212:30;-1:-1:-1;;;20258:18:1;;;20251:46;20314:18;;76105:63:0::1;20172:166:1::0;76105:63:0::1;76179:20:::0;:34;;;76224:15;:28;;;76263:30;:47;;;76328::::1;::::0;;29878:25:1;;;29934:2;29919:18;;29912:34;;;29962:18;;;29955:34;;;76328:47:0::1;::::0;29866:2:1;29851:18;76328:47:0::1;;;;;;;75833:550:::0;;;:::o;72230:215::-;-1:-1:-1;;;;;72332:19:0;;72300:11;72332:19;;;:12;:19;;;;;;72378:11;:31;;72332:19;;;;;;;;72378:31;;;;-1:-1:-1;;;72378:31:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;72378:31:0;72370:49;72362:75;;;;-1:-1:-1;;;72362:75:0;;20545:2:1;72362:75:0;;;20527:21:1;20584:2;20564:18;;;20557:30;-1:-1:-1;;;20603:18:1;;;20596:43;20656:18;;72362:75:0;20517:163:1;72362:75:0;72230:215;;;:::o;22090:148::-;21485:7;21512:6;-1:-1:-1;;;;;21512:6:0;20069:10;21659:23;21651:68;;;;-1:-1:-1;;;21651:68:0;;;;;;;:::i;:::-;22197:1:::1;22181:6:::0;;22160:40:::1;::::0;-1:-1:-1;;;;;22181:6:0;;::::1;::::0;22160:40:::1;::::0;22197:1;;22160:40:::1;22228:1;22211:19:::0;;-1:-1:-1;;;;;;22211:19:0::1;::::0;;22090:148::o;73922:237::-;74098:53;;-1:-1:-1;;;74098:53:0;;:11;:53;;;25030:25:1;-1:-1:-1;;;;;25091:32:1;;25071:18;;;25064:60;25140:18;;;25133:34;;;74057:16:0;;74098:36;;;;25003:18:1;;74098:53:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;74098:53:0;;;;;;;;;;;;:::i;:::-;74091:60;73922:237;-1:-1:-1;;;73922:237:0:o;71979:128::-;72042:6;72068:11;:24;;72093:5;72068:31;;;;;;;;-1:-1:-1;;;72068:31:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;72068:31:0;;71979:128;-1:-1:-1;;71979:128:0:o;25049:63::-;21485:7;21512:6;-1:-1:-1;;;;;21512:6:0;20069:10;21659:23;21651:68;;;;-1:-1:-1;;;21651:68:0;;;;;;;:::i;:::-;25096:8:::1;:6;:8::i;71146:308::-:0;71359:7;1848:1;2445:7;;:19;;2437:63;;;;-1:-1:-1;;;2437:63:0;;;;;;;:::i;:::-;1848:1;2578:7;:18;23772:4;23796:7;-1:-1:-1;;;23796:7:0;;;;24050:9:::1;24042:38;;;;-1:-1:-1::0;;;24042:38:0::1;;;;;;;:::i;:::-;71340:8:::2;67800:9;67781:15;:28;;67773:48;;;;-1:-1:-1::0;;;67773:48:0::2;;;;;;;:::i;:::-;71386:60:::3;::::0;-1:-1:-1;;;71386:60:0;;:36:::3;::::0;::::3;::::0;:60:::3;::::0;:11:::3;::::0;71423:7;;71432:13;;71386:60:::3;;;:::i;73341:141::-:0;73438:36;;-1:-1:-1;;;73438:36:0;;:11;:36;;;28175:25:1;28248:4;28236:17;;28216:18;;;28209:45;73411:7:0;;73438:27;;;;28148:18:1;;73438:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;70192:329::-;70426:7;23796;;-1:-1:-1;;;23796:7:0;;;;24050:9;24042:38;;;;-1:-1:-1;;;24042:38:0;;;;;;;:::i;:::-;1848:1:::1;2445:7;;:19;;2437:63;;;;-1:-1:-1::0;;;2437:63:0::1;;;;;;;:::i;:::-;1848:1;2578:7;:18:::0;70407:8;67781:15:::2;:28:::0;-1:-1:-1;67781:28:0::2;67773:48;;;;-1:-1:-1::0;;;67773:48:0::2;;;;;;;:::i;:::-;70453:60:::3;::::0;-1:-1:-1;;;70453:60:0;;:11:::3;:60;::::0;::::3;29010:25:1::0;29083:4;29071:17;;;29051:18;;;29044:45;29125:17;;29105:18;;;29098:45;29159:18;;;29152:34;;;29202:19;;;29195:35;;;70453:16:0::3;::::0;::::3;::::0;28982:19:1;;70453:60:0::3;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1804:1:::1;2757:22:::0;;70446:67;70192:329;-1:-1:-1;;;;;;;70192:329:0:o;72728:132::-;72798:7;72825:11;:20;;72846:5;72825:27;;;;;;;;-1:-1:-1;;;72825:27:0;;;;;;;;;;;;;;;;;72818:34;;72728:132;;;:::o;74167:257::-;74348:68;;-1:-1:-1;;;74348:68:0;;:11;:68;;;25445:25:1;-1:-1:-1;;;;;25506:32:1;;25486:18;;;25479:60;25555:18;;;25548:34;;;25630:4;25618:17;;25598:18;;;25591:45;74321:7:0;;74348:44;;;;25417:19:1;;74348:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;74341:75;74167:257;-1:-1:-1;;;;74167:257:0:o;72596:124::-;72656:16;72692:11;:20;;72685:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;72596:124;:::o;73687:227::-;73852:54;;-1:-1:-1;;;73852:54:0;;:11;:54;;;28530:25:1;28603:4;28591:17;;;28571:18;;;28564:45;28645:17;;28625:18;;;28618:45;28679:18;;;28672:34;;;73825:7:0;;73852:25;;;;28502:19:1;;73852:54:0;28484:228:1;71851:120:0;71904:15;71939:11;:24;;71932:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;71932:31:0;;;;;;;;;;;;;;;;;;;;;;71851:120;:::o;75150:245::-;75283:19;;-1:-1:-1;;;;;75283:19:0;75261:10;:42;75253:63;;;;-1:-1:-1;;;75253:63:0;;17371:2:1;75253:63:0;;;17353:21:1;17410:1;17390:18;;;17383:29;-1:-1:-1;;;17428:18:1;;;17421:38;17476:18;;75253:63:0;17343:157:1;75253:63:0;75327:60;;-1:-1:-1;;;75327:60:0;;:11;:60;;;25030:25:1;-1:-1:-1;;;;;25091:32:1;;25071:18;;;25064:60;25140:18;;;25133:34;;;75327:33:0;;;;25003:18:1;;75327:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;75150:245;;:::o;77792:419::-;21485:7;21512:6;-1:-1:-1;;;;;21512:6:0;20069:10;21659:23;21651:68;;;;-1:-1:-1;;;21651:68:0;;;;;;;:::i;:::-;77851:23;;77877:15:::1;-1:-1:-1::0;77843:68:0::1;;;::::0;-1:-1:-1;;;77843:68:0;;24429:2:1;77843:68:0::1;::::0;::::1;24411:21:1::0;24468:2;24448:18;;;24441:30;-1:-1:-1;;;24487:18:1;;;24480:44;24541:18;;77843:68:0::1;24401:164:1::0;77843:68:0::1;77941:18;::::0;-1:-1:-1;;;77941:18:0;;:11:::1;:18;::::0;::::1;24754:25:1::0;77922:16:0::1;::::0;77941::::1;::::0;::::1;::::0;24727:18:1;;77941::0::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;77972:20:::0;:31;;;78014:19;:30;;;78082:15:::1;78055:24:::0;:42;;;78108:23;:41;;;78167:36:::1;::::0;77922:37;;-1:-1:-1;78167:36:0::1;::::0;::::1;::::0;77922:37;26997:25:1;;27053:2;27038:18;;27031:34;26985:2;26970:18;;26952:119;78462:242:0;21485:7;21512:6;-1:-1:-1;;;;;21512:6:0;20069:10;21659:23;21651:68;;;;-1:-1:-1;;;21651:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;78554:29:0;::::1;78546:53;;;::::0;-1:-1:-1;;;78546:53:0;;19157:2:1;78546:53:0::1;::::0;::::1;19139:21:1::0;19196:2;19176:18;;;19169:30;-1:-1:-1;;;19215:18:1;;;19208:41;19266:18;;78546:53:0::1;19129:161:1::0;78546:53:0::1;78610:14;:32:::0;;-1:-1:-1;;;;;;78610:32:0::1;-1:-1:-1::0;;;;;78610:32:0;::::1;::::0;;::::1;::::0;;;78658:38:::1;::::0;11573:51:1;;;78658:38:0::1;::::0;11561:2:1;11546:18;78658:38:0::1;11528:102:1::0;72453:135:0;72516:16;72552:11;:28;;72545:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;72453:135;:::o;71619:101::-;71694:18;;-1:-1:-1;;;71694:18:0;;:11;:18;;;24754:25:1;71667:7:0;;71694:16;;;;24727:18:1;;71694::0;24709:76:1;68010:1856:0;21485:7;21512:6;-1:-1:-1;;;;;21512:6:0;20069:10;21659:23;21651:68;;;;-1:-1:-1;;;21651:68:0;;;;;;;:::i;:::-;4326:13:::1;::::0;::::1;::::0;::::1;;;::::0;:30:::1;;-1:-1:-1::0;4344:12:0::1;::::0;::::1;;4343:13;4326:30;4318:89;;;::::0;-1:-1:-1;;;4318:89:0;;18394:2:1;4318:89:0::1;::::0;::::1;18376:21:1::0;18433:2;18413:18;;;18406:30;18472:34;18452:18;;;18445:62;-1:-1:-1;;;18523:18:1;;;18516:44;18577:19;;4318:89:0::1;18366:236:1::0;4318:89:0::1;4443:13;::::0;::::1;::::0;::::1;;;4442:14;4467:101:::0;::::1;;;4502:13;:20:::0;;-1:-1:-1;;4537:19:0;;;;;4467:101:::1;68384:9:::2;:16;68367:6;:13;:33;68359:75;;;::::0;-1:-1:-1;;;68359:75:0;;21578:2:1;68359:75:0::2;::::0;::::2;21560:21:1::0;21617:2;21597:18;;;21590:30;21656:31;21636:18;;;21629:59;21705:18;;68359:75:0::2;21550:179:1::0;68359:75:0::2;-1:-1:-1::0;;;;;68453:29:0;::::2;68445:64;;;::::0;-1:-1:-1;;;68445:64:0;;20887:2:1;68445:64:0::2;::::0;::::2;20869:21:1::0;20926:2;20906:18;;;20899:30;-1:-1:-1;;;20945:18:1;;;20938:52;21007:18;;68445:64:0::2;20859:172:1::0;68445:64:0::2;68544:13:::0;;68520:21:::2;68544:13:::0;68593:28:::2;::::0;::::2;;;;-1:-1:-1::0;;;68593:28:0::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;68593:28:0::2;;68568:53;;68632:21;68669:13;68656:27;;;;;;-1:-1:-1::0;;;68656:27:0::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;68656:27:0::2;;68632:51;;68699:9;68694:408;68718:13;68714:1;:17;68694:408;;;68782:1;-1:-1:-1::0;;;;;68761:23:0::2;:6;68768:1;68761:9;;;;;;-1:-1:-1::0;;;68761:9:0::2;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;68761:23:0::2;;;68753:55;;;::::0;-1:-1:-1;;;68753:55:0;;18809:2:1;68753:55:0::2;::::0;::::2;18791:21:1::0;18848:2;18828:18;;;18821:30;-1:-1:-1;;;18867:18:1;;;18860:49;18926:18;;68753:55:0::2;18781:169:1::0;68753:55:0::2;44213:2;68831:9;68841:1;68831:12;;;;;;-1:-1:-1::0;;;68831:12:0::2;;;;;;;;;;;;;;;:54;;;;68823:82;;;::::0;-1:-1:-1;;;68823:82:0;;16279:2:1;68823:82:0::2;::::0;::::2;16261:21:1::0;16318:2;16298:18;;;16291:30;-1:-1:-1;;;16337:18:1;;;16330:45;16392:18;;68823:82:0::2;16251:165:1::0;68823:82:0::2;68977:9;68987:1;68977:12;;;;;;-1:-1:-1::0;;;68977:12:0::2;;;;;;;;;;;;;;;68936:53;;44213:2;68936:53;;;;:::i;:::-;68931:59;::::0;:2:::2;:59;:::i;:::-;68920:5;68926:1;68920:8;;;;;;-1:-1:-1::0;;;68920:8:0::2;;;;;;;;;;;;;;:70;;;::::0;::::2;69023:6;69030:1;69023:9;;;;;;-1:-1:-1::0;;;69023:9:0::2;;;;;;;;;;;;;;;69005:5;69011:1;69005:8;;;;;;-1:-1:-1::0;;;69005:8:0::2;;;;;;;;;;;;;;:28;-1:-1:-1::0;;;;;69005:28:0::2;;;-1:-1:-1::0;;;;;69005:28:0::2;;;::::0;::::2;69088:1;69048:12;:31;69069:5;69075:1;69069:8;;;;;;-1:-1:-1::0;;;69069:8:0::2;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;69048:31:0::2;-1:-1:-1::0;;;;;69048:31:0::2;;;;;;;;;;;;;:42;;;;;;;;;;;;;;;;;;68733:3;;;;;:::i;:::-;;;;68694:408;;;;67268:4;69122:2;:10;69114:29;;;::::0;-1:-1:-1;;;69114:29:0;;15538:2:1;69114:29:0::2;::::0;::::2;15520:21:1::0;15577:1;15557:18;;;15550:29;-1:-1:-1;;;15595:18:1;;;15588:36;15641:18;;69114:29:0::2;15510:155:1::0;69114:29:0::2;67449:3;69162:4;:20;;69154:45;;;::::0;-1:-1:-1;;;69154:45:0;;16623:2:1;69154:45:0::2;::::0;::::2;16605:21:1::0;16662:2;16642:18;;;16635:30;-1:-1:-1;;;16681:18:1;;;16674:42;16733:18;;69154:45:0::2;16595:162:1::0;69154:45:0::2;67391:4;69218:9;:26;;69210:52;;;::::0;-1:-1:-1;;;69210:52:0;;18052:2:1;69210:52:0::2;::::0;::::2;18034:21:1::0;18091:2;18071:18;;;18064:30;-1:-1:-1;;;18110:18:1;;;18103:43;18163:18;;69210:52:0::2;18024:163:1::0;69210:52:0::2;67508:3;69281:12;:32;;69273:61;;;::::0;-1:-1:-1;;;69273:61:0;;20200:2:1;69273:61:0::2;::::0;::::2;20182:21:1::0;20239:2;20219:18;;;20212:30;-1:-1:-1;;;20258:18:1;;;20251:46;20314:18;;69273:61:0::2;20172:166:1::0;69273:61:0::2;69381:11;69394:13;69369:39;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::2;;;;;-1:-1:-1::0;69347:19:0;:61;;-1:-1:-1;;;;;;69347:61:0::2;-1:-1:-1::0;;;;;69347:61:0;;;::::2;::::0;;;::::2;::::0;;69456:13;69442:28:::2;::::0;::::2;;;;-1:-1:-1::0;;;69442:28:0::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;69442:28:0::2;-1:-1:-1::0;69419:51:0;;::::2;::::0;:20;;:51:::2;::::0;;::::2;::::0;::::2;:::i;:::-;-1:-1:-1::0;69481:36:0;;::::2;::::0;:28;;:36:::2;::::0;::::2;::::0;::::2;:::i;:::-;-1:-1:-1::0;69528:32:0;;::::2;::::0;:11:::2;::::0;:32:::2;::::0;::::2;::::0;::::2;:::i;:::-;-1:-1:-1::0;69594:28:0::2;44048:3;69594:2:::0;:28:::2;:::i;:::-;69571:20:::0;:51;69655:28:::2;44048:3;69655:2:::0;:28:::2;:::i;:::-;69633:19:::0;:50;-1:-1:-1;;;69633:19:0::2;69694:22:::0;;;69727:20;:32;;;69770:30;:45;;;69826:14:::2;:32:::0;;-1:-1:-1;;;;;;69826:32:0::2;-1:-1:-1::0;;;;;69826:32:0;::::2;;::::0;;4594:68;::::1;;;4629:13;:21:::0;;-1:-1:-1;;4629:21:0::1;::::0;;4594:68:::1;21730:1;68010:1856:::0;;;;;;;;;:::o;71488:123::-;71574:29;;-1:-1:-1;;;71574:29:0;;:11;:29;;;24754:25:1;71547:7:0;;71574:27;;;;24727:18:1;;71574:29:0;24709:76:1;73490:189:0;73621:50;;-1:-1:-1;;;73621:50:0;;73594:7;;73621:32;;;;:50;;:11;;73654:7;;;;73663;;73621:50;;;:::i;22393:244::-;21485:7;21512:6;-1:-1:-1;;;;;21512:6:0;20069:10;21659:23;21651:68;;;;-1:-1:-1;;;21651:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;22482:22:0;::::1;22474:73;;;::::0;-1:-1:-1;;;22474:73:0;;15872:2:1;22474:73:0::1;::::0;::::1;15854:21:1::0;15911:2;15891:18;;;15884:30;15950:34;15930:18;;;15923:62;-1:-1:-1;;;16001:18:1;;;15994:36;16047:19;;22474:73:0::1;15844:228:1::0;22474:73:0::1;22584:6;::::0;;22563:38:::1;::::0;-1:-1:-1;;;;;22563:38:0;;::::1;::::0;22584:6;::::1;::::0;22563:38:::1;::::0;::::1;22612:6;:17:::0;;-1:-1:-1;;;;;;22612:17:0::1;-1:-1:-1::0;;;;;22612:17:0;;;::::1;::::0;;;::::1;::::0;;22393:244::o;78712:479::-;67918:13;;-1:-1:-1;;;;;67918:13:0;67904:10;:27;;:52;;-1:-1:-1;21485:7:0;21512:6;-1:-1:-1;;;;;21512:6:0;67935:10;:21;67904:52;67896:86;;;;-1:-1:-1;;;67896:86:0;;22294:2:1;67896:86:0;;;22276:21:1;22333:2;22313:18;;;22306:30;-1:-1:-1;;;22352:18:1;;;22345:51;22413:18;;67896:86:0;22266:171:1;67896:86:0;78790:9:::1;78785:399;78809:11;:31:::0;78805:35;::::1;78785:399;;;78862:12;78877:11;:24;;78902:1;78877:27;;;;;;-1:-1:-1::0;;;78877:27:0::1;;;;;;;;;;::::0;;;::::1;::::0;;::::1;::::0;78971:20;:23;;-1:-1:-1;;;;;78877:27:0;;::::1;::::0;-1:-1:-1;78971:20:0;78992:1;;78971:23;::::1;;;-1:-1:-1::0;;;78971:23:0::1;;;;;;;;;;::::0;;;::::1;::::0;;;::::1;::::0;78937:30:::1;::::0;-1:-1:-1;;;78937:30:0;;78961:4:::1;78937:30;::::0;::::1;11573:51:1::0;-1:-1:-1;;;;;78937:15:0;::::1;::::0;::::1;::::0;11546:18:1;;78937:30:0::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:58;;;;:::i;:::-;78919:76:::0;-1:-1:-1;79014:12:0;;79010:163:::1;;79066:14;::::0;79047:43:::1;::::0;-1:-1:-1;;;;;79047:18:0;;::::1;::::0;79066:14:::1;79082:7:::0;79047:18:::1;:43::i;:::-;79114;::::0;;-1:-1:-1;;;;;11827:32:1;;11809:51;;11891:2;11876:18;;11869:34;;;79114:43:0::1;::::0;11782:18:1;79114:43:0::1;;;;;;;79010:163;78785:399;;78842:3;;;;;:::i;:::-;;;;78785:399;;;;78712:479::o:0;24784:120::-;23772:4;23796:7;-1:-1:-1;;;23796:7:0;;;;24320:41;;;;-1:-1:-1;;;24320:41:0;;15189:2:1;24320:41:0;;;15171:21:1;15228:2;15208:18;;;15201:30;-1:-1:-1;;;15247:18:1;;;15240:50;15307:18;;24320:41:0;15161:170:1;24320:41:0;24853:5:::1;24843:15:::0;;-1:-1:-1;;;;24843:15:0::1;::::0;;24874:22:::1;20069:10:::0;24883:12:::1;24874:22;::::0;-1:-1:-1;;;;;11591:32:1;;;11573:51;;11561:2;11546:18;24874:22:0::1;;;;;;;24784:120::o:0;65796:499::-;-1:-1:-1;;;;;65935:27:0;;65897:7;65935:27;;;:21;;;:27;;;;;;65897:7;;65935:39;;65966:7;65935:39;:::i;:::-;65917:57;;65999:15;65989:7;:25;65985:284;;;66031:20;66054:25;66064:15;66054:7;:25;:::i;:::-;-1:-1:-1;;;;;66145:32:0;;;;;;:26;;;:32;;;;;;66119:23;;;;66031:48;;-1:-1:-1;43756:4:0;;66214:7;;66031:48;;66119:58;;66145:32;66119:58;:::i;:::-;:73;;;;:::i;:::-;66118:104;;;;:::i;:::-;:139;;;;:::i;:::-;66094:163;;;;;;65985:284;-1:-1:-1;66286:1:0;;65796:499;-1:-1:-1;;;65796:499:0:o;24525:118::-;23772:4;23796:7;-1:-1:-1;;;23796:7:0;;;;24050:9;24042:38;;;;-1:-1:-1;;;24042:38:0;;;;;;;:::i;:::-;24585:7:::1;:14:::0;;-1:-1:-1;;;;24585:14:0::1;-1:-1:-1::0;;;24585:14:0::1;::::0;;24615:20:::1;24622:12;20069:10:::0;;19989:98;16155:177;16265:58;;;-1:-1:-1;;;;;11827:32:1;;16265:58:0;;;11809:51:1;11876:18;;;;11869:34;;;16265:58:0;;;;;;;;;;11782:18:1;;;;16265:58:0;;;;;;;;-1:-1:-1;;;;;16265:58:0;-1:-1:-1;;;16265:58:0;;;16238:86;;16258:5;;16238:19;:86::i;:::-;16155:177;;;:::o;18589:761::-;19013:23;19039:69;19067:4;19039:69;;;;;;;;;;;;;;;;;19047:5;-1:-1:-1;;;;;19039:27:0;;;:69;;;;;:::i;:::-;19123:17;;19013:95;;-1:-1:-1;19123:21:0;19119:224;;19265:10;19254:30;;;;;;;;;;;;:::i;:::-;19246:85;;;;-1:-1:-1;;;19246:85:0;;22644:2:1;19246:85:0;;;22626:21:1;22683:2;22663:18;;;22656:30;22722:34;22702:18;;;22695:62;-1:-1:-1;;;22773:18:1;;;22766:40;22823:19;;19246:85:0;22616:232:1;11179:195:0;11282:12;11314:52;11336:6;11344:4;11350:1;11353:12;11282;8628:20;;12475:60;;;;-1:-1:-1;;;12475:60:0;;21936:2:1;12475:60:0;;;21918:21:1;21975:2;21955:18;;;21948:30;22014:31;21994:18;;;21987:59;22063:18;;12475:60:0;21908:179:1;12475:60:0;12609:12;12623:23;12650:6;-1:-1:-1;;;;;12650:11:0;12670:5;12678:4;12650:33;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12608:75;;;;12701:52;12719:7;12728:10;12740:12;12701:17;:52::i;:::-;12694:59;12231:530;-1:-1:-1;;;;;;;12231:530:0:o;14771:742::-;14886:12;14915:7;14911:595;;;-1:-1:-1;14946:10:0;14939:17;;14911:595;15060:17;;:21;15056:439;;15323:10;15317:17;15384:15;15371:10;15367:2;15363:19;15356:44;15271:148;15466:12;15459:20;;-1:-1:-1;;;15459:20:0;;;;;;;;:::i;-1:-1:-1:-;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14:173:1;82:20;;-1:-1:-1;;;;;131:31:1;;121:42;;111:2;;177:1;174;167:12;192:699;246:5;299:3;292:4;284:6;280:17;276:27;266:2;;321:5;314;307:20;266:2;361:6;348:20;387:4;411:60;427:43;467:2;427:43;:::i;:::-;411:60;:::i;:::-;493:3;517:2;512:3;505:15;545:2;540:3;536:12;529:19;;580:2;572:6;568:15;632:3;627:2;621;618:1;614:10;606:6;602:23;598:32;595:41;592:2;;;653:5;646;639:20;592:2;679:5;693:169;707:2;704:1;701:9;693:169;;;764:23;783:3;764:23;:::i;:::-;752:36;;808:12;;;;840;;;;725:1;718:9;693:169;;;-1:-1:-1;880:5:1;;256:635;-1:-1:-1;;;;;;;256:635:1:o;896:693::-;950:5;1003:3;996:4;988:6;984:17;980:27;970:2;;1025:5;1018;1011:20;970:2;1065:6;1052:20;1091:4;1115:60;1131:43;1171:2;1131:43;:::i;1115:60::-;1197:3;1221:2;1216:3;1209:15;1249:2;1244:3;1240:12;1233:19;;1284:2;1276:6;1272:15;1336:3;1331:2;1325;1322:1;1318:10;1310:6;1306:23;1302:32;1299:41;1296:2;;;1357:5;1350;1343:20;1296:2;1383:5;1397:163;1411:2;1408:1;1405:9;1397:163;;;1468:17;;1456:30;;1506:12;;;;1538;;;;1429:1;1422:9;1397:163;;1594:695;1646:5;1699:3;1692:4;1684:6;1680:17;1676:27;1666:2;;1721:5;1714;1707:20;1666:2;1761:6;1748:20;1787:4;1811:60;1827:43;1867:2;1827:43;:::i;1811:60::-;1893:3;1917:2;1912:3;1905:15;1945:2;1940:3;1936:12;1929:19;;1980:2;1972:6;1968:15;2032:3;2027:2;2021;2018:1;2014:10;2006:6;2002:23;1998:32;1995:41;1992:2;;;2053:5;2046;2039:20;1992:2;2079:5;2093:167;2107:2;2104:1;2101:9;2093:167;;;2164:21;2181:3;2164:21;:::i;:::-;2152:34;;2206:12;;;;2238;;;;2125:1;2118:9;2093:167;;2294:551;2337:5;2390:3;2383:4;2375:6;2371:17;2367:27;2357:2;;2412:5;2405;2398:20;2357:2;2452:6;2439:20;2478:18;2474:2;2471:26;2468:2;;;2500:18;;:::i;:::-;2544:55;2587:2;2568:13;;-1:-1:-1;;2564:27:1;2593:4;2560:38;2544:55;:::i;:::-;2624:2;2615:7;2608:19;2670:3;2663:4;2658:2;2650:6;2646:15;2642:26;2639:35;2636:2;;;2691:5;2684;2677:20;2636:2;2760;2753:4;2745:6;2741:17;2734:4;2725:7;2721:18;2708:55;2783:16;;;2801:4;2779:27;2772:42;;;;2787:7;2347:498;-1:-1:-1;;2347:498:1:o;2850:156::-;2916:20;;2976:4;2965:16;;2955:27;;2945:2;;2996:1;2993;2986:12;3011:196;3070:6;3123:2;3111:9;3102:7;3098:23;3094:32;3091:2;;;3144:6;3136;3129:22;3091:2;3172:29;3191:9;3172:29;:::i;3212:264::-;3280:6;3288;3341:2;3329:9;3320:7;3316:23;3312:32;3309:2;;;3362:6;3354;3347:22;3309:2;3390:29;3409:9;3390:29;:::i;:::-;3380:39;3466:2;3451:18;;;;3438:32;;-1:-1:-1;;;3299:177:1:o;3481:334::-;3556:6;3564;3572;3625:2;3613:9;3604:7;3600:23;3596:32;3593:2;;;3646:6;3638;3631:22;3593:2;3674:29;3693:9;3674:29;:::i;:::-;3664:39;;3750:2;3739:9;3735:18;3722:32;3712:42;;3773:36;3805:2;3794:9;3790:18;3773:36;:::i;:::-;3763:46;;3583:232;;;;;:::o;3820:1393::-;4019:6;4027;4035;4043;4051;4059;4067;4075;4083;4136:3;4124:9;4115:7;4111:23;4107:33;4104:2;;;4158:6;4150;4143:22;4104:2;4203:9;4190:23;4232:18;4273:2;4265:6;4262:14;4259:2;;;4294:6;4286;4279:22;4259:2;4322:61;4375:7;4366:6;4355:9;4351:22;4322:61;:::i;:::-;4312:71;;4436:2;4425:9;4421:18;4408:32;4392:48;;4465:2;4455:8;4452:16;4449:2;;;4486:6;4478;4471:22;4449:2;4514:61;4567:7;4556:8;4545:9;4541:24;4514:61;:::i;:::-;4504:71;;4628:2;4617:9;4613:18;4600:32;4584:48;;4657:2;4647:8;4644:16;4641:2;;;4678:6;4670;4663:22;4641:2;4706:52;4750:7;4739:8;4728:9;4724:24;4706:52;:::i;:::-;4696:62;;4811:2;4800:9;4796:18;4783:32;4767:48;;4840:2;4830:8;4827:16;4824:2;;;4861:6;4853;4846:22;4824:2;;4889:52;4933:7;4922:8;4911:9;4907:24;4889:52;:::i;:::-;4879:62;;;4988:3;4977:9;4973:19;4960:33;4950:43;;5040:3;5029:9;5025:19;5012:33;5002:43;;5092:3;5081:9;5077:19;5064:33;5054:43;;5144:3;5133:9;5129:19;5116:33;5106:43;;5168:39;5202:3;5191:9;5187:19;5168:39;:::i;:::-;5158:49;;4094:1119;;;;;;;;;;;:::o;5218:800::-;5310:6;5318;5326;5379:2;5367:9;5358:7;5354:23;5350:32;5347:2;;;5400:6;5392;5385:22;5347:2;5445:9;5432:23;5474:18;5515:2;5507:6;5504:14;5501:2;;;5536:6;5528;5521:22;5501:2;5579:6;5568:9;5564:22;5554:32;;5624:7;5617:4;5613:2;5609:13;5605:27;5595:2;;5651:6;5643;5636:22;5595:2;5696;5683:16;5722:2;5714:6;5711:14;5708:2;;;5743:6;5735;5728:22;5708:2;5803:7;5796:4;5786:6;5783:1;5779:14;5775:2;5771:23;5767:34;5764:47;5761:2;;;5829:6;5821;5814:22;5761:2;5865:4;5857:13;;;;-1:-1:-1;5889:6:1;-1:-1:-1;;5930:20:1;;5917:34;5960:28;5917:34;5960:28;:::i;:::-;6007:5;5997:15;;;5337:681;;;;;:::o;6023:937::-;6118:6;6149:2;6192;6180:9;6171:7;6167:23;6163:32;6160:2;;;6213:6;6205;6198:22;6160:2;6251:9;6245:16;6284:18;6276:6;6273:30;6270:2;;;6321:6;6313;6306:22;6270:2;6349:22;;6402:4;6394:13;;6390:27;-1:-1:-1;6380:2:1;;6436:6;6428;6421:22;6380:2;6470;6464:9;6493:60;6509:43;6549:2;6509:43;:::i;6493:60::-;6575:3;6599:2;6594:3;6587:15;6627:2;6622:3;6618:12;6611:19;;6658:2;6654;6650:11;6706:7;6701:2;6695;6692:1;6688:10;6684:2;6680:19;6676:28;6673:41;6670:2;;;6732:6;6724;6717:22;6670:2;6759:6;6750:15;;6774:156;6788:2;6785:1;6782:9;6774:156;;;6845:10;;6833:23;;6806:1;6799:9;;;;;6876:12;;;;6908;;6774:156;;;-1:-1:-1;6949:5:1;6129:831;-1:-1:-1;;;;;;;6129:831:1:o;6965:504::-;7067:6;7075;7083;7136:2;7124:9;7115:7;7111:23;7107:32;7104:2;;;7157:6;7149;7142:22;7104:2;7202:9;7189:23;7235:18;7227:6;7224:30;7221:2;;;7272:6;7264;7257:22;7221:2;7300:61;7353:7;7344:6;7333:9;7329:22;7300:61;:::i;:::-;7290:71;7408:2;7393:18;;7380:32;;-1:-1:-1;7459:2:1;7444:18;;;7431:32;;7094:375;-1:-1:-1;;;;7094:375:1:o;7474:255::-;7541:6;7594:2;7582:9;7573:7;7569:23;7565:32;7562:2;;;7615:6;7607;7600:22;7562:2;7652:9;7646:16;7671:28;7693:5;7671:28;:::i;7734:194::-;7804:6;7857:2;7845:9;7836:7;7832:23;7828:32;7825:2;;;7878:6;7870;7863:22;7825:2;-1:-1:-1;7906:16:1;;7815:113;-1:-1:-1;7815:113:1:o;7933:504::-;8035:6;8043;8051;8104:2;8092:9;8083:7;8079:23;8075:32;8072:2;;;8125:6;8117;8110:22;8072:2;8166:9;8153:23;8143:33;;8227:2;8216:9;8212:18;8199:32;8254:18;8246:6;8243:30;8240:2;;;8291:6;8283;8276:22;8240:2;8319:61;8372:7;8363:6;8352:9;8348:22;8319:61;:::i;:::-;8309:71;;;8427:2;8416:9;8412:18;8399:32;8389:42;;8062:375;;;;;:::o;8442:258::-;8510:6;8518;8571:2;8559:9;8550:7;8546:23;8542:32;8539:2;;;8592:6;8584;8577:22;8539:2;-1:-1:-1;;8620:23:1;;;8690:2;8675:18;;;8662:32;;-1:-1:-1;8529:171:1:o;8705:326::-;8782:6;8790;8798;8851:2;8839:9;8830:7;8826:23;8822:32;8819:2;;;8872:6;8864;8857:22;8819:2;-1:-1:-1;;8900:23:1;;;8970:2;8955:18;;8942:32;;-1:-1:-1;9021:2:1;9006:18;;;8993:32;;8809:222;-1:-1:-1;8809:222:1:o;9036:397::-;9120:6;9128;9136;9144;9197:3;9185:9;9176:7;9172:23;9168:33;9165:2;;;9219:6;9211;9204:22;9165:2;9260:9;9247:23;9237:33;;9289:36;9321:2;9310:9;9306:18;9289:36;:::i;:::-;9155:278;;9279:46;;-1:-1:-1;;;;9372:2:1;9357:18;;9344:32;;9423:2;9408:18;9395:32;;9155:278::o;9438:192::-;9495:6;9548:2;9536:9;9527:7;9523:23;9519:32;9516:2;;;9569:6;9561;9554:22;9516:2;9597:27;9614:9;9597:27;:::i;9635:330::-;9708:6;9716;9724;9777:2;9765:9;9756:7;9752:23;9748:32;9745:2;;;9798:6;9790;9783:22;9745:2;9826:27;9843:9;9826:27;:::i;:::-;9816:37;;9872:36;9904:2;9893:9;9889:18;9872:36;:::i;:::-;9862:46;;9955:2;9944:9;9940:18;9927:32;9917:42;;9735:230;;;;;:::o;9970:468::-;10061:6;10069;10077;10085;10093;10146:3;10134:9;10125:7;10121:23;10117:33;10114:2;;;10168:6;10160;10153:22;10114:2;10196:27;10213:9;10196:27;:::i;:::-;10186:37;;10242:36;10274:2;10263:9;10259:18;10242:36;:::i;:::-;10104:334;;10232:46;;-1:-1:-1;;;;10325:2:1;10310:18;;10297:32;;10376:2;10361:18;;10348:32;;10427:3;10412:19;;;10399:33;;-1:-1:-1;10104:334:1:o;10443:437::-;10496:3;10534:5;10528:12;10561:6;10556:3;10549:19;10587:4;10616:2;10611:3;10607:12;10600:19;;10653:2;10646:5;10642:14;10674:3;10686:169;10700:6;10697:1;10694:13;10686:169;;;10761:13;;10749:26;;10795:12;;;;10830:15;;;;10722:1;10715:9;10686:169;;;-1:-1:-1;10871:3:1;;10504:376;-1:-1:-1;;;;;10504:376:1:o;10885:258::-;10927:3;10965:5;10959:12;10992:6;10987:3;10980:19;11008:63;11064:6;11057:4;11052:3;11048:14;11041:4;11034:5;11030:16;11008:63;:::i;:::-;11125:2;11104:15;-1:-1:-1;;11100:29:1;11091:39;;;;11132:4;11087:50;;10935:208;-1:-1:-1;;10935:208:1:o;11148:274::-;11277:3;11315:6;11309:13;11331:53;11377:6;11372:3;11365:4;11357:6;11353:17;11331:53;:::i;:::-;11400:16;;;;;11285:137;-1:-1:-1;;11285:137:1:o;11914:675::-;12099:2;12151:21;;;12221:13;;12124:18;;;12243:22;;;12070:4;;12099:2;12322:15;;;;12296:2;12281:18;;;12070:4;12368:195;12382:6;12379:1;12376:13;12368:195;;;12447:13;;-1:-1:-1;;;;;12443:39:1;12431:52;;12538:15;;;;12503:12;;;;12479:1;12397:9;12368:195;;;-1:-1:-1;12580:3:1;;12079:510;-1:-1:-1;;;;;;12079:510:1:o;12594:635::-;12765:2;12817:21;;;12887:13;;12790:18;;;12909:22;;;12736:4;;12765:2;12988:15;;;;12962:2;12947:18;;;12736:4;13034:169;13048:6;13045:1;13042:13;13034:169;;;13109:13;;13097:26;;13178:15;;;;13143:12;;;;13070:1;13063:9;13034:169;;14374:220;14523:2;14512:9;14505:21;14486:4;14543:45;14584:2;14573:9;14569:18;14561:6;14543:45;:::i;14599:383::-;14796:2;14785:9;14778:21;14759:4;14822:45;14863:2;14852:9;14848:18;14840:6;14822:45;:::i;:::-;14915:9;14907:6;14903:22;14898:2;14887:9;14883:18;14876:50;14943:33;14969:6;14961;14943:33;:::i;:::-;14935:41;14768:214;-1:-1:-1;;;;;14768:214:1:o;17505:340::-;17707:2;17689:21;;;17746:2;17726:18;;;17719:30;-1:-1:-1;;;17780:2:1;17765:18;;17758:46;17836:2;17821:18;;17679:166::o;19295:356::-;19497:2;19479:21;;;19516:18;;;19509:30;19575:34;19570:2;19555:18;;19548:62;19642:2;19627:18;;19469:182::o;23193:330::-;23395:2;23377:21;;;23434:1;23414:18;;;23407:29;-1:-1:-1;;;23467:2:1;23452:18;;23445:37;23514:2;23499:18;;23367:156::o;23867:355::-;24069:2;24051:21;;;24108:2;24088:18;;;24081:30;24147:33;24142:2;24127:18;;24120:61;24213:2;24198:18;;24041:181::o;25647:687::-;25906:25;;;25967:2;25962;25947:18;;25940:30;;;25986:18;;25979:34;;;-1:-1:-1;;;;;;26025:31:1;;26022:2;;;26072:4;26066;26059:18;26022:2;26109:6;26106:1;26102:14;26167:6;26159;26153:3;26142:9;26138:19;26125:49;26197:22;;26221:3;26193:32;26234:16;;;26312:14;;26305:22;26300:2;26285:18;;;26278:50;26193:32;25896:438;-1:-1:-1;;;25896:438:1:o;26339:441::-;26612:6;26601:9;26594:25;26655:2;26650;26639:9;26635:18;26628:30;26575:4;26675:56;26727:2;26716:9;26712:18;26704:6;26675:56;:::i;:::-;26667:64;;26767:6;26762:2;26751:9;26747:18;26740:34;26584:196;;;;;;:::o;27076:441::-;27349:6;27338:9;27331:25;27392:6;27387:2;27376:9;27372:18;27365:34;27435:2;27430;27419:9;27415:18;27408:30;27312:4;27455:56;27507:2;27496:9;27492:18;27484:6;27455:56;:::i;30585:275::-;30656:2;30650:9;30721:2;30702:13;;-1:-1:-1;;30698:27:1;30686:40;;30756:18;30741:34;;30777:22;;;30738:62;30735:2;;;30803:18;;:::i;:::-;30839:2;30832:22;30630:230;;-1:-1:-1;30630:230:1:o;30865:183::-;30925:4;30958:18;30950:6;30947:30;30944:2;;;30980:18;;:::i;:::-;-1:-1:-1;31025:1:1;31021:14;31037:4;31017:25;;30934:114::o;31053:128::-;31093:3;31124:1;31120:6;31117:1;31114:13;31111:2;;;31130:18;;:::i;:::-;-1:-1:-1;31166:9:1;;31101:80::o;31186:217::-;31226:1;31252;31242:2;;-1:-1:-1;;;31277:31:1;;31331:4;31328:1;31321:15;31359:4;31284:1;31349:15;31242:2;-1:-1:-1;31388:9:1;;31232:171::o;31408:422::-;31497:1;31540:5;31497:1;31554:270;31575:7;31565:8;31562:21;31554:270;;;31634:4;31630:1;31626:6;31622:17;31616:4;31613:27;31610:2;;;31643:18;;:::i;:::-;31693:7;31683:8;31679:22;31676:2;;;31713:16;;;;31676:2;31792:22;;;;31752:15;;;;31554:270;;;31558:3;31472:358;;;;;:::o;31835:131::-;31895:5;31924:36;31951:8;31945:4;32020:5;32050:8;32040:2;;-1:-1:-1;32091:1:1;32105:5;;32040:2;32139:4;32129:2;;-1:-1:-1;32176:1:1;32190:5;;32129:2;32221:4;32239:1;32234:59;;;;32307:1;32302:130;;;;32214:218;;32234:59;32264:1;32255:10;;32278:5;;;32302:130;32339:3;32329:8;32326:17;32323:2;;;32346:18;;:::i;:::-;-1:-1:-1;;32402:1:1;32388:16;;32417:5;;32214:218;;32516:2;32506:8;32503:16;32497:3;32491:4;32488:13;32484:36;32478:2;32468:8;32465:16;32460:2;32454:4;32451:12;32447:35;32444:77;32441:2;;;-1:-1:-1;32553:19:1;;;32585:5;;32441:2;32632:34;32657:8;32651:4;32632:34;:::i;:::-;32702:6;32698:1;32694:6;32690:19;32681:7;32678:32;32675:2;;;32713:18;;:::i;:::-;32751:20;;32030:747;-1:-1:-1;;;32030:747:1:o;32782:168::-;32822:7;32888:1;32884;32880:6;32876:14;32873:1;32870:21;32865:1;32858:9;32851:17;32847:45;32844:2;;;32895:18;;:::i;:::-;-1:-1:-1;32935:9:1;;32834:116::o;32955:125::-;32995:4;33023:1;33020;33017:8;33014:2;;;33028:18;;:::i;:::-;-1:-1:-1;33065:9:1;;33004:76::o;33085:258::-;33157:1;33167:113;33181:6;33178:1;33175:13;33167:113;;;33257:11;;;33251:18;33238:11;;;33231:39;33203:2;33196:10;33167:113;;;33298:6;33295:1;33292:13;33289:2;;;33333:1;33324:6;33319:3;33315:16;33308:27;33289:2;;33138:205;;;:::o;33348:135::-;33387:3;-1:-1:-1;;33408:17:1;;33405:2;;;33428:18;;:::i;:::-;-1:-1:-1;33475:1:1;33464:13;;33395:88::o;33488:127::-;33549:10;33544:3;33540:20;33537:1;33530:31;33580:4;33577:1;33570:15;33604:4;33601:1;33594:15;33620:127;33681:10;33676:3;33672:20;33669:1;33662:31;33712:4;33709:1;33702:15;33736:4;33733:1;33726:15;33752:118;33838:5;33831:13;33824:21;33817:5;33814:32;33804:2;;33860:1;33857;33850:12
Swarm Source
ipfs://88e6e6b51718287bd3fd106f820ff5cd9c072c769afed263493316cac7968ed0
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.