Source Code
Overview
MOVR Balance
MOVR Value
$0.00View more zero value Internal Transactions in Advanced View mode
Cross-Chain Transactions
Loading...
Loading
Contract Name:
StableSwapStorage
Compiler Version
v0.8.7+commit.e28d00a7
Contract Source Code (Solidity)
/**
*Submitted for verification at moonriver.moonscan.io on 2022-05-30
*/
// File: @openzeppelin/contracts/utils/Context.sol
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
// File: @openzeppelin/contracts/access/Ownable.sol
// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)
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() {
_transferOwnership(_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 {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
// File: @openzeppelin/contracts/utils/Address.sol
// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @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
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
// File: @openzeppelin/contracts/token/ERC20/IERC20.sol
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)
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 `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, 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 `from` to `to` 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 from,
address to,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
// File: contracts/stableswap/interfaces/IStableSwap.sol
pragma solidity >=0.8.0;
interface IStableSwap {
/// EVENTS
event AddLiquidity(
address indexed provider,
uint256[] tokenAmounts,
uint256[] fees,
uint256 invariant,
uint256 tokenSupply
);
event FlashLoan(
address indexed caller,
address indexed receiver,
uint256[] amounts_out
);
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);
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(uint256 amount) external view returns (uint256[] memory);
function calculateRemoveLiquidityOneToken(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);
// state modifying functions
function swap(
uint8 tokenIndexFrom,
uint8 tokenIndexTo,
uint256 dx,
uint256 minDy,
uint256 deadline
) external returns (uint256);
function flashLoan(
uint256[] memory amountsOut,
address to,
bytes calldata data,
uint256 deadline
) external;
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 withdrawAdminFee() external;
}
// File: @openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
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/ERC20.sol
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/ERC20.sol)
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 Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC20
* applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* The default value of {decimals} is 18. To select a different value for
* {decimals} you should overload it.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the value {ERC20} uses, unless this function is
* overridden;
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual override returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_transfer(owner, to, 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}.
*
* NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
* `transferFrom`. This is semantically equivalent to an infinite approval.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_approve(owner, 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}.
*
* NOTE: Does not update the allowance if the current allowance
* is the maximum `uint256`.
*
* Requirements:
*
* - `from` and `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
* - the caller must have allowance for ``from``'s tokens of at least
* `amount`.
*/
function transferFrom(
address from,
address to,
uint256 amount
) public virtual override returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, 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) {
address owner = _msgSender();
_approve(owner, spender, _allowances[owner][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) {
address owner = _msgSender();
uint256 currentAllowance = _allowances[owner][spender];
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
/**
* @dev Moves `amount` of tokens from `sender` to `recipient`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
*/
function _transfer(
address from,
address to,
uint256 amount
) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
}
_balances[to] += amount;
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev Spend `amount` form the allowance of `owner` toward `spender`.
*
* Does not update the allowance amount in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Might emit an {Approval} event.
*/
function _spendAllowance(
address owner,
address spender,
uint256 amount
) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
/**
* @dev Hook that is called before any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* will be transferred to `to`.
* - when `from` is zero, `amount` tokens will be minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
/**
* @dev Hook that is called after any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* has been transferred to `to`.
* - when `from` is zero, `amount` tokens have been minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens have been burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}
// File: @openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Burnable.sol)
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 {
_spendAllowance(account, _msgSender(), amount);
_burn(account, amount);
}
}
// File: contracts/stableswap/LPToken.sol
pragma solidity >=0.8.0;
contract LPToken is Ownable, ERC20Burnable {
IStableSwap public swap;
constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {
swap = IStableSwap(msg.sender);
}
function mint(address _to, uint256 _amount) external onlyOwner {
require(_amount > 0, "zeroMintAmount");
_mint(_to, _amount);
}
}
// File: contracts/stableswap/interfaces/IStableSwapCallee.sol
pragma solidity >=0.8.0;
interface IStableSwapCallee {
function zenlinkStableSwapCall(
address sender,
IERC20[] memory tokens,
uint256[] memory amounts,
uint256[] memory fees,
bytes calldata data
) external;
}
// File: @openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol
// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
// File: contracts/stableswap/StableSwapStorage.sol
pragma solidity >=0.8.0;
/**
* StableSwap main algorithm
*/
library StableSwapStorage {
using SafeERC20 for IERC20;
event AddLiquidity(
address indexed provider,
uint256[] token_amounts,
uint256[] fees,
uint256 invariant,
uint256 token_supply
);
event FlashLoan(
address indexed caller,
address indexed receiver,
uint256[] amounts_out
);
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;
/// @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 calculate
uint256 internal constant MAX_ITERATION = 256;
uint256 public constant POOL_TOKEN_COMMON_DECIMALS = 18;
struct SwapStorage {
IERC20[] pooledTokens;
LPToken lpToken;
uint256[] tokenMultipliers; // token i multiplier to reach POOL_TOKEN_COMMON_DECIMALS
uint256[] balances; // effective balance which might different from token balance of the contract 'cause it hold admin fee as well
uint256 fee; // swap fee ratio. Charge on any action which move balance state far from the ideal state
uint256 adminFee; // admin fee in ratio of swap fee.
uint256 initialA; // observation of A, multiplied with A_PRECISION
uint256 futureA;
uint256 initialATime;
uint256 futureATime;
}
/**
* @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
if (amounts[i] > 0) {
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 flashLoan(
SwapStorage storage self,
uint256[] memory amountsOut,
address to,
bytes calldata data
) external {
uint256 nCoins = self.pooledTokens.length;
require(amountsOut.length == nCoins, "invalidAmountsLength");
{
uint256 tokenSupply = self.lpToken.totalSupply();
require(tokenSupply > 0, "insufficientLiquidity");
}
uint256[] memory fees = new uint256[](nCoins);
uint256 _fee = _feePerToken(self);
uint256 amp = _getAPrecise(self);
uint256 D0 = _getD(_xp(self.balances, self.tokenMultipliers), amp);
for (uint256 i = 0; i < nCoins; i++) {
if (amountsOut[i] > 0) {
require(amountsOut[i] < self.balances[i], "insufficientBalance");
fees[i] = (_fee * amountsOut[i]) / FEE_DENOMINATOR;
self.pooledTokens[i].safeTransfer(to, amountsOut[i]);
}
}
if (data.length > 0) {
IStableSwapCallee(to).zenlinkStableSwapCall(
msg.sender,
self.pooledTokens,
amountsOut,
fees,
data
);
}
uint256[] memory newBalances = self.balances;
for (uint256 i = 0; i < nCoins; i++) {
if (amountsOut[i] > 0) {
newBalances[i] += (_doTransferIn(self.pooledTokens[i], amountsOut[i] + fees[i]) - amountsOut[i]);
}
}
uint256 D1 = _getD(_xp(newBalances, self.tokenMultipliers), amp);
assert(D1 > D0);
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);
}
emit FlashLoan(msg.sender, to, amountsOut);
}
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; // just in case there were some rounding 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, 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, 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 += 1; // in case of rounding errors
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();
if (tokenSupply > 0) {
return (D * 10**POOL_TOKEN_COMMON_DECIMALS) / tokenSupply;
}
return 0;
}
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, uint256 amount)
external
view
returns (uint256[] memory)
{
return _calculateRemoveLiquidity(self, amount);
}
function calculateRemoveLiquidityOneToken(
SwapStorage storage self,
uint256 lpAmount,
uint256 tokenIndex
) external view returns (uint256 amount) {
(amount, ) = _calculateRemoveLiquidityOneToken(self, lpAmount, tokenIndex);
}
/// 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, uint256 amount)
internal
view
returns (uint256[] memory)
{
uint256 totalSupply = self.lpToken.totalSupply();
require(amount <= totalSupply, "Cannot exceed total supply");
uint256[] memory amounts = new uint256[](self.pooledTokens.length);
for (uint256 i = 0; i < self.pooledTokens.length; i++) {
amounts[i] = (self.balances[i] * (amount)) / (totalSupply);
}
return amounts;
}
function _calculateRemoveLiquidityOneToken(
SwapStorage storage self,
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;
}
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 _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;
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"provider","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"token_amounts","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"fees","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"invariant","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"token_supply","type":"uint256"}],"name":"AddLiquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"amounts_out","type":"uint256[]"}],"name":"FlashLoan","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"provider","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"token_amounts","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"fees","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"token_supply","type":"uint256"}],"name":"RemoveLiquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"provider","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"token_amounts","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"fees","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"invariant","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"token_supply","type":"uint256"}],"name":"RemoveLiquidityImbalance","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"provider","type":"address"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"token_amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"coin_amount","type":"uint256"}],"name":"RemoveLiquidityOne","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"uint256","name":"sold_id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokens_sold","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"bought_id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokens_bought","type":"uint256"}],"name":"TokenExchange","type":"event"},{"inputs":[],"name":"A_PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"POOL_TOKEN_COMMON_DECIMALS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]Contract Creation Code
613dce61003a600b82828239805160001a60731461002d57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106101155760003560e01c8063a5416c7b116100ac578063d0b1a0051161007b578063d0b1a00514610231578063d73792a91461025e578063e42f75fa1461026a578063ec623a1e1461028a578063f94eed871461029d57600080fd5b8063a5416c7b146101ec578063b9510fc81461020e578063c20aace814610221578063d011f9181461022957600080fd5b80634ddd2918116100e85780634ddd291814610186578063576b9735146101995780637461cf1b146101b95780638ce65d8e146101cc57600080fd5b80630a1368cd1461011a57806337ac5bea146101405780633a8d10bd1461015357806345b69ab714610173575b600080fd5b61012d6101283660046137d7565b6102b0565b6040519081526020015b60405180910390f35b61012d61014e366004613654565b6103a8565b81801561015f57600080fd5b5061012d61016e3660046138a7565b61048c565b61012d61018136600461372c565b61073b565b61012d610194366004613849565b610a62565b8180156101a557600080fd5b5061012d6101b4366004613787565b610a78565b61012d6101c7366004613654565b61105e565b8180156101d857600080fd5b5061012d6101e7366004613875565b611069565b8180156101f857600080fd5b5061020c61020736600461366d565b6113cf565b005b61012d61021c366004613654565b611ad8565b61012d601281565b61012d606481565b81801561023d57600080fd5b5061025161024c3660046137f9565b611aef565b6040516101379190613a19565b61012d6402540be40081565b81801561027657600080fd5b5061012d610285366004613787565b611da2565b61012d610298366004613875565b612400565b6102516102ab3660046137d7565b61250d565b815460009082106102dc5760405162461bcd60e51b81526004016102d390613b12565b60405180910390fd5b8260030182815481106102f1576102f1613d5b565b906000526020600020015483600001838154811061031157610311613d5b565b6000918252602090912001546040516370a0823160e01b81523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b15801561035d57600080fd5b505afa158015610371573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061039591906138e2565b61039f9190613cd1565b90505b92915050565b6000806103c56103b784612519565b6103c0856125c7565b6126a0565b905060008360010160009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561041957600080fd5b505afa15801561042d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061045191906138e2565b9050801561048257806104666012600a613c0a565b6104709084613cb2565b61047a9190613ba5565b949350505050565b5060009392505050565b6000808660000186815481106104a4576104a4613d5b565b60009182526020822001546001600160a01b031691506104c388612519565b90506104cf828661283c565b945060008860020188815481106104e8576104e8613d5b565b9060005260206000200154866104fe9190613cb2565b82898151811061051057610510613d5b565b60200260200101516105229190613b8d565b905060006105338a8a8a8587612952565b90506000600182858b8151811061054c5761054c613d5b565b602002602001015161055e9190613cd1565b6105689190613cd1565b905060006402540be4008c60040154836105829190613cb2565b61058c9190613ba5565b90508b6002018a815481106105a3576105a3613d5b565b906000526020600020015481836105ba9190613cd1565b6105c49190613ba5565b9150878210156105e65760405162461bcd60e51b81526004016102d390613b69565b60008c6002018b815481106105fd576105fd613d5b565b90600052602060002001546402540be4008e600501548461061e9190613cb2565b6106289190613ba5565b6106329190613ba5565b9050898d6003018d8154811061064a5761064a613d5b565b9060005260206000200160008282546106639190613b8d565b9091555061067390508184613b8d565b8d6003018c8154811061068857610688613d5b565b9060005260206000200160008282546106a19190613cd1565b925050819055506106de33848f6000018e815481106106c2576106c2613d5b565b6000918252602090912001546001600160a01b03169190612b84565b604080518d8152602081018c90529081018c90526060810184905233907fb2e76ae99761dc136e598d4a629bb347eccb9532a5f8bbd72e18467c3c34cc989060800160405180910390a25090955050505050505b95945050505050565b825482516000919081146107615760405162461bcd60e51b81526004016102d390613b3b565b600061076c866125c7565b9050600061078261077c88612519565b836126a0565b90506000876003018054806020026020016040519081016040528092919081815260200182805480156107d457602002820191906000526020600020905b8154815260200190600101908083116107c0575b5050505050905060005b8481101561088a578615610834578781815181106107fe576107fe613d5b565b602002602001015182828151811061081857610818613d5b565b6020026020010181815161082c9190613b8d565b905250610878565b87818151811061084657610846613d5b565b602002602001015182828151811061086057610860613d5b565b602002602001018181516108749190613cd1565b9052505b8061088281613d14565b9150506107de565b5060006108f26108ec838b6002018054806020026020016040519081016040528092919081815260200182805480156108e257602002820191906000526020600020905b8154815260200190600101908083116108ce575b5050505050612bec565b856126a0565b905060008960010160009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561094657600080fd5b505afa15801561095a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097e91906138e2565b90508061099257509450610a5b9350505050565b6000886109a8576109a38386613cd1565b6109b2565b6109b28584613cd1565b9050848b60010160009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610a0557600080fd5b505afa158015610a19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3d91906138e2565b610a479083613cb2565b610a519190613ba5565b9750505050505050505b9392505050565b6000610a6f848484612c6f565b50949350505050565b82548251600091908114610a9e5760405162461bcd60e51b81526004016102d390613b3b565b6001850154604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b158015610ae557600080fd5b505afa158015610af9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b1d91906138e2565b905080610b5e5760405162461bcd60e51b815260206004820152600f60248201526e0746f74616c537570706c79203d203608c1b60448201526064016102d3565b6000610b6987612f63565b90506000610b76886125c7565b9050600088600301805480602002602001604051908101604052809291908181526020018280548015610bc857602002820191906000526020600020905b815481526020019060010190808311610bb4575b505050505090506000610be3610bdd8b612519565b846126a0565b905060005b86811015610c4557898181518110610c0257610c02613d5b565b6020026020010151838281518110610c1c57610c1c613d5b565b60200260200101818151610c309190613cd1565b90525080610c3d81613d14565b915050610be8565b506000610ca56108ec848d6002018054806020026020016040519081016040528092919081815260200182805480156108e257602002820191906000526020600020908154815260200190600101908083116108ce575050505050612bec565b905060008767ffffffffffffffff811115610cc257610cc2613d71565b604051908082528060200260200182016040528015610ceb578160200160208202803683370190505b50905060005b88811015610e6b576000848e6003018381548110610d1157610d11613d5b565b906000526020600020015485610d279190613cb2565b610d319190613ba5565b90506000610d58878481518110610d4a57610d4a613d5b565b602002602001015183612f98565b90506402540be400610d6a828b613cb2565b610d749190613ba5565b848481518110610d8657610d86613d5b565b6020026020010181815250506402540be4008f60050154858581518110610daf57610daf613d5b565b6020026020010151610dc19190613cb2565b610dcb9190613ba5565b878481518110610ddd57610ddd613d5b565b6020026020010151610def9190613cd1565b8f6003018481548110610e0457610e04613d5b565b9060005260206000200181905550838381518110610e2457610e24613d5b565b6020026020010151878481518110610e3e57610e3e613d5b565b60200260200101818151610e529190613cd1565b905250829150610e63905081613d14565b915050610cf1565b50610ecf610ec9858e6002018054806020026020016040519081016040528092919081815260200182805480156108e257602002820191906000526020600020908154815260200190600101908083116108ce575050505050612bec565b866126a0565b91508287610edd8483613cd1565b610ee79190613cb2565b610ef19190613ba5565b985060008911610f0357610f03613d2f565b610f0e60018a613b8d565b985089891115610f305760405162461bcd60e51b81526004016102d390613b69565b60018c015460405163079cc67960e41b8152336004820152602481018b90526001600160a01b03909116906379cc679090604401600060405180830381600087803b158015610f7e57600080fd5b505af1158015610f92573d6000803e3d6000fd5b5050505060005b88811015611007578b8181518110610fb357610fb3613d5b565b6020026020010151600014610ff557610ff5338d8381518110610fd857610fd8613d5b565b60200260200101518f60000184815481106106c2576106c2613d5b565b80610fff81613d14565b915050610f99565b50337f3631c28b1f9dd213e0319fb167b554d76b6c283a41143eb400a0d1adb1af17558c83856110378e8d613cd1565b6040516110479493929190613aa6565b60405180910390a250505050505050509392505050565b60006103a2826125c7565b6000808560010160009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156110bc57600080fd5b505afa1580156110d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f491906138e2565b9050600081116111385760405162461bcd60e51b815260206004820152600f60248201526e0746f74616c537570706c79203d203608c1b60448201526064016102d3565b855460018701546040516370a0823160e01b81523360048201526001600160a01b03909116906370a082319060240160206040518083038186803b15801561117f57600080fd5b505afa158015611193573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111b791906138e2565b8611156111f25760405162461bcd60e51b81526020600482015260096024820152683e2062616c616e636560b81b60448201526064016102d3565b818611156112325760405162461bcd60e51b815260206004820152600d60248201526c3e20746f74616c537570706c7960981b60448201526064016102d3565b8085106112715760405162461bcd60e51b815260206004820152600d60248201526c1d1bdad95b939bdd119bdd5b99609a1b60448201526064016102d3565b60008061127f898989612c6f565b92509050858110156112a35760405162461bcd60e51b81526004016102d390613b69565b6402540be4008960050154836112b99190613cb2565b6112c39190613ba5565b6112cd9082613b8d565b8960030188815481106112e2576112e2613d5b565b9060005260206000200160008282546112fb9190613cd1565b9091555050600189015460405163079cc67960e41b8152336004820152602481018a90526001600160a01b03909116906379cc679090604401600060405180830381600087803b15801561134e57600080fd5b505af1158015611362573d6000803e3d6000fd5b5050505061138033828b6000018a815481106106c2576106c2613d5b565b60408051888152602081018a905290810182905233907f5ad056f2e28a8cec232015406b843668c1e36cda598127ec3b8c59b8c72773a09060600160405180910390a298975050505050505050565b8454845181146113f15760405162461bcd60e51b81526004016102d390613b3b565b6001860154604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b15801561143857600080fd5b505afa15801561144c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147091906138e2565b9050600081116114ba5760405162461bcd60e51b8152602060048201526015602482015274696e73756666696369656e744c697175696469747960581b60448201526064016102d3565b5060008167ffffffffffffffff8111156114d6576114d6613d71565b6040519080825280602002602001820160405280156114ff578160200160208202803683370190505b509050600061150d88612f63565b9050600061151a896125c7565b905060006115cd61077c8b60030180548060200260200160405190810160405280929190818152602001828054801561157257602002820191906000526020600020905b81548152602001906001019080831161155e575b50505050508c6002018054806020026020016040519081016040528092919081815260200182805480156108e257602002820191906000526020600020908154815260200190600101908083116108ce575050505050612bec565b905060005b858110156117115760008a82815181106115ee576115ee613d5b565b602002602001015111156116ff578a600301818154811061161157611611613d5b565b90600052602060002001548a828151811061162e5761162e613d5b565b6020026020010151106116795760405162461bcd60e51b8152602060048201526013602482015272696e73756666696369656e7442616c616e636560681b60448201526064016102d3565b6402540be4008a828151811061169157611691613d5b565b6020026020010151856116a49190613cb2565b6116ae9190613ba5565b8582815181106116c0576116c0613d5b565b6020026020010181815250506116ff898b83815181106116e2576116e2613d5b565b60200260200101518d60000184815481106106c2576106c2613d5b565b8061170981613d14565b9150506115d2565b508515611781576040516366f9eaab60e01b81526001600160a01b038916906366f9eaab9061174e9033908e908e908a908e908e9060040161397b565b600060405180830381600087803b15801561176857600080fd5b505af115801561177c573d6000803e3d6000fd5b505050505b60008a6003018054806020026020016040519081016040528092919081815260200182805480156117d157602002820191906000526020600020905b8154815260200190600101908083116117bd575b5050505050905060005b868110156118de5760008b82815181106117f7576117f7613d5b565b602002602001015111156118cc578a818151811061181757611817613d5b565b60200260200101516118988d600001838154811061183757611837613d5b565b9060005260206000200160009054906101000a90046001600160a01b031688848151811061186757611867613d5b565b60200260200101518e858151811061188157611881613d5b565b60200260200101516118939190613b8d565b61283c565b6118a29190613cd1565b8282815181106118b4576118b4613d5b565b602002602001018181516118c89190613b8d565b9052505b806118d681613d14565b9150506117db565b50600061193e6108ec838e6002018054806020026020016040519081016040528092919081815260200182805480156108e257602002820191906000526020600020908154815260200190600101908083116108ce575050505050612bec565b905082811161194f5761194f613d2f565b6000805b88811015611a7d576119b3858f600301838154811061197457611974613d5b565b90600052602060002001548561198a9190613cb2565b6119949190613ba5565b8583815181106119a6576119a6613d5b565b6020026020010151612f98565b91506402540be4006119c58389613cb2565b6119cf9190613ba5565b8882815181106119e1576119e1613d5b565b6020026020010181815250506402540be4008e60050154898381518110611a0a57611a0a613d5b565b6020026020010151611a1c9190613cb2565b611a269190613ba5565b848281518110611a3857611a38613d5b565b6020026020010151611a4a9190613cd1565b8e6003018281548110611a5f57611a5f613d5b565b60009182526020909120015580611a7581613d14565b915050611953565b508a6001600160a01b0316336001600160a01b03167f1e659566d9cc1f93351027d53422a1ec429f52c34bc45ee462dd91e99bdd26bb8e604051611ac19190613a5d565b60405180910390a350505050505050505050505050565b60006064611ae5836125c7565b6103a29190613ba5565b606060008460010160009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611b4357600080fd5b505afa158015611b57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b7b91906138e2565b905080841115611b8a57600080fd5b845460008167ffffffffffffffff811115611ba757611ba7613d71565b604051908082528060200260200182016040528015611bd0578160200160208202803683370190505b509050611bdd8787612fba565b935060005b8451811015611ce957858181518110611bfd57611bfd613d5b565b6020026020010151858281518110611c1757611c17613d5b565b60200260200101511015611c3d5760405162461bcd60e51b81526004016102d390613b69565b848181518110611c4f57611c4f613d5b565b6020026020010151886003018281548110611c6c57611c6c613d5b565b9060005260206000200154611c819190613cd1565b886003018281548110611c9657611c96613d5b565b9060005260206000200181905550611cd733868381518110611cba57611cba613d5b565b60200260200101518a60000184815481106106c2576106c2613d5b565b80611ce181613d14565b915050611be2565b50600187015460405163079cc67960e41b8152336004820152602481018890526001600160a01b03909116906379cc679090604401600060405180830381600087803b158015611d3857600080fd5b505af1158015611d4c573d6000803e3d6000fd5b503392507f347ad828e58cbe534d8f6b67985d791360756b18f0d95fd9f197a66cc46480ea915086905083611d818a88613cd1565b604051611d9093929190613a70565b60405180910390a25050509392505050565b82548251600091908114611dc85760405162461bcd60e51b81526004016102d390613b3b565b60008167ffffffffffffffff811115611de357611de3613d71565b604051908082528060200260200182016040528015611e0c578160200160208202803683370190505b5090506000611e1a87612f63565b905060008760010160009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611e6e57600080fd5b505afa158015611e82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ea691906138e2565b90506000611eb3896125c7565b905060008215611f6d57611f6a61077c8b600301805480602002602001604051908101604052809291908181526020018280548015611572576020028201919060005260206000209081548152602001906001019080831161155e5750505050508c6002018054806020026020016040519081016040528092919081815260200182805480156108e257602002820191906000526020600020908154815260200190600101908083116108ce575050505050612bec565b90505b60008a600301805480602002602001604051908101604052809291908181526020018280548015611fbd57602002820191906000526020600020905b815481526020019060010190808311611fa9575b5050505050905060005b878110156120f0578461203d5760008b8281518110611fe857611fe8613d5b565b60200260200101511161203d5760405162461bcd60e51b815260206004820152601e60248201527f696e697469616c4465706f73697452657175697265416c6c546f6b656e73000060448201526064016102d3565b60008b828151811061205157612051613d5b565b602002602001015111156120de576120b48c600001828154811061207757612077613d5b565b9060005260206000200160009054906101000a90046001600160a01b03168c83815181106120a7576120a7613d5b565b602002602001015161283c565b8282815181106120c6576120c6613d5b565b602002602001018181516120da9190613b8d565b9052505b806120e881613d14565b915050611fc7565b5060006121506108ec838e6002018054806020026020016040519081016040528092919081815260200182805480156108e257602002820191906000526020600020908154815260200190600101908083116108ce575050505050612bec565b905082811161216157612161613d2f565b8461218457815161217b9060038e01906020850190613536565b5080985061233b565b6000805b898110156122b8576121a9858f600301838154811061197457611974613d5b565b91506402540be4006121bb838a613cb2565b6121c59190613ba5565b8982815181106121d7576121d7613d5b565b6020026020010181815250506402540be4008e600501548a838151811061220057612200613d5b565b60200260200101516122129190613cb2565b61221c9190613ba5565b84828151811061222e5761222e613d5b565b60200260200101516122409190613cd1565b8e600301828154811061225557612255613d5b565b906000526020600020018190555088818151811061227557612275613d5b565b602002602001015184828151811061228f5761228f613d5b565b602002602001018181516122a39190613cd1565b905250806122b081613d14565b915050612188565b50612316610ec9848f6002018054806020026020016040519081016040528092919081815260200182805480156108e257602002820191906000526020600020908154815260200190600101908083116108ce575050505050612bec565b9150836123238184613cd1565b61232d9088613cb2565b6123379190613ba5565b9950505b8989101561235b5760405162461bcd60e51b81526004016102d390613b69565b60018c01546040516340c10f1960e01b8152336004820152602481018b90526001600160a01b03909116906340c10f1990604401600060405180830381600087803b1580156123a957600080fd5b505af11580156123bd573d6000803e3d6000fd5b50505050336001600160a01b03167f189c623b666b1b45b83d7178f39b8c087cb09774317ca2f53c2d3c3726f222a28c89848d6040516110479493929190613aa6565b60008061240c86612519565b9050600086600201868154811061242557612425613d5b565b90600052602060002001548461243b9190613cb2565b82878151811061244d5761244d613d5b565b602002602001015161245f9190613b8d565b905060006124708888888587612952565b9050600088600201878154811061248957612489613d5b565b9060005260206000200154600183868a815181106124a9576124a9613d5b565b60200260200101516124bb9190613cd1565b6124c59190613cd1565b6124cf9190613ba5565b905060006402540be400828b600401546124e99190613cb2565b6124f39190613ba5565b90506124ff8183613cd1565b9a9950505050505050505050565b606061039f8383612fba565b60606103a28260030180548060200260200160405190810160405280929190818152602001828054801561256c57602002820191906000526020600020905b815481526020019060010190808311612558575b5050505050836002018054806020026020016040519081016040528092919081815260200182805480156108e257602002820191906000526020600020908154815260200190600101908083116108ce575050505050612bec565b6000816009015442106125dc57506007015490565b81600601548260070154111561264657816008015482600901546126009190613cd1565b600883015461260f9042613cd1565b836006015484600701546126239190613cd1565b61262d9190613cb2565b6126379190613ba5565b82600601546103a29190613b8d565b8160080154826009015461265a9190613cd1565b60088301546126699042613cd1565b8360070154846006015461267d9190613cd1565b6126879190613cb2565b6126919190613ba5565b82600601546103a29190613cd1565b8151600090816126af85613152565b9050806126c1576000925050506103a2565b600081816126cf8588613cb2565b905060005b6101008110156127f3578260005b8a5181101561273857878b82815181106126fe576126fe613d5b565b60200260200101516127109190613cb2565b61271a8684613cb2565b6127249190613ba5565b91508061273081613d14565b9150506126e2565b508394508087600161274a9190613b8d565b6127549190613cb2565b6064856127618287613cd1565b61276b9190613cb2565b6127759190613ba5565b61277f9190613b8d565b8461278a8984613cb2565b60646127968a88613cb2565b6127a09190613ba5565b6127aa9190613b8d565b6127b49190613cb2565b6127be9190613ba5565b935060016127cc8587612f98565b116127e057839750505050505050506103a2565b50806127eb81613d14565b9150506126d4565b5060405162461bcd60e51b815260206004820152601a60248201527f696e76617269616e7443616c63756c6174696f6e4661696c656400000000000060448201526064016102d3565b6040516370a0823160e01b815230600482015260009081906001600160a01b038516906370a082319060240160206040518083038186803b15801561288057600080fd5b505afa158015612894573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128b891906138e2565b90506128cf6001600160a01b03851633308661319e565b6040516370a0823160e01b815230600482015281906001600160a01b038616906370a082319060240160206040518083038186803b15801561291057600080fd5b505afa158015612924573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061294891906138e2565b61047a9190613cd1565b6000838514156129905760405162461bcd60e51b815260206004820152600960248201526839b0b6b2aa37b5b2b760b91b60448201526064016102d3565b855480861080156129a057508085105b6129bc5760405162461bcd60e51b81526004016102d390613b12565b60006129c7886125c7565b905060006129d58383613cb2565b905060006129e386846126a0565b9050600081815b86811015612a6b578a8114156129ff57612a59565b60008c8214612a2757898281518110612a1a57612a1a613d5b565b6020026020010151612a29565b8a5b9050612a358185613b8d565b9350612a418882613cb2565b612a4b8685613cb2565b612a559190613ba5565b9250505b80612a6381613d14565b9150506129ea565b50612a768685613cb2565b6064612a828584613cb2565b612a8c9190613cb2565b612a969190613ba5565b9050600084612aa6606486613cb2565b612ab09190613ba5565b612aba9084613b8d565b9050600084815b610100811015612b46578192508684836002612add9190613cb2565b612ae79190613b8d565b612af19190613cd1565b85612afc8480613cb2565b612b069190613b8d565b612b109190613ba5565b91506001612b1e8484612f98565b11612b3457509850610732975050505050505050565b80612b3e81613d14565b915050612ac1565b5060405162461bcd60e51b81526020600482015260126024820152711e50d85b18dd5b185d1a5bdb91985a5b195960721b60448201526064016102d3565b6040516001600160a01b038316602482015260448101829052612be790849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526131dc565b505050565b606060005b8351811015612c6757838181518110612c0c57612c0c613d5b565b6020026020010151838281518110612c2657612c26613d5b565b6020026020010151612c389190613cb2565b838281518110612c4a57612c4a613d5b565b602090810291909101015280612c5f81613d14565b915050612bf1565b509092915050565b825460009081908310612c945760405162461bcd60e51b81526004016102d390613b12565b6000612c9f866125c7565b90506000612cac87612519565b90506000612cba82846126a0565b905060008860010160009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015612d0e57600080fd5b505afa158015612d22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4691906138e2565b612d50838a613cb2565b612d5a9190613ba5565b612d649083613cd1565b90506000612d758a868a87866132ae565b9050836000612d838c612f63565b905060005b8c54811015612e8b5760008b821415612ddd578487878a8581518110612db057612db0613d5b565b6020026020010151612dc29190613cb2565b612dcc9190613ba5565b612dd69190613cd1565b9050612e34565b8686898481518110612df157612df1613d5b565b6020026020010151612e039190613cb2565b612e0d9190613ba5565b888381518110612e1f57612e1f613d5b565b6020026020010151612e319190613cd1565b90505b6402540be400612e448285613cb2565b612e4e9190613ba5565b848381518110612e6057612e60613d5b565b60200260200101818151612e749190613cd1565b905250819050612e8381613d14565b915050612d88565b50612e998c888c85886132ae565b828b81518110612eab57612eab613d5b565b6020026020010151612ebd9190613cd1565b98508b6002018a81548110612ed457612ed4613d5b565b906000526020600020015460018a612eec9190613cd1565b612ef69190613ba5565b9850888c6002018b81548110612f0e57612f0e613d5b565b906000526020600020015484888d81518110612f2c57612f2c613d5b565b6020026020010151612f3e9190613cd1565b612f489190613ba5565b612f529190613cd1565b975050505050505050935093915050565b8054600090612f73600182613cd1565b612f7e906004613cb2565b818460040154612f8e9190613cb2565b610a5b9190613ba5565b6000818311612fb057612fab8383613cd1565b61039f565b61039f8284613cd1565b606060008360010160009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561300e57600080fd5b505afa158015613022573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061304691906138e2565b9050808311156130985760405162461bcd60e51b815260206004820152601a60248201527f43616e6e6f742065786365656420746f74616c20737570706c7900000000000060448201526064016102d3565b835460009067ffffffffffffffff8111156130b5576130b5613d71565b6040519080825280602002602001820160405280156130de578160200160208202803683370190505b50905060005b8554811015610a6f57828587600301838154811061310457613104613d5b565b90600052602060002001546131199190613cb2565b6131239190613ba5565b82828151811061313557613135613d5b565b60209081029190910101528061314a81613d14565b9150506130e4565b6000805b82518110156131985782818151811061317157613171613d5b565b6020026020010151826131849190613b8d565b91508061319081613d14565b915050613156565b50919050565b6040516001600160a01b03808516602483015283166044820152606481018290526131d69085906323b872dd60e01b90608401612bb0565b50505050565b6000613231826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166134229092919063ffffffff16565b805190915015612be7578080602001905181019061324f9190613637565b612be75760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016102d3565b84546000908085106132c2576132c2613d2f565b60006132ce8288613cb2565b90508360008080805b86811015613349578a8114156132ec57613337565b8981815181106132fe576132fe613d5b565b6020026020010151925082846133149190613b8d565b93506133208784613cb2565b61332a8a87613cb2565b6133349190613ba5565b94505b8061334181613d14565b9150506132d7565b506133548686613cb2565b60646133608a87613cb2565b61336a9190613cb2565b6133749190613ba5565b935060008561338460648b613cb2565b61338e9190613ba5565b6133989085613b8d565b90508860005b6101008110156127f3578193508a838360026133ba9190613cb2565b6133c49190613b8d565b6133ce9190613cd1565b876133d98480613cb2565b6133e39190613b8d565b6133ed9190613ba5565b915060016133fb8584612f98565b11613410575097506107329650505050505050565b8061341a81613d14565b91505061339e565b606061047a8484600085856001600160a01b0385163b6134845760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102d3565b600080866001600160a01b031685876040516134a0919061395f565b60006040518083038185875af1925050503d80600081146134dd576040519150601f19603f3d011682016040523d82523d6000602084013e6134e2565b606091505b50915091506134f28282866134fd565b979650505050505050565b6060831561350c575081610a5b565b82511561351c5782518084602001fd5b8160405162461bcd60e51b81526004016102d39190613adf565b828054828255906000526020600020908101928215613571579160200282015b82811115613571578251825591602001919060010190613556565b5061357d929150613581565b5090565b5b8082111561357d5760008155600101613582565b600082601f8301126135a757600080fd5b8135602067ffffffffffffffff808311156135c4576135c4613d71565b8260051b604051601f19603f830116810181811084821117156135e9576135e9613d71565b6040528481528381019250868401828801850189101561360857600080fd5b600092505b8583101561362b57803584529284019260019290920191840161360d565b50979650505050505050565b60006020828403121561364957600080fd5b8151610a5b81613d87565b60006020828403121561366657600080fd5b5035919050565b60008060008060006080868803121561368557600080fd5b85359450602086013567ffffffffffffffff808211156136a457600080fd5b6136b089838a01613596565b9550604088013591506001600160a01b03821682146136ce57600080fd5b909350606087013590808211156136e457600080fd5b818801915088601f8301126136f857600080fd5b81358181111561370757600080fd5b89602082850101111561371957600080fd5b9699959850939650602001949392505050565b60008060006060848603121561374157600080fd5b83359250602084013567ffffffffffffffff81111561375f57600080fd5b61376b86828701613596565b925050604084013561377c81613d87565b809150509250925092565b60008060006060848603121561379c57600080fd5b83359250602084013567ffffffffffffffff8111156137ba57600080fd5b6137c686828701613596565b925050604084013590509250925092565b600080604083850312156137ea57600080fd5b50508035926020909101359150565b60008060006060848603121561380e57600080fd5b8335925060208401359150604084013567ffffffffffffffff81111561383357600080fd5b61383f86828701613596565b9150509250925092565b60008060006060848603121561385e57600080fd5b505081359360208301359350604090920135919050565b6000806000806080858703121561388b57600080fd5b5050823594602084013594506040840135936060013592509050565b600080600080600060a086880312156138bf57600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b6000602082840312156138f457600080fd5b5051919050565b600081518084526020808501945080840160005b8381101561392b5781518752958201959082019060010161390f565b509495945050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60008251613971818460208701613ce8565b9190910192915050565b600060a0820160018060a01b03808a168452602060a081860152828a5480855260c0870191508b60005282600020945060005b818110156139cc5785548516835260019586019592840192016139ae565b505085810360408701526139e0818b6138fb565b935050505082810360608401526139f781876138fb565b90508281036080840152613a0c818587613936565b9998505050505050505050565b6020808252825182820181905260009190848201906040850190845b81811015613a5157835183529284019291840191600101613a35565b50909695505050505050565b60208152600061039f60208301846138fb565b606081526000613a8360608301866138fb565b8281036020840152613a9581866138fb565b915050826040830152949350505050565b608081526000613ab960808301876138fb565b8281036020840152613acb81876138fb565b604084019590955250506060015292915050565b6020815260008251806020840152613afe816040850160208701613ce8565b601f01601f19169190910160400192915050565b6020808252600f908201526e696e6465784f75744f6652616e676560881b604082015260600190565b6020808252601490820152730d2dcecc2d8d2c882dadeeadce8e698cadccee8d60631b604082015260600190565b6020808252600a90820152693e20736c69707061676560b01b604082015260600190565b60008219821115613ba057613ba0613d45565b500190565b600082613bc257634e487b7160e01b600052601260045260246000fd5b500490565b600181815b80851115613c02578160001904821115613be857613be8613d45565b80851615613bf557918102915b93841c9390800290613bcc565b509250929050565b600061039f8383600082613c20575060016103a2565b81613c2d575060006103a2565b8160018114613c435760028114613c4d57613c69565b60019150506103a2565b60ff841115613c5e57613c5e613d45565b50506001821b6103a2565b5060208310610133831016604e8410600b8410161715613c8c575081810a6103a2565b613c968383613bc7565b8060001904821115613caa57613caa613d45565b029392505050565b6000816000190483118215151615613ccc57613ccc613d45565b500290565b600082821015613ce357613ce3613d45565b500390565b60005b83811015613d03578181015183820152602001613ceb565b838111156131d65750506000910152565b6000600019821415613d2857613d28613d45565b5060010190565b634e487b7160e01b600052600160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b8015158114613d9557600080fd5b5056fea264697066735822122057a1863b038e4fd3218ca5368ab559266e254a8a019bdaf7dc908a5ef1b90a8764736f6c63430008070033
Deployed Bytecode
0x736dcdda63631201f83c89e459621dac6e244e97f230146080604052600436106101155760003560e01c8063a5416c7b116100ac578063d0b1a0051161007b578063d0b1a00514610231578063d73792a91461025e578063e42f75fa1461026a578063ec623a1e1461028a578063f94eed871461029d57600080fd5b8063a5416c7b146101ec578063b9510fc81461020e578063c20aace814610221578063d011f9181461022957600080fd5b80634ddd2918116100e85780634ddd291814610186578063576b9735146101995780637461cf1b146101b95780638ce65d8e146101cc57600080fd5b80630a1368cd1461011a57806337ac5bea146101405780633a8d10bd1461015357806345b69ab714610173575b600080fd5b61012d6101283660046137d7565b6102b0565b6040519081526020015b60405180910390f35b61012d61014e366004613654565b6103a8565b81801561015f57600080fd5b5061012d61016e3660046138a7565b61048c565b61012d61018136600461372c565b61073b565b61012d610194366004613849565b610a62565b8180156101a557600080fd5b5061012d6101b4366004613787565b610a78565b61012d6101c7366004613654565b61105e565b8180156101d857600080fd5b5061012d6101e7366004613875565b611069565b8180156101f857600080fd5b5061020c61020736600461366d565b6113cf565b005b61012d61021c366004613654565b611ad8565b61012d601281565b61012d606481565b81801561023d57600080fd5b5061025161024c3660046137f9565b611aef565b6040516101379190613a19565b61012d6402540be40081565b81801561027657600080fd5b5061012d610285366004613787565b611da2565b61012d610298366004613875565b612400565b6102516102ab3660046137d7565b61250d565b815460009082106102dc5760405162461bcd60e51b81526004016102d390613b12565b60405180910390fd5b8260030182815481106102f1576102f1613d5b565b906000526020600020015483600001838154811061031157610311613d5b565b6000918252602090912001546040516370a0823160e01b81523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b15801561035d57600080fd5b505afa158015610371573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061039591906138e2565b61039f9190613cd1565b90505b92915050565b6000806103c56103b784612519565b6103c0856125c7565b6126a0565b905060008360010160009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561041957600080fd5b505afa15801561042d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061045191906138e2565b9050801561048257806104666012600a613c0a565b6104709084613cb2565b61047a9190613ba5565b949350505050565b5060009392505050565b6000808660000186815481106104a4576104a4613d5b565b60009182526020822001546001600160a01b031691506104c388612519565b90506104cf828661283c565b945060008860020188815481106104e8576104e8613d5b565b9060005260206000200154866104fe9190613cb2565b82898151811061051057610510613d5b565b60200260200101516105229190613b8d565b905060006105338a8a8a8587612952565b90506000600182858b8151811061054c5761054c613d5b565b602002602001015161055e9190613cd1565b6105689190613cd1565b905060006402540be4008c60040154836105829190613cb2565b61058c9190613ba5565b90508b6002018a815481106105a3576105a3613d5b565b906000526020600020015481836105ba9190613cd1565b6105c49190613ba5565b9150878210156105e65760405162461bcd60e51b81526004016102d390613b69565b60008c6002018b815481106105fd576105fd613d5b565b90600052602060002001546402540be4008e600501548461061e9190613cb2565b6106289190613ba5565b6106329190613ba5565b9050898d6003018d8154811061064a5761064a613d5b565b9060005260206000200160008282546106639190613b8d565b9091555061067390508184613b8d565b8d6003018c8154811061068857610688613d5b565b9060005260206000200160008282546106a19190613cd1565b925050819055506106de33848f6000018e815481106106c2576106c2613d5b565b6000918252602090912001546001600160a01b03169190612b84565b604080518d8152602081018c90529081018c90526060810184905233907fb2e76ae99761dc136e598d4a629bb347eccb9532a5f8bbd72e18467c3c34cc989060800160405180910390a25090955050505050505b95945050505050565b825482516000919081146107615760405162461bcd60e51b81526004016102d390613b3b565b600061076c866125c7565b9050600061078261077c88612519565b836126a0565b90506000876003018054806020026020016040519081016040528092919081815260200182805480156107d457602002820191906000526020600020905b8154815260200190600101908083116107c0575b5050505050905060005b8481101561088a578615610834578781815181106107fe576107fe613d5b565b602002602001015182828151811061081857610818613d5b565b6020026020010181815161082c9190613b8d565b905250610878565b87818151811061084657610846613d5b565b602002602001015182828151811061086057610860613d5b565b602002602001018181516108749190613cd1565b9052505b8061088281613d14565b9150506107de565b5060006108f26108ec838b6002018054806020026020016040519081016040528092919081815260200182805480156108e257602002820191906000526020600020905b8154815260200190600101908083116108ce575b5050505050612bec565b856126a0565b905060008960010160009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561094657600080fd5b505afa15801561095a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097e91906138e2565b90508061099257509450610a5b9350505050565b6000886109a8576109a38386613cd1565b6109b2565b6109b28584613cd1565b9050848b60010160009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610a0557600080fd5b505afa158015610a19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3d91906138e2565b610a479083613cb2565b610a519190613ba5565b9750505050505050505b9392505050565b6000610a6f848484612c6f565b50949350505050565b82548251600091908114610a9e5760405162461bcd60e51b81526004016102d390613b3b565b6001850154604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b158015610ae557600080fd5b505afa158015610af9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b1d91906138e2565b905080610b5e5760405162461bcd60e51b815260206004820152600f60248201526e0746f74616c537570706c79203d203608c1b60448201526064016102d3565b6000610b6987612f63565b90506000610b76886125c7565b9050600088600301805480602002602001604051908101604052809291908181526020018280548015610bc857602002820191906000526020600020905b815481526020019060010190808311610bb4575b505050505090506000610be3610bdd8b612519565b846126a0565b905060005b86811015610c4557898181518110610c0257610c02613d5b565b6020026020010151838281518110610c1c57610c1c613d5b565b60200260200101818151610c309190613cd1565b90525080610c3d81613d14565b915050610be8565b506000610ca56108ec848d6002018054806020026020016040519081016040528092919081815260200182805480156108e257602002820191906000526020600020908154815260200190600101908083116108ce575050505050612bec565b905060008767ffffffffffffffff811115610cc257610cc2613d71565b604051908082528060200260200182016040528015610ceb578160200160208202803683370190505b50905060005b88811015610e6b576000848e6003018381548110610d1157610d11613d5b565b906000526020600020015485610d279190613cb2565b610d319190613ba5565b90506000610d58878481518110610d4a57610d4a613d5b565b602002602001015183612f98565b90506402540be400610d6a828b613cb2565b610d749190613ba5565b848481518110610d8657610d86613d5b565b6020026020010181815250506402540be4008f60050154858581518110610daf57610daf613d5b565b6020026020010151610dc19190613cb2565b610dcb9190613ba5565b878481518110610ddd57610ddd613d5b565b6020026020010151610def9190613cd1565b8f6003018481548110610e0457610e04613d5b565b9060005260206000200181905550838381518110610e2457610e24613d5b565b6020026020010151878481518110610e3e57610e3e613d5b565b60200260200101818151610e529190613cd1565b905250829150610e63905081613d14565b915050610cf1565b50610ecf610ec9858e6002018054806020026020016040519081016040528092919081815260200182805480156108e257602002820191906000526020600020908154815260200190600101908083116108ce575050505050612bec565b866126a0565b91508287610edd8483613cd1565b610ee79190613cb2565b610ef19190613ba5565b985060008911610f0357610f03613d2f565b610f0e60018a613b8d565b985089891115610f305760405162461bcd60e51b81526004016102d390613b69565b60018c015460405163079cc67960e41b8152336004820152602481018b90526001600160a01b03909116906379cc679090604401600060405180830381600087803b158015610f7e57600080fd5b505af1158015610f92573d6000803e3d6000fd5b5050505060005b88811015611007578b8181518110610fb357610fb3613d5b565b6020026020010151600014610ff557610ff5338d8381518110610fd857610fd8613d5b565b60200260200101518f60000184815481106106c2576106c2613d5b565b80610fff81613d14565b915050610f99565b50337f3631c28b1f9dd213e0319fb167b554d76b6c283a41143eb400a0d1adb1af17558c83856110378e8d613cd1565b6040516110479493929190613aa6565b60405180910390a250505050505050509392505050565b60006103a2826125c7565b6000808560010160009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156110bc57600080fd5b505afa1580156110d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f491906138e2565b9050600081116111385760405162461bcd60e51b815260206004820152600f60248201526e0746f74616c537570706c79203d203608c1b60448201526064016102d3565b855460018701546040516370a0823160e01b81523360048201526001600160a01b03909116906370a082319060240160206040518083038186803b15801561117f57600080fd5b505afa158015611193573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111b791906138e2565b8611156111f25760405162461bcd60e51b81526020600482015260096024820152683e2062616c616e636560b81b60448201526064016102d3565b818611156112325760405162461bcd60e51b815260206004820152600d60248201526c3e20746f74616c537570706c7960981b60448201526064016102d3565b8085106112715760405162461bcd60e51b815260206004820152600d60248201526c1d1bdad95b939bdd119bdd5b99609a1b60448201526064016102d3565b60008061127f898989612c6f565b92509050858110156112a35760405162461bcd60e51b81526004016102d390613b69565b6402540be4008960050154836112b99190613cb2565b6112c39190613ba5565b6112cd9082613b8d565b8960030188815481106112e2576112e2613d5b565b9060005260206000200160008282546112fb9190613cd1565b9091555050600189015460405163079cc67960e41b8152336004820152602481018a90526001600160a01b03909116906379cc679090604401600060405180830381600087803b15801561134e57600080fd5b505af1158015611362573d6000803e3d6000fd5b5050505061138033828b6000018a815481106106c2576106c2613d5b565b60408051888152602081018a905290810182905233907f5ad056f2e28a8cec232015406b843668c1e36cda598127ec3b8c59b8c72773a09060600160405180910390a298975050505050505050565b8454845181146113f15760405162461bcd60e51b81526004016102d390613b3b565b6001860154604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b15801561143857600080fd5b505afa15801561144c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147091906138e2565b9050600081116114ba5760405162461bcd60e51b8152602060048201526015602482015274696e73756666696369656e744c697175696469747960581b60448201526064016102d3565b5060008167ffffffffffffffff8111156114d6576114d6613d71565b6040519080825280602002602001820160405280156114ff578160200160208202803683370190505b509050600061150d88612f63565b9050600061151a896125c7565b905060006115cd61077c8b60030180548060200260200160405190810160405280929190818152602001828054801561157257602002820191906000526020600020905b81548152602001906001019080831161155e575b50505050508c6002018054806020026020016040519081016040528092919081815260200182805480156108e257602002820191906000526020600020908154815260200190600101908083116108ce575050505050612bec565b905060005b858110156117115760008a82815181106115ee576115ee613d5b565b602002602001015111156116ff578a600301818154811061161157611611613d5b565b90600052602060002001548a828151811061162e5761162e613d5b565b6020026020010151106116795760405162461bcd60e51b8152602060048201526013602482015272696e73756666696369656e7442616c616e636560681b60448201526064016102d3565b6402540be4008a828151811061169157611691613d5b565b6020026020010151856116a49190613cb2565b6116ae9190613ba5565b8582815181106116c0576116c0613d5b565b6020026020010181815250506116ff898b83815181106116e2576116e2613d5b565b60200260200101518d60000184815481106106c2576106c2613d5b565b8061170981613d14565b9150506115d2565b508515611781576040516366f9eaab60e01b81526001600160a01b038916906366f9eaab9061174e9033908e908e908a908e908e9060040161397b565b600060405180830381600087803b15801561176857600080fd5b505af115801561177c573d6000803e3d6000fd5b505050505b60008a6003018054806020026020016040519081016040528092919081815260200182805480156117d157602002820191906000526020600020905b8154815260200190600101908083116117bd575b5050505050905060005b868110156118de5760008b82815181106117f7576117f7613d5b565b602002602001015111156118cc578a818151811061181757611817613d5b565b60200260200101516118988d600001838154811061183757611837613d5b565b9060005260206000200160009054906101000a90046001600160a01b031688848151811061186757611867613d5b565b60200260200101518e858151811061188157611881613d5b565b60200260200101516118939190613b8d565b61283c565b6118a29190613cd1565b8282815181106118b4576118b4613d5b565b602002602001018181516118c89190613b8d565b9052505b806118d681613d14565b9150506117db565b50600061193e6108ec838e6002018054806020026020016040519081016040528092919081815260200182805480156108e257602002820191906000526020600020908154815260200190600101908083116108ce575050505050612bec565b905082811161194f5761194f613d2f565b6000805b88811015611a7d576119b3858f600301838154811061197457611974613d5b565b90600052602060002001548561198a9190613cb2565b6119949190613ba5565b8583815181106119a6576119a6613d5b565b6020026020010151612f98565b91506402540be4006119c58389613cb2565b6119cf9190613ba5565b8882815181106119e1576119e1613d5b565b6020026020010181815250506402540be4008e60050154898381518110611a0a57611a0a613d5b565b6020026020010151611a1c9190613cb2565b611a269190613ba5565b848281518110611a3857611a38613d5b565b6020026020010151611a4a9190613cd1565b8e6003018281548110611a5f57611a5f613d5b565b60009182526020909120015580611a7581613d14565b915050611953565b508a6001600160a01b0316336001600160a01b03167f1e659566d9cc1f93351027d53422a1ec429f52c34bc45ee462dd91e99bdd26bb8e604051611ac19190613a5d565b60405180910390a350505050505050505050505050565b60006064611ae5836125c7565b6103a29190613ba5565b606060008460010160009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611b4357600080fd5b505afa158015611b57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b7b91906138e2565b905080841115611b8a57600080fd5b845460008167ffffffffffffffff811115611ba757611ba7613d71565b604051908082528060200260200182016040528015611bd0578160200160208202803683370190505b509050611bdd8787612fba565b935060005b8451811015611ce957858181518110611bfd57611bfd613d5b565b6020026020010151858281518110611c1757611c17613d5b565b60200260200101511015611c3d5760405162461bcd60e51b81526004016102d390613b69565b848181518110611c4f57611c4f613d5b565b6020026020010151886003018281548110611c6c57611c6c613d5b565b9060005260206000200154611c819190613cd1565b886003018281548110611c9657611c96613d5b565b9060005260206000200181905550611cd733868381518110611cba57611cba613d5b565b60200260200101518a60000184815481106106c2576106c2613d5b565b80611ce181613d14565b915050611be2565b50600187015460405163079cc67960e41b8152336004820152602481018890526001600160a01b03909116906379cc679090604401600060405180830381600087803b158015611d3857600080fd5b505af1158015611d4c573d6000803e3d6000fd5b503392507f347ad828e58cbe534d8f6b67985d791360756b18f0d95fd9f197a66cc46480ea915086905083611d818a88613cd1565b604051611d9093929190613a70565b60405180910390a25050509392505050565b82548251600091908114611dc85760405162461bcd60e51b81526004016102d390613b3b565b60008167ffffffffffffffff811115611de357611de3613d71565b604051908082528060200260200182016040528015611e0c578160200160208202803683370190505b5090506000611e1a87612f63565b905060008760010160009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611e6e57600080fd5b505afa158015611e82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ea691906138e2565b90506000611eb3896125c7565b905060008215611f6d57611f6a61077c8b600301805480602002602001604051908101604052809291908181526020018280548015611572576020028201919060005260206000209081548152602001906001019080831161155e5750505050508c6002018054806020026020016040519081016040528092919081815260200182805480156108e257602002820191906000526020600020908154815260200190600101908083116108ce575050505050612bec565b90505b60008a600301805480602002602001604051908101604052809291908181526020018280548015611fbd57602002820191906000526020600020905b815481526020019060010190808311611fa9575b5050505050905060005b878110156120f0578461203d5760008b8281518110611fe857611fe8613d5b565b60200260200101511161203d5760405162461bcd60e51b815260206004820152601e60248201527f696e697469616c4465706f73697452657175697265416c6c546f6b656e73000060448201526064016102d3565b60008b828151811061205157612051613d5b565b602002602001015111156120de576120b48c600001828154811061207757612077613d5b565b9060005260206000200160009054906101000a90046001600160a01b03168c83815181106120a7576120a7613d5b565b602002602001015161283c565b8282815181106120c6576120c6613d5b565b602002602001018181516120da9190613b8d565b9052505b806120e881613d14565b915050611fc7565b5060006121506108ec838e6002018054806020026020016040519081016040528092919081815260200182805480156108e257602002820191906000526020600020908154815260200190600101908083116108ce575050505050612bec565b905082811161216157612161613d2f565b8461218457815161217b9060038e01906020850190613536565b5080985061233b565b6000805b898110156122b8576121a9858f600301838154811061197457611974613d5b565b91506402540be4006121bb838a613cb2565b6121c59190613ba5565b8982815181106121d7576121d7613d5b565b6020026020010181815250506402540be4008e600501548a838151811061220057612200613d5b565b60200260200101516122129190613cb2565b61221c9190613ba5565b84828151811061222e5761222e613d5b565b60200260200101516122409190613cd1565b8e600301828154811061225557612255613d5b565b906000526020600020018190555088818151811061227557612275613d5b565b602002602001015184828151811061228f5761228f613d5b565b602002602001018181516122a39190613cd1565b905250806122b081613d14565b915050612188565b50612316610ec9848f6002018054806020026020016040519081016040528092919081815260200182805480156108e257602002820191906000526020600020908154815260200190600101908083116108ce575050505050612bec565b9150836123238184613cd1565b61232d9088613cb2565b6123379190613ba5565b9950505b8989101561235b5760405162461bcd60e51b81526004016102d390613b69565b60018c01546040516340c10f1960e01b8152336004820152602481018b90526001600160a01b03909116906340c10f1990604401600060405180830381600087803b1580156123a957600080fd5b505af11580156123bd573d6000803e3d6000fd5b50505050336001600160a01b03167f189c623b666b1b45b83d7178f39b8c087cb09774317ca2f53c2d3c3726f222a28c89848d6040516110479493929190613aa6565b60008061240c86612519565b9050600086600201868154811061242557612425613d5b565b90600052602060002001548461243b9190613cb2565b82878151811061244d5761244d613d5b565b602002602001015161245f9190613b8d565b905060006124708888888587612952565b9050600088600201878154811061248957612489613d5b565b9060005260206000200154600183868a815181106124a9576124a9613d5b565b60200260200101516124bb9190613cd1565b6124c59190613cd1565b6124cf9190613ba5565b905060006402540be400828b600401546124e99190613cb2565b6124f39190613ba5565b90506124ff8183613cd1565b9a9950505050505050505050565b606061039f8383612fba565b60606103a28260030180548060200260200160405190810160405280929190818152602001828054801561256c57602002820191906000526020600020905b815481526020019060010190808311612558575b5050505050836002018054806020026020016040519081016040528092919081815260200182805480156108e257602002820191906000526020600020908154815260200190600101908083116108ce575050505050612bec565b6000816009015442106125dc57506007015490565b81600601548260070154111561264657816008015482600901546126009190613cd1565b600883015461260f9042613cd1565b836006015484600701546126239190613cd1565b61262d9190613cb2565b6126379190613ba5565b82600601546103a29190613b8d565b8160080154826009015461265a9190613cd1565b60088301546126699042613cd1565b8360070154846006015461267d9190613cd1565b6126879190613cb2565b6126919190613ba5565b82600601546103a29190613cd1565b8151600090816126af85613152565b9050806126c1576000925050506103a2565b600081816126cf8588613cb2565b905060005b6101008110156127f3578260005b8a5181101561273857878b82815181106126fe576126fe613d5b565b60200260200101516127109190613cb2565b61271a8684613cb2565b6127249190613ba5565b91508061273081613d14565b9150506126e2565b508394508087600161274a9190613b8d565b6127549190613cb2565b6064856127618287613cd1565b61276b9190613cb2565b6127759190613ba5565b61277f9190613b8d565b8461278a8984613cb2565b60646127968a88613cb2565b6127a09190613ba5565b6127aa9190613b8d565b6127b49190613cb2565b6127be9190613ba5565b935060016127cc8587612f98565b116127e057839750505050505050506103a2565b50806127eb81613d14565b9150506126d4565b5060405162461bcd60e51b815260206004820152601a60248201527f696e76617269616e7443616c63756c6174696f6e4661696c656400000000000060448201526064016102d3565b6040516370a0823160e01b815230600482015260009081906001600160a01b038516906370a082319060240160206040518083038186803b15801561288057600080fd5b505afa158015612894573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128b891906138e2565b90506128cf6001600160a01b03851633308661319e565b6040516370a0823160e01b815230600482015281906001600160a01b038616906370a082319060240160206040518083038186803b15801561291057600080fd5b505afa158015612924573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061294891906138e2565b61047a9190613cd1565b6000838514156129905760405162461bcd60e51b815260206004820152600960248201526839b0b6b2aa37b5b2b760b91b60448201526064016102d3565b855480861080156129a057508085105b6129bc5760405162461bcd60e51b81526004016102d390613b12565b60006129c7886125c7565b905060006129d58383613cb2565b905060006129e386846126a0565b9050600081815b86811015612a6b578a8114156129ff57612a59565b60008c8214612a2757898281518110612a1a57612a1a613d5b565b6020026020010151612a29565b8a5b9050612a358185613b8d565b9350612a418882613cb2565b612a4b8685613cb2565b612a559190613ba5565b9250505b80612a6381613d14565b9150506129ea565b50612a768685613cb2565b6064612a828584613cb2565b612a8c9190613cb2565b612a969190613ba5565b9050600084612aa6606486613cb2565b612ab09190613ba5565b612aba9084613b8d565b9050600084815b610100811015612b46578192508684836002612add9190613cb2565b612ae79190613b8d565b612af19190613cd1565b85612afc8480613cb2565b612b069190613b8d565b612b109190613ba5565b91506001612b1e8484612f98565b11612b3457509850610732975050505050505050565b80612b3e81613d14565b915050612ac1565b5060405162461bcd60e51b81526020600482015260126024820152711e50d85b18dd5b185d1a5bdb91985a5b195960721b60448201526064016102d3565b6040516001600160a01b038316602482015260448101829052612be790849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526131dc565b505050565b606060005b8351811015612c6757838181518110612c0c57612c0c613d5b565b6020026020010151838281518110612c2657612c26613d5b565b6020026020010151612c389190613cb2565b838281518110612c4a57612c4a613d5b565b602090810291909101015280612c5f81613d14565b915050612bf1565b509092915050565b825460009081908310612c945760405162461bcd60e51b81526004016102d390613b12565b6000612c9f866125c7565b90506000612cac87612519565b90506000612cba82846126a0565b905060008860010160009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015612d0e57600080fd5b505afa158015612d22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4691906138e2565b612d50838a613cb2565b612d5a9190613ba5565b612d649083613cd1565b90506000612d758a868a87866132ae565b9050836000612d838c612f63565b905060005b8c54811015612e8b5760008b821415612ddd578487878a8581518110612db057612db0613d5b565b6020026020010151612dc29190613cb2565b612dcc9190613ba5565b612dd69190613cd1565b9050612e34565b8686898481518110612df157612df1613d5b565b6020026020010151612e039190613cb2565b612e0d9190613ba5565b888381518110612e1f57612e1f613d5b565b6020026020010151612e319190613cd1565b90505b6402540be400612e448285613cb2565b612e4e9190613ba5565b848381518110612e6057612e60613d5b565b60200260200101818151612e749190613cd1565b905250819050612e8381613d14565b915050612d88565b50612e998c888c85886132ae565b828b81518110612eab57612eab613d5b565b6020026020010151612ebd9190613cd1565b98508b6002018a81548110612ed457612ed4613d5b565b906000526020600020015460018a612eec9190613cd1565b612ef69190613ba5565b9850888c6002018b81548110612f0e57612f0e613d5b565b906000526020600020015484888d81518110612f2c57612f2c613d5b565b6020026020010151612f3e9190613cd1565b612f489190613ba5565b612f529190613cd1565b975050505050505050935093915050565b8054600090612f73600182613cd1565b612f7e906004613cb2565b818460040154612f8e9190613cb2565b610a5b9190613ba5565b6000818311612fb057612fab8383613cd1565b61039f565b61039f8284613cd1565b606060008360010160009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561300e57600080fd5b505afa158015613022573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061304691906138e2565b9050808311156130985760405162461bcd60e51b815260206004820152601a60248201527f43616e6e6f742065786365656420746f74616c20737570706c7900000000000060448201526064016102d3565b835460009067ffffffffffffffff8111156130b5576130b5613d71565b6040519080825280602002602001820160405280156130de578160200160208202803683370190505b50905060005b8554811015610a6f57828587600301838154811061310457613104613d5b565b90600052602060002001546131199190613cb2565b6131239190613ba5565b82828151811061313557613135613d5b565b60209081029190910101528061314a81613d14565b9150506130e4565b6000805b82518110156131985782818151811061317157613171613d5b565b6020026020010151826131849190613b8d565b91508061319081613d14565b915050613156565b50919050565b6040516001600160a01b03808516602483015283166044820152606481018290526131d69085906323b872dd60e01b90608401612bb0565b50505050565b6000613231826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166134229092919063ffffffff16565b805190915015612be7578080602001905181019061324f9190613637565b612be75760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016102d3565b84546000908085106132c2576132c2613d2f565b60006132ce8288613cb2565b90508360008080805b86811015613349578a8114156132ec57613337565b8981815181106132fe576132fe613d5b565b6020026020010151925082846133149190613b8d565b93506133208784613cb2565b61332a8a87613cb2565b6133349190613ba5565b94505b8061334181613d14565b9150506132d7565b506133548686613cb2565b60646133608a87613cb2565b61336a9190613cb2565b6133749190613ba5565b935060008561338460648b613cb2565b61338e9190613ba5565b6133989085613b8d565b90508860005b6101008110156127f3578193508a838360026133ba9190613cb2565b6133c49190613b8d565b6133ce9190613cd1565b876133d98480613cb2565b6133e39190613b8d565b6133ed9190613ba5565b915060016133fb8584612f98565b11613410575097506107329650505050505050565b8061341a81613d14565b91505061339e565b606061047a8484600085856001600160a01b0385163b6134845760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102d3565b600080866001600160a01b031685876040516134a0919061395f565b60006040518083038185875af1925050503d80600081146134dd576040519150601f19603f3d011682016040523d82523d6000602084013e6134e2565b606091505b50915091506134f28282866134fd565b979650505050505050565b6060831561350c575081610a5b565b82511561351c5782518084602001fd5b8160405162461bcd60e51b81526004016102d39190613adf565b828054828255906000526020600020908101928215613571579160200282015b82811115613571578251825591602001919060010190613556565b5061357d929150613581565b5090565b5b8082111561357d5760008155600101613582565b600082601f8301126135a757600080fd5b8135602067ffffffffffffffff808311156135c4576135c4613d71565b8260051b604051601f19603f830116810181811084821117156135e9576135e9613d71565b6040528481528381019250868401828801850189101561360857600080fd5b600092505b8583101561362b57803584529284019260019290920191840161360d565b50979650505050505050565b60006020828403121561364957600080fd5b8151610a5b81613d87565b60006020828403121561366657600080fd5b5035919050565b60008060008060006080868803121561368557600080fd5b85359450602086013567ffffffffffffffff808211156136a457600080fd5b6136b089838a01613596565b9550604088013591506001600160a01b03821682146136ce57600080fd5b909350606087013590808211156136e457600080fd5b818801915088601f8301126136f857600080fd5b81358181111561370757600080fd5b89602082850101111561371957600080fd5b9699959850939650602001949392505050565b60008060006060848603121561374157600080fd5b83359250602084013567ffffffffffffffff81111561375f57600080fd5b61376b86828701613596565b925050604084013561377c81613d87565b809150509250925092565b60008060006060848603121561379c57600080fd5b83359250602084013567ffffffffffffffff8111156137ba57600080fd5b6137c686828701613596565b925050604084013590509250925092565b600080604083850312156137ea57600080fd5b50508035926020909101359150565b60008060006060848603121561380e57600080fd5b8335925060208401359150604084013567ffffffffffffffff81111561383357600080fd5b61383f86828701613596565b9150509250925092565b60008060006060848603121561385e57600080fd5b505081359360208301359350604090920135919050565b6000806000806080858703121561388b57600080fd5b5050823594602084013594506040840135936060013592509050565b600080600080600060a086880312156138bf57600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b6000602082840312156138f457600080fd5b5051919050565b600081518084526020808501945080840160005b8381101561392b5781518752958201959082019060010161390f565b509495945050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60008251613971818460208701613ce8565b9190910192915050565b600060a0820160018060a01b03808a168452602060a081860152828a5480855260c0870191508b60005282600020945060005b818110156139cc5785548516835260019586019592840192016139ae565b505085810360408701526139e0818b6138fb565b935050505082810360608401526139f781876138fb565b90508281036080840152613a0c818587613936565b9998505050505050505050565b6020808252825182820181905260009190848201906040850190845b81811015613a5157835183529284019291840191600101613a35565b50909695505050505050565b60208152600061039f60208301846138fb565b606081526000613a8360608301866138fb565b8281036020840152613a9581866138fb565b915050826040830152949350505050565b608081526000613ab960808301876138fb565b8281036020840152613acb81876138fb565b604084019590955250506060015292915050565b6020815260008251806020840152613afe816040850160208701613ce8565b601f01601f19169190910160400192915050565b6020808252600f908201526e696e6465784f75744f6652616e676560881b604082015260600190565b6020808252601490820152730d2dcecc2d8d2c882dadeeadce8e698cadccee8d60631b604082015260600190565b6020808252600a90820152693e20736c69707061676560b01b604082015260600190565b60008219821115613ba057613ba0613d45565b500190565b600082613bc257634e487b7160e01b600052601260045260246000fd5b500490565b600181815b80851115613c02578160001904821115613be857613be8613d45565b80851615613bf557918102915b93841c9390800290613bcc565b509250929050565b600061039f8383600082613c20575060016103a2565b81613c2d575060006103a2565b8160018114613c435760028114613c4d57613c69565b60019150506103a2565b60ff841115613c5e57613c5e613d45565b50506001821b6103a2565b5060208310610133831016604e8410600b8410161715613c8c575081810a6103a2565b613c968383613bc7565b8060001904821115613caa57613caa613d45565b029392505050565b6000816000190483118215151615613ccc57613ccc613d45565b500290565b600082821015613ce357613ce3613d45565b500390565b60005b83811015613d03578181015183820152602001613ceb565b838111156131d65750506000910152565b6000600019821415613d2857613d28613d45565b5060010190565b634e487b7160e01b600052600160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b8015158114613d9557600080fd5b5056fea264697066735822122057a1863b038e4fd3218ca5368ab559266e254a8a019bdaf7dc908a5ef1b90a8764736f6c63430008070033
Deployed Bytecode Sourcemap
38555:22782:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50608:269;;;;;;:::i;:::-;;:::i;:::-;;;17699:25:1;;;17687:2;17672:18;50608:269:0;;;;;;;;50257:343;;;;;;:::i;:::-;;:::i;45010:1146::-;;;;;;;;;;-1:-1:-1;45010:1146:0;;;;;:::i;:::-;;:::i;51022:1003::-;;;;;;:::i;:::-;;:::i;53059:272::-;;;;;;:::i;:::-;;:::i;48070:1915::-;;;;;;;;;;-1:-1:-1;48070:1915:0;;;;;:::i;:::-;;:::i;50017:123::-;;;;;;:::i;:::-;;:::i;47037:1025::-;;;;;;;;;;-1:-1:-1;47037:1025:0;;;;;:::i;:::-;;:::i;42986:2016::-;;;;;;;;;;-1:-1:-1;42986:2016:0;;;;;:::i;:::-;;:::i;:::-;;52033:130;;;;;;:::i;:::-;;:::i;39953:55::-;;40006:2;39953:55;;39803:41;;39841:3;39803:41;;46164:865;;;;;;;;;;-1:-1:-1;46164:865:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;39559:46::-;;39601:4;39559:46;;40955:2023;;;;;;;;;;-1:-1:-1;40955:2023:0;;;;;:::i;:::-;;:::i;52171:658::-;;;;;;:::i;:::-;;:::i;52837:214::-;;;;;;:::i;:::-;;:::i;50608:269::-;50733:24;;50697:7;;50725:32;;50717:60;;;;-1:-1:-1;;;50717:60:0;;;;;;;:::i;:::-;;;;;;;;;50848:4;:13;;50862:5;50848:20;;;;;;;;:::i;:::-;;;;;;;;;50795:4;:17;;50813:5;50795:24;;;;;;;;:::i;:::-;;;;;;;;;;;:49;;-1:-1:-1;;;50795:49:0;;50838:4;50795:49;;;6978:51:1;-1:-1:-1;;;;;50795:24:0;;;;:34;;6951:18:1;;50795:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:74;;;;:::i;:::-;50788:81;;50608:269;;;;;:::o;50257:343::-;50331:7;50351:9;50363:36;50369:9;50373:4;50369:3;:9::i;:::-;50380:18;50393:4;50380:12;:18::i;:::-;50363:5;:36::i;:::-;50351:48;;50410:19;50432:4;:12;;;;;;;;;;-1:-1:-1;;;;;50432:12:0;-1:-1:-1;;;;;50432:24:0;;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;50410:48;-1:-1:-1;50473:15:0;;50469:105;;50551:11;50517:30;40006:2;50517;:30;:::i;:::-;50513:34;;:1;:34;:::i;:::-;50512:50;;;;:::i;:::-;50505:57;50257:343;-1:-1:-1;;;;50257:343:0:o;50469:105::-;-1:-1:-1;50591:1:0;;50257:343;-1:-1:-1;;;50257:343:0:o;45010:1146::-;45182:7;45202:13;45218:4;:17;;45236:1;45218:20;;;;;;;;:::i;:::-;;;;;;;;;;-1:-1:-1;;;;;45218:20:0;;-1:-1:-1;45287:9:0;45291:4;45287:3;:9::i;:::-;45249:47;;45318:31;45332:6;45340:8;45318:13;:31::i;:::-;45307:42;;45362:9;45410:4;:21;;45432:1;45410:24;;;;;;;;:::i;:::-;;;;;;;;;45399:8;:35;;;;:::i;:::-;45374:18;45393:1;45374:21;;;;;;;;:::i;:::-;;;;;;;:61;;;;:::i;:::-;45362:73;;45446:9;45458:40;45464:4;45470:1;45473;45476;45479:18;45458:5;:40::i;:::-;45446:52;;45511:10;45552:1;45548;45524:18;45543:1;45524:21;;;;;;;;:::i;:::-;;;;;;;:25;;;;:::i;:::-;:29;;;;:::i;:::-;45511:42;;45612:14;39601:4;45635;:8;;;45630:2;:13;;;;:::i;:::-;45629:33;;;;:::i;:::-;45612:50;;45696:4;:21;;45718:1;45696:24;;;;;;;;:::i;:::-;;;;;;;;;45686:6;45681:2;:11;;;;:::i;:::-;45680:40;;;;:::i;:::-;45675:45;;45762:12;45756:2;:18;;45748:41;;;;-1:-1:-1;;;45748:41:0;;;;;;;:::i;:::-;45802:17;45867:4;:21;;45889:1;45867:24;;;;;;;;:::i;:::-;;;;;;;;;39601:4;45832;:13;;;45823:6;:22;;;;:::i;:::-;45822:42;;;;:::i;:::-;:69;;;;:::i;:::-;45802:89;;45952:8;45932:4;:13;;45946:1;45932:16;;;;;;;;:::i;:::-;;;;;;;;;:28;;;;;;;:::i;:::-;;;;-1:-1:-1;45991:14:0;;-1:-1:-1;45996:9:0;45991:2;:14;:::i;:::-;45971:4;:13;;45985:1;45971:16;;;;;;;;:::i;:::-;;;;;;;;;:34;;;;;;;:::i;:::-;;;;;;;;46018:49;46052:10;46064:2;46018:4;:17;;46036:1;46018:20;;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;46018:20:0;;:49;:33;:49::i;:::-;46083:45;;;18290:25:1;;;18346:2;18331:18;;18324:34;;;18374:18;;;18367:34;;;18432:2;18417:18;;18410:34;;;46097:10:0;;46083:45;;18277:3:1;18262:19;46083:45:0;;;;;;;-1:-1:-1;46146:2:0;;-1:-1:-1;;;;;;45010:1146:0;;;;;;;;:::o;51022:1003::-;51212:24;;51255:14;;51175:7;;51212:24;51255;;51247:57;;;;-1:-1:-1;;;51247:57:0;;;;;;;:::i;:::-;51315:11;51329:18;51342:4;51329:12;:18::i;:::-;51315:32;;51358:10;51371:21;51377:9;51381:4;51377:3;:9::i;:::-;51388:3;51371:5;:21::i;:::-;51358:34;;51405:28;51436:4;:13;;51405:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;51465:9;51460:208;51484:6;51480:1;:10;51460:208;;;51516:7;51512:145;;;51562:7;51570:1;51562:10;;;;;;;;:::i;:::-;;;;;;;51544:11;51556:1;51544:14;;;;;;;;:::i;:::-;;;;;;:28;;;;;;;:::i;:::-;;;-1:-1:-1;51512:145:0;;;51631:7;51639:1;51631:10;;;;;;;;:::i;:::-;;;;;;;51613:11;51625:1;51613:14;;;;;;;;:::i;:::-;;;;;;:28;;;;;;;:::i;:::-;;;-1:-1:-1;51512:145:0;51492:3;;;;:::i;:::-;;;;51460:208;;;;51680:10;51693:51;51699:39;51703:11;51716:4;:21;;51699:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:3;:39::i;:::-;51740:3;51693:5;:51::i;:::-;51680:64;;51755:19;51777:4;:12;;;;;;;;;;-1:-1:-1;;;;;51777:12:0;-1:-1:-1;;;;;51777:24:0;;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;51755:48;-1:-1:-1;51820:16:0;51816:89;;-1:-1:-1;51860:2:0;-1:-1:-1;51853:9:0;;-1:-1:-1;;;;51853:9:0;51816:89;51917:12;51932:7;:27;;51952:7;51957:2;51952;:7;:::i;:::-;51932:27;;;51942:7;51947:2;51942;:7;:::i;:::-;51917:42;;52015:2;51985:4;:12;;;;;;;;;;-1:-1:-1;;;;;51985:12:0;-1:-1:-1;;;;;51985:24:0;;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;51978:33;;:4;:33;:::i;:::-;51977:40;;;;:::i;:::-;51970:47;;;;;;;;;51022:1003;;;;;;:::o;53059:272::-;53222:14;53262:61;53296:4;53302:8;53312:10;53262:33;:61::i;:::-;-1:-1:-1;53249:74:0;53059:272;-1:-1:-1;;;;53059:272:0:o;48070:1915::-;48279:24;;48322:14;;48231:18;;48279:24;48322;;48314:57;;;;-1:-1:-1;;;48314:57:0;;;;;;;:::i;:::-;48404:12;;;;:26;;;-1:-1:-1;;;48404:26:0;;;;48382:19;;-1:-1:-1;;;;;48404:12:0;;:24;;:26;;;;;;;;;;;;;;:12;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;48382:48;-1:-1:-1;48449:16:0;48441:44;;;;-1:-1:-1;;;48441:44:0;;12067:2:1;48441:44:0;;;12049:21:1;12106:2;12086:18;;;12079:30;-1:-1:-1;;;12125:18:1;;;12118:45;12180:18;;48441:44:0;11865:339:1;48441:44:0;48496:12;48511:18;48524:4;48511:12;:18::i;:::-;48496:33;;48540:11;48554:18;48567:4;48554:12;:18::i;:::-;48540:32;;48585:28;48616:4;:13;;48585:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;48640:10;48653:21;48659:9;48663:4;48659:3;:9::i;:::-;48670:3;48653:5;:21::i;:::-;48640:34;;48692:9;48687:92;48711:6;48707:1;:10;48687:92;;;48757:7;48765:1;48757:10;;;;;;;;:::i;:::-;;;;;;;48739:11;48751:1;48739:14;;;;;;;;:::i;:::-;;;;;;:28;;;;;;;:::i;:::-;;;-1:-1:-1;48719:3:0;;;;:::i;:::-;;;;48687:92;;;;48791:10;48804:51;48810:39;48814:11;48827:4;:21;;48810:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:3;:39::i;48804:51::-;48791:64;;48866:21;48904:6;48890:21;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;48890:21:0;;48866:45;;48929:9;48924:376;48948:6;48944:1;:10;48924:376;;;48976:20;49025:2;49005:4;:13;;49019:1;49005:16;;;;;;;;:::i;:::-;;;;;;;;;49000:2;:21;;;;:::i;:::-;48999:28;;;;:::i;:::-;48976:51;;49042:12;49057:39;49067:11;49079:1;49067:14;;;;;;;;:::i;:::-;;;;;;;49083:12;49057:9;:39::i;:::-;49042:54;-1:-1:-1;39601:4:0;49122:11;49042:54;49122:4;:11;:::i;:::-;49121:31;;;;:::i;:::-;49111:4;49116:1;49111:7;;;;;;;;:::i;:::-;;;;;;:41;;;;;39601:4;49215;:13;;;49205:4;49210:1;49205:7;;;;;;;;:::i;:::-;;;;;;;:23;;;;:::i;:::-;49204:43;;;;:::i;:::-;49186:11;49198:1;49186:14;;;;;;;;:::i;:::-;;;;;;;:62;;;;:::i;:::-;49167:4;:13;;49181:1;49167:16;;;;;;;;:::i;:::-;;;;;;;;:81;;;;49281:4;49286:1;49281:7;;;;;;;;:::i;:::-;;;;;;;49263:11;49275:1;49263:14;;;;;;;;:::i;:::-;;;;;;:25;;;;;;;:::i;:::-;;;-1:-1:-1;48956:3:0;;-1:-1:-1;48956:3:0;;-1:-1:-1;48956:3:0;;:::i;:::-;;;;48924:376;;;;49377:51;49383:39;49387:11;49400:4;:21;;49383:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:3;:39::i;:::-;49424:3;49377:5;:51::i;:::-;49372:56;-1:-1:-1;49480:2:0;49465:11;49454:7;49372:56;49480:2;49454:7;:::i;:::-;49453:23;;;;:::i;:::-;49452:30;;;;:::i;:::-;49439:43;;49513:1;49500:10;:14;49493:22;;;;:::i;:::-;49526:15;49540:1;49526:15;;:::i;:::-;;;49604:13;49590:10;:27;;49582:50;;;;-1:-1:-1;;;49582:50:0;;;;;;;:::i;:::-;49645:12;;;;:45;;-1:-1:-1;;;49645:45:0;;49667:10;49645:45;;;8962:51:1;9029:18;;;9022:34;;;-1:-1:-1;;;;;49645:12:0;;;;:21;;8935:18:1;;49645:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49708:9;49703:176;49727:6;49723:1;:10;49703:176;;;49759:7;49767:1;49759:10;;;;;;;;:::i;:::-;;;;;;;49773:1;49759:15;49755:113;;49795:57;49829:10;49841:7;49849:1;49841:10;;;;;;;;:::i;:::-;;;;;;;49795:4;:17;;49813:1;49795:20;;;;;;;;:::i;:57::-;49735:3;;;;:::i;:::-;;;;49703:176;;;-1:-1:-1;49921:10:0;49896:81;49933:7;49942:4;49948:2;49952:24;49966:10;49952:11;:24;:::i;:::-;49896:81;;;;;;;;;:::i;:::-;;;;;;;;48251:1734;;;;;;;;48070:1915;;;;;:::o;50017:123::-;50087:7;50114:18;50127:4;50114:12;:18::i;47037:1025::-;47209:7;47229:19;47251:4;:12;;;;;;;;;;-1:-1:-1;;;;;47251:12:0;-1:-1:-1;;;;;47251:24:0;;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;47229:48;;47310:1;47296:11;:15;47288:43;;;;-1:-1:-1;;;47288:43:0;;12067:2:1;47288:43:0;;;12049:21:1;12106:2;12086:18;;;12079:30;-1:-1:-1;;;12125:18:1;;;12118:45;12180:18;;47288:43:0;11865:339:1;47288:43:0;47362:24;;47417:12;;;;:34;;-1:-1:-1;;;47417:34:0;;47440:10;47417:34;;;6978:51:1;-1:-1:-1;;;;;47417:12:0;;;;:22;;6951:18:1;;47417:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;47405:8;:46;;47397:68;;;;-1:-1:-1;;;47397:68:0;;12411:2:1;47397:68:0;;;12393:21:1;12450:1;12430:18;;;12423:29;-1:-1:-1;;;12468:18:1;;;12461:39;12517:18;;47397:68:0;12209:332:1;47397:68:0;47496:11;47484:8;:23;;47476:49;;;;-1:-1:-1;;;47476:49:0;;14195:2:1;47476:49:0;;;14177:21:1;14234:2;14214:18;;;14207:30;-1:-1:-1;;;14253:18:1;;;14246:43;14306:18;;47476:49:0;13993:337:1;47476:49:0;47552:9;47544:5;:17;47536:43;;;;-1:-1:-1;;;47536:43:0;;14537:2:1;47536:43:0;;;14519:21:1;14576:2;14556:18;;;14549:30;-1:-1:-1;;;14595:18:1;;;14588:43;14648:18;;47536:43:0;14335:337:1;47536:43:0;47592:13;47616:10;47653:56;47687:4;47693:8;47703:5;47653:33;:56::i;:::-;47639:70;-1:-1:-1;47639:70:0;-1:-1:-1;47730:15:0;;;;47722:38;;;;-1:-1:-1;;;47722:38:0;;;;;;;:::i;:::-;39601:4;47812;:13;;;47804:5;:21;;;;:::i;:::-;47803:41;;;;:::i;:::-;47798:46;;:2;:46;:::i;:::-;47773:4;:13;;47787:5;47773:20;;;;;;;;:::i;:::-;;;;;;;;;:72;;;;;;;:::i;:::-;;;;-1:-1:-1;;47856:12:0;;;;:43;;-1:-1:-1;;;47856:43:0;;47878:10;47856:43;;;8962:51:1;9029:18;;;9022:34;;;-1:-1:-1;;;;;47856:12:0;;;;:21;;8935:18:1;;47856:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;47910:53;47948:10;47960:2;47910:4;:17;;47928:5;47910:24;;;;;;;;:::i;:53::-;47981:51;;;17937:25:1;;;17993:2;17978:18;;17971:34;;;18021:18;;;18014:34;;;48000:10:0;;47981:51;;17925:2:1;17910:18;47981:51:0;;;;;;;48052:2;47037:1025;-1:-1:-1;;;;;;;;47037:1025:0:o;42986:2016::-;43173:24;;43216:17;;:27;;43208:60;;;;-1:-1:-1;;;43208:60:0;;;;;;;:::i;:::-;43316:12;;;;:26;;;-1:-1:-1;;;43316:26:0;;;;43294:19;;-1:-1:-1;;;;;43316:12:0;;:24;;:26;;;;;;;;;;;;;;:12;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;43294:48;;43379:1;43365:11;:15;43357:49;;;;-1:-1:-1;;;43357:49:0;;17397:2:1;43357:49:0;;;17379:21:1;17436:2;17416:18;;;17409:30;-1:-1:-1;;;17455:18:1;;;17448:51;17516:18;;43357:49:0;17195:345:1;43357:49:0;43279:139;43428:21;43466:6;43452:21;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;43452:21:0;;43428:45;;43484:12;43499:18;43512:4;43499:12;:18::i;:::-;43484:33;;43528:11;43542:18;43555:4;43542:12;:18::i;:::-;43528:32;;43571:10;43584:53;43590:41;43594:4;:13;;43590:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;43609:4;:21;;43590:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:3;:41::i;43584:53::-;43571:66;;43655:9;43650:325;43674:6;43670:1;:10;43650:325;;;43722:1;43706:10;43717:1;43706:13;;;;;;;;:::i;:::-;;;;;;;:17;43702:262;;;43768:4;:13;;43782:1;43768:16;;;;;;;;:::i;:::-;;;;;;;;;43752:10;43763:1;43752:13;;;;;;;;:::i;:::-;;;;;;;:32;43744:64;;;;-1:-1:-1;;;43744:64:0;;13847:2:1;43744:64:0;;;13829:21:1;13886:2;13866:18;;;13859:30;-1:-1:-1;;;13905:18:1;;;13898:49;13964:18;;43744:64:0;13645:343:1;43744:64:0;39601:4;43845:10;43856:1;43845:13;;;;;;;;:::i;:::-;;;;;;;43838:4;:20;;;;:::i;:::-;43837:40;;;;:::i;:::-;43827:4;43832:1;43827:7;;;;;;;;:::i;:::-;;;;;;:50;;;;;43896:52;43930:2;43934:10;43945:1;43934:13;;;;;;;;:::i;:::-;;;;;;;43896:4;:17;;43914:1;43896:20;;;;;;;;:::i;:52::-;43682:3;;;;:::i;:::-;;;;43650:325;;;-1:-1:-1;43991:15:0;;43987:249;;44023:201;;-1:-1:-1;;;44023:201:0;;-1:-1:-1;;;;;44023:43:0;;;;;:201;;44085:10;;44115:4;;44151:10;;44181:4;;44205;;;;44023:201;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;43987:249;44248:28;44279:4;:13;;44248:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;44308:9;44303:217;44327:6;44323:1;:10;44303:217;;;44375:1;44359:10;44370:1;44359:13;;;;;;;;:::i;:::-;;;;;;;:17;44355:154;;;44479:10;44490:1;44479:13;;;;;;;;:::i;:::-;;;;;;;44416:60;44430:4;:17;;44448:1;44430:20;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;44430:20:0;44468:4;44473:1;44468:7;;;;;;;;:::i;:::-;;;;;;;44452:10;44463:1;44452:13;;;;;;;;:::i;:::-;;;;;;;:23;;;;:::i;:::-;44416:13;:60::i;:::-;:76;;;;:::i;:::-;44397:11;44409:1;44397:14;;;;;;;;:::i;:::-;;;;;;:96;;;;;;;:::i;:::-;;;-1:-1:-1;44355:154:0;44335:3;;;;:::i;:::-;;;;44303:217;;;;44532:10;44545:51;44551:39;44555:11;44568:4;:21;;44551:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:3;:39::i;44545:51::-;44532:64;;44619:2;44614;:7;44607:15;;;;:::i;:::-;44635:12;44667:9;44662:278;44686:6;44682:1;:10;44662:278;;;44721:55;44757:2;44737:4;:13;;44751:1;44737:16;;;;;;;;:::i;:::-;;;;;;;;;44732:2;:21;;;;:::i;:::-;44731:28;;;;:::i;:::-;44761:11;44773:1;44761:14;;;;;;;;:::i;:::-;;;;;;;44721:9;:55::i;:::-;44714:62;-1:-1:-1;39601:4:0;44802:11;44714:62;44802:4;:11;:::i;:::-;44801:31;;;;:::i;:::-;44791:4;44796:1;44791:7;;;;;;;;:::i;:::-;;;;;;:41;;;;;39601:4;44895;:13;;;44885:4;44890:1;44885:7;;;;;;;;:::i;:::-;;;;;;;:23;;;;:::i;:::-;44884:43;;;;:::i;:::-;44866:11;44878:1;44866:14;;;;;;;;:::i;:::-;;;;;;;:62;;;;:::i;:::-;44847:4;:13;;44861:1;44847:16;;;;;;;;:::i;:::-;;;;;;;;;;:81;44694:3;;;;:::i;:::-;;;;44662:278;;;;44979:2;-1:-1:-1;;;;;44957:37:0;44967:10;-1:-1:-1;;;;;44957:37:0;;44983:10;44957:37;;;;;;:::i;:::-;;;;;;;;43145:1857;;;;;;;;42986:2016;;;;;:::o;52033:130::-;52096:7;39841:3;52123:18;52136:4;52123:12;:18::i;:::-;:32;;;;:::i;46164:865::-;46314:24;46351:19;46373:4;:12;;;;;;;;;;-1:-1:-1;;;;;46373:12:0;-1:-1:-1;;;;;46373:24:0;;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;46351:48;;46430:11;46418:8;:23;;46410:32;;;;;;46470:24;;46453:14;46470:24;46531:21;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;46531:21:0;;46507:45;;46573:41;46599:4;46605:8;46573:25;:41::i;:::-;46563:51;;46632:9;46627:257;46651:7;:14;46647:1;:18;46627:257;;;46709:10;46720:1;46709:13;;;;;;;;:::i;:::-;;;;;;;46695:7;46703:1;46695:10;;;;;;;;:::i;:::-;;;;;;;:27;;46687:50;;;;-1:-1:-1;;;46687:50:0;;;;;;;:::i;:::-;46790:7;46798:1;46790:10;;;;;;;;:::i;:::-;;;;;;;46771:4;:13;;46785:1;46771:16;;;;;;;;:::i;:::-;;;;;;;;;:29;;;;:::i;:::-;46752:4;:13;;46766:1;46752:16;;;;;;;;:::i;:::-;;;;;;;;:48;;;;46815:57;46849:10;46861:7;46869:1;46861:10;;;;;;;;:::i;:::-;;;;;;;46815:4;:17;;46833:1;46815:20;;;;;;;;:::i;:57::-;46667:3;;;;:::i;:::-;;;;46627:257;;;-1:-1:-1;46896:12:0;;;;:43;;-1:-1:-1;;;46896:43:0;;46918:10;46896:43;;;8962:51:1;9029:18;;;9022:34;;;-1:-1:-1;;;;;46896:12:0;;;;:21;;8935:18:1;;46896:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;46971:10:0;;-1:-1:-1;46955:66:0;;-1:-1:-1;46983:7:0;;-1:-1:-1;46992:4:0;46998:22;47012:8;46998:11;:22;:::i;:::-;46955:66;;;;;;;;:::i;:::-;;;;;;;;46340:689;;;46164:865;;;;;:::o;40955:2023::-;41152:24;;41195:14;;41104:18;;41152:24;41195;;41187:57;;;;-1:-1:-1;;;41187:57:0;;;;;;;:::i;:::-;41255:21;41293:6;41279:21;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;41279:21:0;;41255:45;;41311:12;41326:18;41339:4;41326:12;:18::i;:::-;41311:33;;41357:19;41379:4;:12;;;;;;;;;;-1:-1:-1;;;;;41379:12:0;-1:-1:-1;;;;;41379:24:0;;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;41357:48;;41416:11;41430:18;41443:4;41430:12;:18::i;:::-;41416:32;-1:-1:-1;41461:10:0;41490:15;;41486:106;;41527:53;41533:41;41537:4;:13;;41533:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;41552:4;:21;;41533:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:3;:41::i;41527:53::-;41522:58;;41486:106;41604:28;41635:4;:13;;41604:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;41666:9;41661:355;41685:6;41681:1;:10;41661:355;;;41717:16;41713:114;;41775:1;41762:7;41770:1;41762:10;;;;;;;;:::i;:::-;;;;;;;:14;41754:57;;;;-1:-1:-1;;;41754:57:0;;17038:2:1;41754:57:0;;;17020:21:1;17077:2;17057:18;;;17050:30;17116:32;17096:18;;;17089:60;17166:18;;41754:57:0;16836:354:1;41754:57:0;41902:1;41889:7;41897:1;41889:10;;;;;;;;:::i;:::-;;;;;;;:14;41885:120;;;41942:47;41956:4;:17;;41974:1;41956:20;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;41956:20:0;41978:7;41986:1;41978:10;;;;;;;;:::i;:::-;;;;;;;41942:13;:47::i;:::-;41924:11;41936:1;41924:14;;;;;;;;:::i;:::-;;;;;;:65;;;;;;;:::i;:::-;;;-1:-1:-1;41885:120:0;41693:3;;;;:::i;:::-;;;;41661:355;;;;42028:10;42041:51;42047:39;42051:11;42064:4;:21;;42047:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:3;:39::i;42041:51::-;42028:64;;42115:2;42110;:7;42103:15;;;;:::i;:::-;42151:16;42147:636;;42184:27;;;;:13;;;;:27;;;;;:::i;:::-;;42239:2;42226:15;;42147:636;;;42274:12;42310:9;42305:338;42329:6;42325:1;:10;42305:338;;;42368:55;42404:2;42384:4;:13;;42398:1;42384:16;;;;;;;;:::i;42368:55::-;42361:62;-1:-1:-1;39601:4:0;42453:11;42361:62;42453:4;:11;:::i;:::-;42452:31;;;;:::i;:::-;42442:4;42447:1;42442:7;;;;;;;;:::i;:::-;;;;;;:41;;;;;39601:4;42550;:13;;;42540:4;42545:1;42540:7;;;;;;;;:::i;:::-;;;;;;;:23;;;;:::i;:::-;42539:43;;;;:::i;:::-;42521:11;42533:1;42521:14;;;;;;;;:::i;:::-;;;;;;;:62;;;;:::i;:::-;42502:4;:13;;42516:1;42502:16;;;;;;;;:::i;:::-;;;;;;;;:81;;;;42620:4;42625:1;42620:7;;;;;;;;:::i;:::-;;;;;;;42602:11;42614:1;42602:14;;;;;;;;:::i;:::-;;;;;;:25;;;;;;;:::i;:::-;;;-1:-1:-1;42337:3:0;;;;:::i;:::-;;;;42305:338;;;;42662:51;42668:39;42672:11;42685:4;:21;;42668:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:3;:39::i;42662:51::-;42657:56;-1:-1:-1;42769:2:0;42757:7;42769:2;42657:56;42757:7;:::i;:::-;42742:23;;:11;:23;:::i;:::-;42741:30;;;;:::i;:::-;42728:43;;42259:524;42147:636;42817:13;42803:10;:27;;42795:50;;;;-1:-1:-1;;;42795:50:0;;;;;;;:::i;:::-;42858:12;;;;:41;;-1:-1:-1;;;42858:41:0;;42876:10;42858:41;;;8962:51:1;9029:18;;;9022:34;;;-1:-1:-1;;;;;42858:12:0;;;;:17;;8935:18:1;;42858:41:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;42928:10;-1:-1:-1;;;;;42915:55:0;;42940:7;42949:4;42955:2;42959:10;42915:55;;;;;;;;;:::i;52171:658::-;52339:7;52359:35;52397:9;52401:4;52397:3;:9::i;:::-;52359:47;;52417:20;52482:4;:21;;52504:7;52482:30;;;;;;;;:::i;:::-;;;;;;;;;52471:8;:41;;;;:::i;:::-;52440:18;52459:7;52440:27;;;;;;;;:::i;:::-;;;;;;;:73;;;;:::i;:::-;52417:96;;52524:18;52545:64;52551:4;52557:7;52566:8;52576:12;52590:18;52545:5;:64::i;:::-;52524:85;;52620:17;52690:4;:21;;52712:8;52690:31;;;;;;;;:::i;:::-;;;;;;;;;52685:1;52672:10;52641:18;52660:8;52641:28;;;;;;;;:::i;:::-;;;;;;;:41;;;;:::i;:::-;:45;;;;:::i;:::-;52640:81;;;;:::i;:::-;52620:101;;52732:12;39601:4;52759:9;52748:4;:8;;;:20;;;;:::i;:::-;52747:40;;;;:::i;:::-;52732:55;-1:-1:-1;52805:16:0;52732:55;52805:9;:16;:::i;:::-;52798:23;52171:658;-1:-1:-1;;;;;;;;;;52171:658:0:o;52837:214::-;52963:16;53004:39;53030:4;53036:6;53004:25;:39::i;54423:147::-;54485:16;54521:41;54525:4;:13;;54521:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;54540:4;:21;;54521:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:3;:41::i;53456:633::-;53527:7;53570:4;:16;;;53551:15;:35;53547:87;;-1:-1:-1;53610:12:0;;;;53456:633::o;53547:87::-;53665:4;:13;;;53650:4;:12;;;:28;53646:248;;;53864:4;:17;;;53845:4;:16;;;:36;;;;:::i;:::-;53805:17;;;;53787:35;;:15;:35;:::i;:::-;53769:4;:13;;;53754:4;:12;;;:28;;;;:::i;:::-;53753:70;;;;:::i;:::-;53752:130;;;;:::i;:::-;53719:4;:13;;;:163;;;;:::i;53646:248::-;54063:4;:17;;;54044:4;:16;;;:36;;;;:::i;:::-;54008:17;;;;53990:35;;:15;:35;:::i;:::-;53973:4;:12;;;53957:4;:13;;;:28;;;;:::i;:::-;53956:70;;;;:::i;:::-;53955:126;;;;:::i;:::-;53926:4;:13;;;:155;;;;:::i;54704:1118::-;54813:9;;54776:7;;;54847:10;54813:2;54847:6;:10::i;:::-;54833:24;-1:-1:-1;54872:8:0;54868:49;;54904:1;54897:8;;;;;;54868:49;54929:13;54969:3;54929:13;54997:12;55003:6;54997:3;:12;:::i;:::-;54983:26;;55027:9;55022:486;39943:3;55042:1;:17;55022:486;;;55095:1;55081:11;55111:109;55135:2;:9;55131:1;:13;55111:109;;;55197:6;55189:2;55192:1;55189:5;;;;;;;;:::i;:::-;;;;;;;:14;;;;:::i;:::-;55177:7;55183:1;55177:3;:7;:::i;:::-;55176:28;;;;:::i;:::-;55170:34;-1:-1:-1;55146:3:0;;;;:::i;:::-;;;;55111:109;;;;55242:1;55234:9;;55405:3;55391:6;55400:1;55391:10;;;;:::i;:::-;55390:18;;;;:::i;:::-;39841:3;55371:1;55350:17;39841:3;55350;:17;:::i;:::-;55349:23;;;;:::i;:::-;55348:39;;;;:::i;:::-;:60;;;;:::i;:::-;55325:1;55309:12;55315:6;55309:3;:12;:::i;:::-;39841:3;55282:9;55288:3;55282;:9;:::i;:::-;55281:25;;;;:::i;:::-;:40;;;;:::i;:::-;55280:46;;;;:::i;:::-;55279:130;;;;:::i;:::-;55258:151;;55451:1;55428:19;55438:1;55441:5;55428:9;:19::i;:::-;:24;55424:73;;55480:1;55473:8;;;;;;;;;;;55424:73;-1:-1:-1;55061:3:0;;;;:::i;:::-;;;;55022:486;;;-1:-1:-1;55778:36:0;;-1:-1:-1;;;55778:36:0;;12748:2:1;55778:36:0;;;12730:21:1;12787:2;12767:18;;;12760:30;12826:28;12806:18;;;12799:56;12872:18;;55778:36:0;12546:350:1;60730:283:0;60844:30;;-1:-1:-1;;;60844:30:0;;60868:4;60844:30;;;6978:51:1;60801:7:0;;;;-1:-1:-1;;;;;60844:15:0;;;;;6951:18:1;;60844:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;60821:53;-1:-1:-1;60885:57:0;-1:-1:-1;;;;;60885:22:0;;60908:10;60928:4;60935:6;60885:22;:57::i;:::-;60960:30;;-1:-1:-1;;;60960:30:0;;60984:4;60960:30;;;6978:51:1;60993:12:0;;-1:-1:-1;;;;;60960:15:0;;;;;6951:18:1;;60960:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:45;;;;:::i;56380:1351::-;56587:7;56626:8;56615:7;:19;;56607:41;;;;-1:-1:-1;;;56607:41:0;;13103:2:1;56607:41:0;;;13085:21:1;13142:1;13122:18;;;13115:29;-1:-1:-1;;;13160:18:1;;;13153:39;13209:18;;56607:41:0;12901:332:1;56607:41:0;56676:24;;56719:16;;;:37;;;;;56750:6;56739:8;:17;56719:37;56711:65;;;;-1:-1:-1;;;56711:65:0;;;;;;;:::i;:::-;56789:11;56803:18;56816:4;56803:12;:18::i;:::-;56789:32;-1:-1:-1;56832:11:0;56846:12;56852:6;56789:32;56846:12;:::i;:::-;56832:26;;56869:9;56881:30;56887:18;56907:3;56881:5;:30::i;:::-;56869:42;-1:-1:-1;56924:11:0;56869:42;56924:11;57017:266;57041:6;57037:1;:10;57017:266;;;57078:8;57073:1;:13;57069:62;;;57107:8;;57069:62;57147:9;57164:7;57159:1;:12;:48;;57186:18;57205:1;57186:21;;;;;;;;:::i;:::-;;;;;;;57159:48;;;57174:9;57159:48;57147:60;-1:-1:-1;57222:8:0;57147:60;57222:8;;:::i;:::-;;-1:-1:-1;57260:10:0;57264:6;57260:1;:10;:::i;:::-;57250:5;57254:1;57250;:5;:::i;:::-;57249:22;;;;:::i;:::-;57245:26;;57054:229;57017:266;57049:3;;;;:::i;:::-;;;;57017:266;;;-1:-1:-1;57324:12:0;57330:6;57324:3;:12;:::i;:::-;39841:3;57300:5;57304:1;57300;:5;:::i;:::-;:19;;;;:::i;:::-;57299:38;;;;:::i;:::-;57295:42;-1:-1:-1;57348:9:0;57386:3;57367:15;39841:3;57367:1;:15;:::i;:::-;57366:23;;;;:::i;:::-;57360:29;;:3;:29;:::i;:::-;57348:41;-1:-1:-1;57402:13:0;57442:1;57402:13;57456:227;39943:3;57480:5;:21;57456:227;;;57535:1;57527:9;;57582:1;57578;57574;57570;:5;;;;:::i;:::-;:9;;;;:::i;:::-;:13;;;;:::i;:::-;57564:1;57556:5;57560:1;;57556:5;:::i;:::-;:9;;;;:::i;:::-;57555:29;;;;:::i;:::-;57551:33;;57626:1;57603:19;57613:5;57620:1;57603:9;:19::i;:::-;:24;57599:73;;-1:-1:-1;57655:1:0;-1:-1:-1;57648:8:0;;-1:-1:-1;;;;;;;;57648:8:0;57599:73;57503:7;;;;:::i;:::-;;;;57456:227;;;-1:-1:-1;57695:28:0;;-1:-1:-1;;;57695:28:0;;15237:2:1;57695:28:0;;;15219:21:1;15276:2;15256:18;;;15249:30;-1:-1:-1;;;15295:18:1;;;15288:48;15353:18;;57695:28:0;15035:342:1;35126:211:0;35270:58;;-1:-1:-1;;;;;8980:32:1;;35270:58:0;;;8962:51:1;9029:18;;;9022:34;;;35243:86:0;;35263:5;;-1:-1:-1;;;35293:23:0;8935:18:1;;35270:58:0;;;;-1:-1:-1;;35270:58:0;;;;;;;;;;;;;;-1:-1:-1;;;;;35270:58:0;-1:-1:-1;;;;;;35270:58:0;;;;;;;;;;35243:19;:86::i;:::-;35126:211;;;:::o;54159:256::-;54246:16;54280:9;54275:108;54299:8;:15;54295:1;:19;54275:108;;;54359:8;54368:1;54359:11;;;;;;;;:::i;:::-;;;;;;;54348:5;54354:1;54348:8;;;;;;;;:::i;:::-;;;;;;;:22;;;;:::i;:::-;54336:5;54342:1;54336:8;;;;;;;;:::i;:::-;;;;;;;;;;:35;54316:3;;;;:::i;:::-;;;;54275:108;;;-1:-1:-1;54402:5:0;;54159:256;-1:-1:-1;;54159:256:0:o;58291:1178::-;58505:24;;58453:10;;;;58497:32;;58489:60;;;;-1:-1:-1;;;58489:60:0;;;;;;;:::i;:::-;58560:11;58574:18;58587:4;58574:12;:18::i;:::-;58560:32;;58603:19;58625:9;58629:4;58625:3;:9::i;:::-;58603:31;;58645:10;58658:14;58664:2;58668:3;58658:5;:14::i;:::-;58645:27;;58683:10;58722:4;:12;;;;;;;;;;-1:-1:-1;;;;;58722:12:0;-1:-1:-1;;;;;58722:24:0;;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;58702:16;58716:2;58702:11;:16;:::i;:::-;58701:47;;;;:::i;:::-;58696:52;;:2;:52;:::i;:::-;58683:65;;58759:12;58774:32;58781:4;58787:3;58792:5;58799:2;58803;58774:6;:32::i;:::-;58759:47;-1:-1:-1;58846:2:0;58817:26;58874:18;58887:4;58874:12;:18::i;:::-;58859:33;;58910:9;58905:353;58929:24;;58925:28;;58905:353;;;58975:18;59021:5;59016:1;:10;59012:167;;;59080:4;59075:2;59069;59061;59064:1;59061:5;;;;;;;;:::i;:::-;;;;;;;:10;;;;:::i;:::-;59060:17;;;;:::i;:::-;:24;;;;:::i;:::-;59047:37;;59012:167;;;59161:2;59155;59147;59150:1;59147:5;;;;;;;;:::i;:::-;;;;;;;:10;;;;:::i;:::-;59146:17;;;;:::i;:::-;59138:2;59141:1;59138:5;;;;;;;;:::i;:::-;;;;;;;:25;;;;:::i;:::-;59125:38;;59012:167;39601:4;59210:17;59217:10;59210:4;:17;:::i;:::-;59209:37;;;;:::i;:::-;59193:9;59203:1;59193:12;;;;;;;;:::i;:::-;;;;;;:53;;;;;;;:::i;:::-;;;-1:-1:-1;58955:3:0;;-1:-1:-1;58955:3:0;;;:::i;:::-;;;;58905:353;;;;59294:39;59301:4;59307:3;59312:5;59319:9;59330:2;59294:6;:39::i;:::-;59275:9;59285:5;59275:16;;;;;;;;:::i;:::-;;;;;;;:58;;;;:::i;:::-;59270:63;;59360:4;:21;;59382:5;59360:28;;;;;;;;:::i;:::-;;;;;;;;;59355:1;59350:2;:6;;;;:::i;:::-;59349:39;;;;:::i;:::-;59344:44;;59459:2;59427:4;:21;;59449:5;59427:28;;;;;;;;:::i;:::-;;;;;;;;;59419:4;59407:2;59410:5;59407:9;;;;;;;;:::i;:::-;;;;;;;:16;;;;:::i;:::-;59406:49;;;;:::i;:::-;59405:56;;;;:::i;:::-;59399:62;;58478:991;;;;;;;58291:1178;;;;;;:::o;59477:198::-;59585:24;;59548:7;;59655:10;59664:1;59585:24;59655:10;:::i;:::-;59650:16;;:1;:16;:::i;:::-;59639:6;59628:4;:8;;;:17;;;;:::i;:::-;59627:40;;;;:::i;61214:120::-;61278:7;61309:1;61305;:5;:21;;61321:5;61325:1;61321;:5;:::i;:::-;61305:21;;;61313:5;61317:1;61313;:5;:::i;57739:544::-;57866:16;57900:19;57922:4;:12;;;;;;;;;;-1:-1:-1;;;;;57922:12:0;-1:-1:-1;;;;;57922:24:0;;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;57900:48;;57977:11;57967:6;:21;;57959:60;;;;-1:-1:-1;;;57959:60:0;;15995:2:1;57959:60:0;;;15977:21:1;16034:2;16014:18;;;16007:30;16073:28;16053:18;;;16046:56;16119:18;;57959:60:0;15793:350:1;57959:60:0;58073:24;;58032;;58059:39;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;58059:39:0;;58032:66;;58116:9;58111:140;58135:24;;58131:28;;58111:140;;;58227:11;58215:6;58195:4;:13;;58209:1;58195:16;;;;;;;;:::i;:::-;;;;;;;;;:27;;;;:::i;:::-;58194:45;;;;:::i;:::-;58181:7;58189:1;58181:10;;;;;;;;:::i;:::-;;;;;;;;;;:58;58161:3;;;;:::i;:::-;;;;58111:140;;61021:185;61080:11;61127:9;61122:77;61146:1;:8;61142:1;:12;61122:77;;;61183:1;61185;61183:4;;;;;;;;:::i;:::-;;;;;;;61176:11;;;;;:::i;:::-;;-1:-1:-1;61156:3:0;;;;:::i;:::-;;;;61122:77;;;;61021:185;;;:::o;35345:248::-;35516:68;;-1:-1:-1;;;;;7298:15:1;;;35516:68:0;;;7280:34:1;7350:15;;7330:18;;;7323:43;7382:18;;;7375:34;;;35489:96:0;;35509:5;;-1:-1:-1;;;35539:27:0;7215:18:1;;35516:68:0;7040:375:1;35489:96:0;35345:248;;;;:::o;37699:716::-;38123:23;38149:69;38177:4;38149:69;;;;;;;;;;;;;;;;;38157:5;-1:-1:-1;;;;;38149:27:0;;;:69;;;;;:::i;:::-;38233:17;;38123:95;;-1:-1:-1;38233:21:0;38229:179;;38330:10;38319:30;;;;;;;;;;;;:::i;:::-;38311:85;;;;-1:-1:-1;;;38311:85:0;;15584:2:1;38311:85:0;;;15566:21:1;15623:2;15603:18;;;15596:30;15662:34;15642:18;;;15635:62;-1:-1:-1;;;15713:18:1;;;15706:40;15763:19;;38311:85:0;15382:406:1;59683:1039:0;59895:24;;59858:7;;59937:14;;;59930:22;;;;:::i;:::-;59963:11;59977:10;59981:6;59977:1;:10;:::i;:::-;59963:24;-1:-1:-1;60010:1:0;59998:9;;;;60101:211;60125:6;60121:1;:10;60101:211;;;60162:5;60157:1;:10;60153:59;;;60188:8;;60153:59;60231:2;60234:1;60231:5;;;;;;;;:::i;:::-;;;;;;;60226:10;;60256:2;60251:7;;;;;:::i;:::-;;-1:-1:-1;60288:11:0;60293:6;60288:2;:11;:::i;:::-;60278:5;60282:1;60278;:5;:::i;:::-;60277:23;;;;:::i;:::-;60273:27;;60101:211;60133:3;;;;:::i;:::-;;;;60101:211;;;-1:-1:-1;60353:12:0;60359:6;60353:3;:12;:::i;:::-;39841:3;60329:5;60333:1;60329;:5;:::i;:::-;:19;;;;:::i;:::-;60328:38;;;;:::i;:::-;60324:42;-1:-1:-1;60377:9:0;60413:3;60394:15;39841:3;60394:1;:15;:::i;:::-;60393:23;;;;:::i;:::-;60389:27;;:1;:27;:::i;:::-;60377:39;-1:-1:-1;60439:1:0;60427:9;60453:215;39943:3;60473:1;:17;60453:215;;;60520:1;60512:9;;60567:1;60563;60559;60555;:5;;;;:::i;:::-;:9;;;;:::i;:::-;:13;;;;:::i;:::-;60549:1;60541:5;60545:1;;60541:5;:::i;:::-;:9;;;;:::i;:::-;60540:29;;;;:::i;:::-;60536:33;;60611:1;60588:19;60598:5;60605:1;60588:9;:19::i;:::-;:24;60584:73;;-1:-1:-1;60640:1:0;-1:-1:-1;60633:8:0;;-1:-1:-1;;;;;;;60633:8:0;60584:73;60492:3;;;;:::i;:::-;;;;60453:215;;7401:229;7538:12;7570:52;7592:6;7600:4;7606:1;7609:12;7538;-1:-1:-1;;;;;4951:19:0;;;8808:60;;;;-1:-1:-1;;;8808:60:0;;14879:2:1;8808:60:0;;;14861:21:1;14918:2;14898:18;;;14891:30;14957:31;14937:18;;;14930:59;15006:18;;8808:60:0;14677:353:1;8808:60:0;8882:12;8896:23;8923:6;-1:-1:-1;;;;;8923:11:0;8942:5;8949:4;8923:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8881:73;;;;8972:51;8989:7;8998:10;9010:12;8972:16;:51::i;:::-;8965:58;8521:510;-1:-1:-1;;;;;;;8521:510:0:o;11207:712::-;11357:12;11386:7;11382:530;;;-1:-1:-1;11417:10:0;11410:17;;11382:530;11531:17;;:21;11527:374;;11729:10;11723:17;11790:15;11777:10;11773:2;11769:19;11762:44;11527:374;11872:12;11865:20;;-1:-1:-1;;;11865:20:0;;;;;;;;:::i;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;14:913:1;68:5;121:3;114:4;106:6;102:17;98:27;88:55;;139:1;136;129:12;88:55;175:6;162:20;201:4;224:18;261:2;257;254:10;251:36;;;267:18;;:::i;:::-;313:2;310:1;306:10;345:2;339:9;408:2;404:7;399:2;395;391:11;387:25;379:6;375:38;463:6;451:10;448:22;443:2;431:10;428:18;425:46;422:72;;;474:18;;:::i;:::-;510:2;503:22;560:18;;;594:15;;;;-1:-1:-1;629:15:1;;;663;;;659:24;;656:33;-1:-1:-1;653:53:1;;;702:1;699;692:12;653:53;724:1;715:10;;734:163;748:2;745:1;742:9;734:163;;;805:17;;793:30;;843:12;;;;766:1;759:9;;;;;875:12;;734:163;;;-1:-1:-1;915:6:1;14:913;-1:-1:-1;;;;;;;14:913:1:o;932:245::-;999:6;1052:2;1040:9;1031:7;1027:23;1023:32;1020:52;;;1068:1;1065;1058:12;1020:52;1100:9;1094:16;1119:28;1141:5;1119:28;:::i;1182:210::-;1271:6;1324:2;1312:9;1303:7;1299:23;1295:32;1292:52;;;1340:1;1337;1330:12;1292:52;-1:-1:-1;1363:23:1;;1182:210;-1:-1:-1;1182:210:1:o;1397:1090::-;1549:6;1557;1565;1573;1581;1634:3;1622:9;1613:7;1609:23;1605:33;1602:53;;;1651:1;1648;1641:12;1602:53;1687:9;1674:23;1664:33;;1748:2;1737:9;1733:18;1720:32;1771:18;1812:2;1804:6;1801:14;1798:34;;;1828:1;1825;1818:12;1798:34;1851:61;1904:7;1895:6;1884:9;1880:22;1851:61;:::i;:::-;1841:71;-1:-1:-1;1962:2:1;1947:18;;1934:32;;-1:-1:-1;;;;;;1995:31:1;;1985:42;;1975:70;;2041:1;2038;2031:12;1975:70;2064:5;;-1:-1:-1;2122:2:1;2107:18;;2094:32;;2138:16;;;2135:36;;;2167:1;2164;2157:12;2135:36;2205:8;2194:9;2190:24;2180:34;;2252:7;2245:4;2241:2;2237:13;2233:27;2223:55;;2274:1;2271;2264:12;2223:55;2314:2;2301:16;2340:2;2332:6;2329:14;2326:34;;;2356:1;2353;2346:12;2326:34;2401:7;2396:2;2387:6;2383:2;2379:15;2375:24;2372:37;2369:57;;;2422:1;2419;2412:12;2369:57;1397:1090;;;;-1:-1:-1;1397:1090:1;;-1:-1:-1;2453:2:1;2445:11;;2475:6;1397:1090;-1:-1:-1;;;1397:1090:1:o;2492:575::-;2621:6;2629;2637;2690:2;2678:9;2669:7;2665:23;2661:32;2658:52;;;2706:1;2703;2696:12;2658:52;2742:9;2729:23;2719:33;;2803:2;2792:9;2788:18;2775:32;2830:18;2822:6;2819:30;2816:50;;;2862:1;2859;2852:12;2816:50;2885:61;2938:7;2929:6;2918:9;2914:22;2885:61;:::i;:::-;2875:71;;;2996:2;2985:9;2981:18;2968:32;3009:28;3031:5;3009:28;:::i;:::-;3056:5;3046:15;;;2492:575;;;;;:::o;3072:514::-;3204:6;3212;3220;3273:2;3261:9;3252:7;3248:23;3244:32;3241:52;;;3289:1;3286;3279:12;3241:52;3325:9;3312:23;3302:33;;3386:2;3375:9;3371:18;3358:32;3413:18;3405:6;3402:30;3399:50;;;3445:1;3442;3435:12;3399:50;3468:61;3521:7;3512:6;3501:9;3497:22;3468:61;:::i;:::-;3458:71;;;3576:2;3565:9;3561:18;3548:32;3538:42;;3072:514;;;;;:::o;3591:278::-;3689:6;3697;3750:2;3738:9;3729:7;3725:23;3721:32;3718:52;;;3766:1;3763;3756:12;3718:52;-1:-1:-1;;3789:23:1;;;3859:2;3844:18;;;3831:32;;-1:-1:-1;3591:278:1:o;3874:514::-;4006:6;4014;4022;4075:2;4063:9;4054:7;4050:23;4046:32;4043:52;;;4091:1;4088;4081:12;4043:52;4127:9;4114:23;4104:33;;4184:2;4173:9;4169:18;4156:32;4146:42;;4239:2;4228:9;4224:18;4211:32;4266:18;4258:6;4255:30;4252:50;;;4298:1;4295;4288:12;4252:50;4321:61;4374:7;4365:6;4354:9;4350:22;4321:61;:::i;:::-;4311:71;;;3874:514;;;;;:::o;4393:346::-;4500:6;4508;4516;4569:2;4557:9;4548:7;4544:23;4540:32;4537:52;;;4585:1;4582;4575:12;4537:52;-1:-1:-1;;4608:23:1;;;4678:2;4663:18;;4650:32;;-1:-1:-1;4729:2:1;4714:18;;;4701:32;;4393:346;-1:-1:-1;4393:346:1:o;4744:415::-;4860:6;4868;4876;4884;4937:3;4925:9;4916:7;4912:23;4908:33;4905:53;;;4954:1;4951;4944:12;4905:53;-1:-1:-1;;4977:23:1;;;5047:2;5032:18;;5019:32;;-1:-1:-1;5098:2:1;5083:18;;5070:32;;5149:2;5134:18;5121:32;;-1:-1:-1;4744:415:1;-1:-1:-1;4744:415:1:o;5164:484::-;5289:6;5297;5305;5313;5321;5374:3;5362:9;5353:7;5349:23;5345:33;5342:53;;;5391:1;5388;5381:12;5342:53;-1:-1:-1;;5414:23:1;;;5484:2;5469:18;;5456:32;;-1:-1:-1;5535:2:1;5520:18;;5507:32;;5586:2;5571:18;;5558:32;;-1:-1:-1;5637:3:1;5622:19;5609:33;;-1:-1:-1;5164:484:1;-1:-1:-1;5164:484:1:o;5653:184::-;5723:6;5776:2;5764:9;5755:7;5751:23;5747:32;5744:52;;;5792:1;5789;5782:12;5744:52;-1:-1:-1;5815:16:1;;5653:184;-1:-1:-1;5653:184:1:o;5842:435::-;5895:3;5933:5;5927:12;5960:6;5955:3;5948:19;5986:4;6015:2;6010:3;6006:12;5999:19;;6052:2;6045:5;6041:14;6073:1;6083:169;6097:6;6094:1;6091:13;6083:169;;;6158:13;;6146:26;;6192:12;;;;6227:15;;;;6119:1;6112:9;6083:169;;;-1:-1:-1;6268:3:1;;5842:435;-1:-1:-1;;;;;5842:435:1:o;6282:266::-;6370:6;6365:3;6358:19;6422:6;6415:5;6408:4;6403:3;6399:14;6386:43;-1:-1:-1;6474:1:1;6449:16;;;6467:4;6445:27;;;6438:38;;;;6530:2;6509:15;;;-1:-1:-1;;6505:29:1;6496:39;;;6492:50;;6282:266::o;6553:274::-;6682:3;6720:6;6714:13;6736:53;6782:6;6777:3;6770:4;6762:6;6758:17;6736:53;:::i;:::-;6805:16;;;;;6553:274;-1:-1:-1;;6553:274:1:o;7420:1363::-;7813:4;7861:3;7850:9;7846:19;7901:1;7897;7892:3;7888:11;7884:19;7942:2;7934:6;7930:15;7919:9;7912:34;7965:2;8003:3;7998:2;7987:9;7983:18;7976:31;8027:6;8062;8056:13;8093:6;8085;8078:22;8131:3;8120:9;8116:19;8109:26;;8154:6;8151:1;8144:17;8197:2;8194:1;8184:16;8170:30;;8218:1;8228:177;8242:6;8239:1;8236:13;8228:177;;;8307:13;;8303:22;;8291:35;;8393:1;8381:14;;;;8346:12;;;;8257:9;8228:177;;;8232:3;;8450:9;8445:3;8441:19;8436:2;8425:9;8421:18;8414:47;8484:41;8521:3;8513:6;8484:41;:::i;:::-;8470:55;;;;;8573:9;8565:6;8561:22;8556:2;8545:9;8541:18;8534:50;8607:44;8644:6;8636;8607:44;:::i;:::-;8593:58;;8700:9;8692:6;8688:22;8682:3;8671:9;8667:19;8660:51;8728:49;8770:6;8762;8754;8728:49;:::i;:::-;8720:57;7420:1363;-1:-1:-1;;;;;;;;;7420:1363:1:o;9067:640::-;9246:2;9298:21;;;9368:13;;9271:18;;;9390:22;;;9217:4;;9246:2;9469:15;;;;9443:2;9428:18;;;9217:4;9512:169;9526:6;9523:1;9520:13;9512:169;;;9587:13;;9575:26;;9656:15;;;;9621:12;;;;9548:1;9541:9;9512:169;;;-1:-1:-1;9698:3:1;;9067:640;-1:-1:-1;;;;;;9067:640:1:o;9712:261::-;9891:2;9880:9;9873:21;9854:4;9911:56;9963:2;9952:9;9948:18;9940:6;9911:56;:::i;9978:536::-;10263:2;10252:9;10245:21;10226:4;10289:56;10341:2;10330:9;10326:18;10318:6;10289:56;:::i;:::-;10393:9;10385:6;10381:22;10376:2;10365:9;10361:18;10354:50;10421:44;10458:6;10450;10421:44;:::i;:::-;10413:52;;;10501:6;10496:2;10485:9;10481:18;10474:34;9978:536;;;;;;:::o;10519:609::-;10832:3;10821:9;10814:22;10795:4;10859:57;10911:3;10900:9;10896:19;10888:6;10859:57;:::i;:::-;10964:9;10956:6;10952:22;10947:2;10936:9;10932:18;10925:50;10992:44;11029:6;11021;10992:44;:::i;:::-;11067:2;11052:18;;11045:34;;;;-1:-1:-1;;11110:2:1;11095:18;11088:34;10984:52;10519:609;-1:-1:-1;;10519:609:1:o;11133:383::-;11282:2;11271:9;11264:21;11245:4;11314:6;11308:13;11357:6;11352:2;11341:9;11337:18;11330:34;11373:66;11432:6;11427:2;11416:9;11412:18;11407:2;11399:6;11395:15;11373:66;:::i;:::-;11500:2;11479:15;-1:-1:-1;;11475:29:1;11460:45;;;;11507:2;11456:54;;11133:383;-1:-1:-1;;11133:383:1:o;11521:339::-;11723:2;11705:21;;;11762:2;11742:18;;;11735:30;-1:-1:-1;;;11796:2:1;11781:18;;11774:45;11851:2;11836:18;;11521:339::o;16148:344::-;16350:2;16332:21;;;16389:2;16369:18;;;16362:30;-1:-1:-1;;;16423:2:1;16408:18;;16401:50;16483:2;16468:18;;16148:344::o;16497:334::-;16699:2;16681:21;;;16738:2;16718:18;;;16711:30;-1:-1:-1;;;16772:2:1;16757:18;;16750:40;16822:2;16807:18;;16497:334::o;18455:128::-;18495:3;18526:1;18522:6;18519:1;18516:13;18513:39;;;18532:18;;:::i;:::-;-1:-1:-1;18568:9:1;;18455:128::o;18588:217::-;18628:1;18654;18644:132;;18698:10;18693:3;18689:20;18686:1;18679:31;18733:4;18730:1;18723:15;18761:4;18758:1;18751:15;18644:132;-1:-1:-1;18790:9:1;;18588:217::o;18810:422::-;18899:1;18942:5;18899:1;18956:270;18977:7;18967:8;18964:21;18956:270;;;19036:4;19032:1;19028:6;19024:17;19018:4;19015:27;19012:53;;;19045:18;;:::i;:::-;19095:7;19085:8;19081:22;19078:55;;;19115:16;;;;19078:55;19194:22;;;;19154:15;;;;18956:270;;;18960:3;18810:422;;;;;:::o;19237:131::-;19297:5;19326:36;19353:8;19347:4;19422:5;19452:8;19442:80;;-1:-1:-1;19493:1:1;19507:5;;19442:80;19541:4;19531:76;;-1:-1:-1;19578:1:1;19592:5;;19531:76;19623:4;19641:1;19636:59;;;;19709:1;19704:130;;;;19616:218;;19636:59;19666:1;19657:10;;19680:5;;;19704:130;19741:3;19731:8;19728:17;19725:43;;;19748:18;;:::i;:::-;-1:-1:-1;;19804:1:1;19790:16;;19819:5;;19616:218;;19918:2;19908:8;19905:16;19899:3;19893:4;19890:13;19886:36;19880:2;19870:8;19867:16;19862:2;19856:4;19853:12;19849:35;19846:77;19843:159;;;-1:-1:-1;19955:19:1;;;19987:5;;19843:159;20034:34;20059:8;20053:4;20034:34;:::i;:::-;20104:6;20100:1;20096:6;20092:19;20083:7;20080:32;20077:58;;;20115:18;;:::i;:::-;20153:20;;19373:806;-1:-1:-1;;;19373:806:1:o;20184:168::-;20224:7;20290:1;20286;20282:6;20278:14;20275:1;20272:21;20267:1;20260:9;20253:17;20249:45;20246:71;;;20297:18;;:::i;:::-;-1:-1:-1;20337:9:1;;20184:168::o;20357:125::-;20397:4;20425:1;20422;20419:8;20416:34;;;20430:18;;:::i;:::-;-1:-1:-1;20467:9:1;;20357:125::o;20487:258::-;20559:1;20569:113;20583:6;20580:1;20577:13;20569:113;;;20659:11;;;20653:18;20640:11;;;20633:39;20605:2;20598:10;20569:113;;;20700:6;20697:1;20694:13;20691:48;;;-1:-1:-1;;20735:1:1;20717:16;;20710:27;20487:258::o;20750:135::-;20789:3;-1:-1:-1;;20810:17:1;;20807:43;;;20830:18;;:::i;:::-;-1:-1:-1;20877:1:1;20866:13;;20750:135::o;20890:127::-;20951:10;20946:3;20942:20;20939:1;20932:31;20982:4;20979:1;20972:15;21006:4;21003:1;20996:15;21022:127;21083:10;21078:3;21074:20;21071:1;21064:31;21114:4;21111:1;21104:15;21138:4;21135:1;21128:15;21154:127;21215:10;21210:3;21206:20;21203:1;21196:31;21246:4;21243:1;21236:15;21270:4;21267:1;21260:15;21286:127;21347:10;21342:3;21338:20;21335:1;21328:31;21378:4;21375:1;21368:15;21402:4;21399:1;21392:15;21418:118;21504:5;21497:13;21490:21;21483:5;21480:32;21470:60;;21526:1;21523;21516:12;21470:60;21418:118;:::o
Swarm Source
ipfs://57a1863b038e4fd3218ca5368ab559266e254a8a019bdaf7dc908a5ef1b90a87
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in MOVR
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.