Contract
0xe1dad9e06380bc8962e259ddd6a5257a4f56d525
4
Contract Overview
[ Download CSV Export ]
Latest 1 internal transaction
Parent Txn Hash | Block | From | To | Value | |||
---|---|---|---|---|---|---|---|
0x97c4b5d75beca3d8b530a6e84fb6768c4e58e73b1170f907e160e66c6edbb210 | 4430342 | 283 days 2 hrs ago | Kyber Swap: Factory | Contract Creation | 0 AVAX |
[ Download CSV Export ]
Similar Match Source Code
Note: This contract matches the deployed ByteCode of the Source Code for Contract 0x535a99a079d64b8c3f4cc264eba70d82992b224b
Contract Name:
DMMPool
Compiler Version
v0.6.12+commit.27d51765
Contract Source Code (Solidity)
/** *Submitted for verification at snowtrace.io on 2022-03-16 */ // File: @openzeppelin/contracts/math/SafeMath.sol // SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b > a) return (false, 0); return (true, a - b); } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a / b); } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a % b); } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, "SafeMath: subtraction overflow"); return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) return 0; uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: division by zero"); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: modulo by zero"); return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); return a - b; } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryDiv}. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a % b; } } // File: @openzeppelin/contracts/math/Math.sol // MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow, so we distribute return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); } } // File: @openzeppelin/contracts/utils/ReentrancyGuard.sol // MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor () internal { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } } // File: @openzeppelin/contracts/token/ERC20/IERC20.sol // MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } // File: @openzeppelin/contracts/utils/Address.sol // MIT pragma solidity >=0.6.2 <0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain`call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: value }(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } } // File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol // MIT pragma solidity >=0.6.0 <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 SafeMath for uint256; using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // solhint-disable-next-line max-line-length require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).add(value); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } // File: contracts/libraries/MathExt.sol // MIT pragma solidity 0.6.12; library MathExt { using SafeMath for uint256; uint256 public constant PRECISION = (10**18); /// @dev Returns x*y in precision function mulInPrecision(uint256 x, uint256 y) internal pure returns (uint256) { return x.mul(y) / PRECISION; } /// @dev source: dsMath /// @param xInPrecision should be < PRECISION, so this can not overflow /// @return zInPrecision = (x/PRECISION) ^k * PRECISION function unsafePowInPrecision(uint256 xInPrecision, uint256 k) internal pure returns (uint256 zInPrecision) { require(xInPrecision <= PRECISION, "MathExt: x > PRECISION"); zInPrecision = k % 2 != 0 ? xInPrecision : PRECISION; for (k /= 2; k != 0; k /= 2) { xInPrecision = (xInPrecision * xInPrecision) / PRECISION; if (k % 2 != 0) { zInPrecision = (zInPrecision * xInPrecision) / PRECISION; } } } // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) function sqrt(uint256 y) internal pure returns (uint256 z) { if (y > 3) { z = y; uint256 x = y / 2 + 1; while (x < z) { z = x; x = (y / x + x) / 2; } } else if (y != 0) { z = 1; } } } // File: contracts/libraries/FeeFomula.sol // BUSL-1.1 pragma solidity 0.6.12; library FeeFomula { using SafeMath for uint256; using MathExt for uint256; uint256 private constant PRECISION = 10**18; uint256 private constant R0 = 1477405064814996100; // 1.4774050648149961 uint256 private constant C0 = (60 * PRECISION) / 10000; uint256 private constant A = uint256(PRECISION * 20000) / 27; uint256 private constant B = uint256(PRECISION * 250) / 9; uint256 private constant C1 = uint256(PRECISION * 985) / 27; uint256 private constant U = (120 * PRECISION) / 100; uint256 private constant G = (836 * PRECISION) / 1000; uint256 private constant F = 5 * PRECISION; uint256 private constant L = (2 * PRECISION) / 10000; // C2 = 25 * PRECISION - (F * (PRECISION - G)**2) / ((PRECISION - G)**2 + L * PRECISION) uint256 private constant C2 = 20036905816356657810; /// @dev calculate fee from rFactorInPrecision, see section 3.2 in dmmSwap white paper /// @dev fee in [15, 60] bps /// @return fee percentage in Precision function getFee(uint256 rFactorInPrecision) internal pure returns (uint256) { if (rFactorInPrecision >= R0) { return C0; } else if (rFactorInPrecision >= PRECISION) { // C1 + A * (r-U)^3 + b * (r -U) if (rFactorInPrecision > U) { uint256 tmp = rFactorInPrecision - U; uint256 tmp3 = tmp.unsafePowInPrecision(3); return (C1.add(A.mulInPrecision(tmp3)).add(B.mulInPrecision(tmp))) / 10000; } else { uint256 tmp = U - rFactorInPrecision; uint256 tmp3 = tmp.unsafePowInPrecision(3); return C1.sub(A.mulInPrecision(tmp3)).sub(B.mulInPrecision(tmp)) / 10000; } } else { // [ C2 + sign(r - G) * F * (r-G) ^2 / (L + (r-G) ^2) ] / 10000 uint256 tmp = ( rFactorInPrecision > G ? (rFactorInPrecision - G) : (G - rFactorInPrecision) ); tmp = tmp.unsafePowInPrecision(2); uint256 tmp2 = F.mul(tmp).div(tmp.add(L)); if (rFactorInPrecision > G) { return C2.add(tmp2) / 10000; } else { return C2.sub(tmp2) / 10000; } } } } // File: @openzeppelin/contracts/utils/Context.sol // MIT pragma solidity >=0.6.0 <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 GSN 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 payable) { return msg.sender; } function _msgData() internal view virtual returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } // File: @openzeppelin/contracts/token/ERC20/ERC20.sol // MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin guidelines: functions revert instead * of returning `false` on failure. This behavior is nonetheless conventional * and does not conflict with the expectations of ERC20 applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20 { using SafeMath for uint256; mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; uint8 private _decimals; /** * @dev Sets the values for {name} and {symbol}, initializes {decimals} with * a default value of 18. * * To select a different value for {decimals}, use {_setupDecimals}. * * All three of these values are immutable: they can only be set once during * construction. */ constructor (string memory name_, string memory symbol_) public { _name = name_; _symbol = symbol_; _decimals = 18; } /** * @dev Returns the name of the token. */ function name() public view virtual returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is * called. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual returns (uint8) { return _decimals; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * Requirements: * * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for ``sender``'s tokens of at least * `amount`. */ function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { _transfer(sender, recipient, amount); _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); return true; } /** * @dev Moves tokens `amount` from `sender` to `recipient`. * * This is internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer(address sender, address recipient, uint256 amount) internal virtual { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(sender, recipient, amount); _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); _balances[recipient] = _balances[recipient].add(amount); emit Transfer(sender, recipient, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `to` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply = _totalSupply.add(amount); _balances[account] = _balances[account].add(amount); emit Transfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); _totalSupply = _totalSupply.sub(amount); emit Transfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve(address owner, address spender, uint256 amount) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Sets {decimals} to a value other than the default one of 18. * * WARNING: This function should only be called from the constructor. Most * applications that interact with token contracts will not expect * {decimals} to ever change, and may work incorrectly if it does. */ function _setupDecimals(uint8 decimals_) internal virtual { _decimals = decimals_; } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be to transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } } // File: contracts/interfaces/IERC20Permit.sol // MIT pragma solidity 0.6.12; interface IERC20Permit is IERC20 { function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; } // File: contracts/libraries/ERC20Permit.sol // MIT pragma solidity 0.6.12; /// @dev https://eips.ethereum.org/EIPS/eip-2612 contract ERC20Permit is ERC20, IERC20Permit { /// @dev To make etherscan auto-verify new pool, this variable is not immutable bytes32 public domainSeparator; // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; mapping(address => uint256) public nonces; constructor( string memory name, string memory symbol, string memory version ) public ERC20(name, symbol) { uint256 chainId; assembly { chainId := chainid() } domainSeparator = keccak256( abi.encode( keccak256( "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" ), keccak256(bytes(name)), keccak256(bytes(version)), chainId, address(this) ) ); } function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external override { require(deadline >= block.timestamp, "ERC20Permit: EXPIRED"); bytes32 digest = keccak256( abi.encodePacked( "\x19\x01", domainSeparator, keccak256( abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline) ) ) ); address recoveredAddress = ecrecover(digest, v, r, s); require( recoveredAddress != address(0) && recoveredAddress == owner, "ERC20Permit: INVALID_SIGNATURE" ); _approve(owner, spender, value); } } // File: contracts/interfaces/IDMMFactory.sol // BUSL-1.1 pragma solidity 0.6.12; interface IDMMFactory { function createPool( IERC20 tokenA, IERC20 tokenB, uint32 ampBps ) external returns (address pool); function setFeeConfiguration(address feeTo, uint16 governmentFeeBps) external; function setFeeToSetter(address) external; function getFeeConfiguration() external view returns (address feeTo, uint16 governmentFeeBps); function feeToSetter() external view returns (address); function allPools(uint256) external view returns (address pool); function allPoolsLength() external view returns (uint256); function getUnamplifiedPool(IERC20 token0, IERC20 token1) external view returns (address); function getPools(IERC20 token0, IERC20 token1) external view returns (address[] memory _tokenPools); function isPool( IERC20 token0, IERC20 token1, address pool ) external view returns (bool); } // File: contracts/interfaces/IDMMCallee.sol // BUSL-1.1 pragma solidity 0.6.12; interface IDMMCallee { function dmmSwapCall( address sender, uint256 amount0, uint256 amount1, bytes calldata data ) external; } // File: contracts/interfaces/IDMMPool.sol // BUSL-1.1 pragma solidity 0.6.12; interface IDMMPool { function mint(address to) external returns (uint256 liquidity); function burn(address to) external returns (uint256 amount0, uint256 amount1); function swap( uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data ) external; function sync() external; function getReserves() external view returns (uint112 reserve0, uint112 reserve1); function getTradeInfo() external view returns ( uint112 _vReserve0, uint112 _vReserve1, uint112 reserve0, uint112 reserve1, uint256 feeInPrecision ); function token0() external view returns (IERC20); function token1() external view returns (IERC20); function ampBps() external view returns (uint32); function factory() external view returns (IDMMFactory); function kLast() external view returns (uint256); } // File: contracts/interfaces/IERC20Metadata.sol // MIT pragma solidity 0.6.12; /** * @dev Interface for the optional metadata functions from the ERC20 standard. */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); } // File: contracts/VolumeTrendRecorder.sol // BUSL-1.1 pragma solidity 0.6.12; /// @dev contract to calculate volume trend. See secion 3.1 in the white paper /// @dev EMA stands for Exponential moving average /// @dev https://en.wikipedia.org/wiki/Moving_average contract VolumeTrendRecorder { using MathExt for uint256; using SafeMath for uint256; uint256 private constant MAX_UINT128 = 2**128 - 1; uint256 internal constant PRECISION = 10**18; uint256 private constant SHORT_ALPHA = (2 * PRECISION) / 5401; uint256 private constant LONG_ALPHA = (2 * PRECISION) / 10801; uint128 internal shortEMA; uint128 internal longEMA; // total volume in current block uint128 internal currentBlockVolume; uint128 internal lastTradeBlock; event UpdateEMA(uint256 shortEMA, uint256 longEMA, uint128 lastBlockVolume, uint256 skipBlock); constructor(uint128 _emaInit) public { shortEMA = _emaInit; longEMA = _emaInit; lastTradeBlock = safeUint128(block.number); } function getVolumeTrendData() external view returns ( uint128 _shortEMA, uint128 _longEMA, uint128 _currentBlockVolume, uint128 _lastTradeBlock ) { _shortEMA = shortEMA; _longEMA = longEMA; _currentBlockVolume = currentBlockVolume; _lastTradeBlock = lastTradeBlock; } /// @dev records a new trade, update ema and returns current rFactor for this trade /// @return rFactor in Precision for this trade function recordNewUpdatedVolume(uint256 blockNumber, uint256 value) internal returns (uint256) { // this can not be underflow because block.number always increases uint256 skipBlock = blockNumber - lastTradeBlock; if (skipBlock == 0) { currentBlockVolume = safeUint128( uint256(currentBlockVolume).add(value), "volume exceeds valid range" ); return calculateRFactor(uint256(shortEMA), uint256(longEMA)); } uint128 _currentBlockVolume = currentBlockVolume; uint256 _shortEMA = newEMA(shortEMA, SHORT_ALPHA, currentBlockVolume); uint256 _longEMA = newEMA(longEMA, LONG_ALPHA, currentBlockVolume); // ema = ema * (1-aplha) ^(skipBlock -1) _shortEMA = _shortEMA.mulInPrecision( (PRECISION - SHORT_ALPHA).unsafePowInPrecision(skipBlock - 1) ); _longEMA = _longEMA.mulInPrecision( (PRECISION - LONG_ALPHA).unsafePowInPrecision(skipBlock - 1) ); shortEMA = safeUint128(_shortEMA); longEMA = safeUint128(_longEMA); currentBlockVolume = safeUint128(value); lastTradeBlock = safeUint128(blockNumber); emit UpdateEMA(_shortEMA, _longEMA, _currentBlockVolume, skipBlock); return calculateRFactor(_shortEMA, _longEMA); } /// @return rFactor in Precision for this trade function getRFactor(uint256 blockNumber) internal view returns (uint256) { // this can not be underflow because block.number always increases uint256 skipBlock = blockNumber - lastTradeBlock; if (skipBlock == 0) { return calculateRFactor(shortEMA, longEMA); } uint256 _shortEMA = newEMA(shortEMA, SHORT_ALPHA, currentBlockVolume); uint256 _longEMA = newEMA(longEMA, LONG_ALPHA, currentBlockVolume); _shortEMA = _shortEMA.mulInPrecision( (PRECISION - SHORT_ALPHA).unsafePowInPrecision(skipBlock - 1) ); _longEMA = _longEMA.mulInPrecision( (PRECISION - LONG_ALPHA).unsafePowInPrecision(skipBlock - 1) ); return calculateRFactor(_shortEMA, _longEMA); } function calculateRFactor(uint256 _shortEMA, uint256 _longEMA) internal pure returns (uint256) { if (_longEMA == 0) { return 0; } return (_shortEMA * MathExt.PRECISION) / _longEMA; } /// @dev return newEMA value /// @param ema previous ema value in wei /// @param alpha in Precicion (required < Precision) /// @param value current value to update ema /// @dev ema and value is uint128 and alpha < Percison /// @dev so this function can not overflow and returned ema is not overflow uint128 function newEMA( uint128 ema, uint256 alpha, uint128 value ) internal pure returns (uint256) { assert(alpha < PRECISION); return ((PRECISION - alpha) * uint256(ema) + alpha * uint256(value)) / PRECISION; } function safeUint128(uint256 v) internal pure returns (uint128) { require(v <= MAX_UINT128, "overflow uint128"); return uint128(v); } function safeUint128(uint256 v, string memory errorMessage) internal pure returns (uint128) { require(v <= MAX_UINT128, errorMessage); return uint128(v); } } // File: contracts/DMMPool.sol // BUSL-1.1 pragma solidity 0.6.12; contract DMMPool is IDMMPool, ERC20Permit, ReentrancyGuard, VolumeTrendRecorder { using SafeMath for uint256; using SafeERC20 for IERC20; uint256 internal constant MAX_UINT112 = 2**112 - 1; uint256 internal constant BPS = 10000; struct ReserveData { uint256 reserve0; uint256 reserve1; uint256 vReserve0; uint256 vReserve1; // only used when isAmpPool = true } uint256 public constant MINIMUM_LIQUIDITY = 10**3; /// @dev To make etherscan auto-verify new pool, these variables are not immutable IDMMFactory public override factory; IERC20 public override token0; IERC20 public override token1; /// @dev uses single storage slot, accessible via getReservesData uint112 internal reserve0; uint112 internal reserve1; uint32 public override ampBps; /// @dev addition param only when amplification factor > 1 uint112 internal vReserve0; uint112 internal vReserve1; /// @dev vReserve0 * vReserve1, as of immediately after the most recent liquidity event uint256 public override kLast; event Mint(address indexed sender, uint256 amount0, uint256 amount1); event Burn(address indexed sender, uint256 amount0, uint256 amount1, address indexed to); event Swap( address indexed sender, uint256 amount0In, uint256 amount1In, uint256 amount0Out, uint256 amount1Out, address indexed to, uint256 feeInPrecision ); event Sync(uint256 vReserve0, uint256 vReserve1, uint256 reserve0, uint256 reserve1); constructor() public ERC20Permit("KyberDMM LP", "DMM-LP", "1") VolumeTrendRecorder(0) { factory = IDMMFactory(msg.sender); } // called once by the factory at time of deployment function initialize( IERC20 _token0, IERC20 _token1, uint32 _ampBps ) external { require(msg.sender == address(factory), "DMM: FORBIDDEN"); token0 = _token0; token1 = _token1; ampBps = _ampBps; } /// @dev this low-level function should be called from a contract /// which performs important safety checks function mint(address to) external override nonReentrant returns (uint256 liquidity) { (bool isAmpPool, ReserveData memory data) = getReservesData(); ReserveData memory _data; _data.reserve0 = token0.balanceOf(address(this)); _data.reserve1 = token1.balanceOf(address(this)); uint256 amount0 = _data.reserve0.sub(data.reserve0); uint256 amount1 = _data.reserve1.sub(data.reserve1); bool feeOn = _mintFee(isAmpPool, data); uint256 _totalSupply = totalSupply(); // gas savings, must be defined here since totalSupply can update in _mintFee if (_totalSupply == 0) { if (isAmpPool) { uint32 _ampBps = ampBps; _data.vReserve0 = _data.reserve0.mul(_ampBps) / BPS; _data.vReserve1 = _data.reserve1.mul(_ampBps) / BPS; } liquidity = MathExt.sqrt(amount0.mul(amount1)).sub(MINIMUM_LIQUIDITY); _mint(address(-1), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens } else { liquidity = Math.min( amount0.mul(_totalSupply) / data.reserve0, amount1.mul(_totalSupply) / data.reserve1 ); if (isAmpPool) { uint256 b = liquidity.add(_totalSupply); _data.vReserve0 = Math.max(data.vReserve0.mul(b) / _totalSupply, _data.reserve0); _data.vReserve1 = Math.max(data.vReserve1.mul(b) / _totalSupply, _data.reserve1); } } require(liquidity > 0, "DMM: INSUFFICIENT_LIQUIDITY_MINTED"); _mint(to, liquidity); _update(isAmpPool, _data); if (feeOn) kLast = getK(isAmpPool, _data); emit Mint(msg.sender, amount0, amount1); } /// @dev this low-level function should be called from a contract /// @dev which performs important safety checks /// @dev user must transfer LP token to this contract before call burn function burn(address to) external override nonReentrant returns (uint256 amount0, uint256 amount1) { (bool isAmpPool, ReserveData memory data) = getReservesData(); // gas savings IERC20 _token0 = token0; // gas savings IERC20 _token1 = token1; // gas savings uint256 balance0 = _token0.balanceOf(address(this)); uint256 balance1 = _token1.balanceOf(address(this)); require(balance0 >= data.reserve0 && balance1 >= data.reserve1, "DMM: UNSYNC_RESERVES"); uint256 liquidity = balanceOf(address(this)); bool feeOn = _mintFee(isAmpPool, data); uint256 _totalSupply = totalSupply(); // gas savings, must be defined here since totalSupply can update in _mintFee amount0 = liquidity.mul(balance0) / _totalSupply; // using balances ensures pro-rata distribution amount1 = liquidity.mul(balance1) / _totalSupply; // using balances ensures pro-rata distribution require(amount0 > 0 && amount1 > 0, "DMM: INSUFFICIENT_LIQUIDITY_BURNED"); _burn(address(this), liquidity); _token0.safeTransfer(to, amount0); _token1.safeTransfer(to, amount1); ReserveData memory _data; _data.reserve0 = _token0.balanceOf(address(this)); _data.reserve1 = _token1.balanceOf(address(this)); if (isAmpPool) { uint256 b = Math.min( _data.reserve0.mul(_totalSupply) / data.reserve0, _data.reserve1.mul(_totalSupply) / data.reserve1 ); _data.vReserve0 = Math.max(data.vReserve0.mul(b) / _totalSupply, _data.reserve0); _data.vReserve1 = Math.max(data.vReserve1.mul(b) / _totalSupply, _data.reserve1); } _update(isAmpPool, _data); if (feeOn) kLast = getK(isAmpPool, _data); // data are up-to-date emit Burn(msg.sender, amount0, amount1, to); } /// @dev this low-level function should be called from a contract /// @dev which performs important safety checks function swap( uint256 amount0Out, uint256 amount1Out, address to, bytes calldata callbackData ) external override nonReentrant { require(amount0Out > 0 || amount1Out > 0, "DMM: INSUFFICIENT_OUTPUT_AMOUNT"); (bool isAmpPool, ReserveData memory data) = getReservesData(); // gas savings require( amount0Out < data.reserve0 && amount1Out < data.reserve1, "DMM: INSUFFICIENT_LIQUIDITY" ); ReserveData memory newData; { // scope for _token{0,1}, avoids stack too deep errors IERC20 _token0 = token0; IERC20 _token1 = token1; require(to != address(_token0) && to != address(_token1), "DMM: INVALID_TO"); if (amount0Out > 0) _token0.safeTransfer(to, amount0Out); // optimistically transfer tokens if (amount1Out > 0) _token1.safeTransfer(to, amount1Out); // optimistically transfer tokens if (callbackData.length > 0) IDMMCallee(to).dmmSwapCall(msg.sender, amount0Out, amount1Out, callbackData); newData.reserve0 = _token0.balanceOf(address(this)); newData.reserve1 = _token1.balanceOf(address(this)); if (isAmpPool) { newData.vReserve0 = data.vReserve0.add(newData.reserve0).sub(data.reserve0); newData.vReserve1 = data.vReserve1.add(newData.reserve1).sub(data.reserve1); } } uint256 amount0In = newData.reserve0 > data.reserve0 - amount0Out ? newData.reserve0 - (data.reserve0 - amount0Out) : 0; uint256 amount1In = newData.reserve1 > data.reserve1 - amount1Out ? newData.reserve1 - (data.reserve1 - amount1Out) : 0; require(amount0In > 0 || amount1In > 0, "DMM: INSUFFICIENT_INPUT_AMOUNT"); uint256 feeInPrecision = verifyBalanceAndUpdateEma( amount0In, amount1In, isAmpPool ? data.vReserve0 : data.reserve0, isAmpPool ? data.vReserve1 : data.reserve1, isAmpPool ? newData.vReserve0 : newData.reserve0, isAmpPool ? newData.vReserve1 : newData.reserve1 ); _update(isAmpPool, newData); emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to, feeInPrecision); } /// @dev force balances to match reserves function skim(address to) external nonReentrant { token0.safeTransfer(to, token0.balanceOf(address(this)).sub(reserve0)); token1.safeTransfer(to, token1.balanceOf(address(this)).sub(reserve1)); } /// @dev force reserves to match balances function sync() external override nonReentrant { (bool isAmpPool, ReserveData memory data) = getReservesData(); bool feeOn = _mintFee(isAmpPool, data); ReserveData memory newData; newData.reserve0 = IERC20(token0).balanceOf(address(this)); newData.reserve1 = IERC20(token1).balanceOf(address(this)); // update virtual reserves if this is amp pool if (isAmpPool) { uint256 _totalSupply = totalSupply(); uint256 b = Math.min( newData.reserve0.mul(_totalSupply) / data.reserve0, newData.reserve1.mul(_totalSupply) / data.reserve1 ); newData.vReserve0 = Math.max(data.vReserve0.mul(b) / _totalSupply, newData.reserve0); newData.vReserve1 = Math.max(data.vReserve1.mul(b) / _totalSupply, newData.reserve1); } _update(isAmpPool, newData); if (feeOn) kLast = getK(isAmpPool, newData); } /// @dev returns data to calculate amountIn, amountOut function getTradeInfo() external virtual override view returns ( uint112 _reserve0, uint112 _reserve1, uint112 _vReserve0, uint112 _vReserve1, uint256 feeInPrecision ) { // gas saving to read reserve data _reserve0 = reserve0; _reserve1 = reserve1; uint32 _ampBps = ampBps; _vReserve0 = vReserve0; _vReserve1 = vReserve1; if (_ampBps == BPS) { _vReserve0 = _reserve0; _vReserve1 = _reserve1; } uint256 rFactorInPrecision = getRFactor(block.number); feeInPrecision = getFinalFee(FeeFomula.getFee(rFactorInPrecision), _ampBps); } /// @dev returns reserve data to calculate amount to add liquidity function getReserves() external override view returns (uint112 _reserve0, uint112 _reserve1) { _reserve0 = reserve0; _reserve1 = reserve1; } function name() public override view returns (string memory) { IERC20Metadata _token0 = IERC20Metadata(address(token0)); IERC20Metadata _token1 = IERC20Metadata(address(token1)); return string(abi.encodePacked("KyberDMM LP ", _token0.symbol(), "-", _token1.symbol())); } function symbol() public override view returns (string memory) { IERC20Metadata _token0 = IERC20Metadata(address(token0)); IERC20Metadata _token1 = IERC20Metadata(address(token1)); return string(abi.encodePacked("DMM-LP ", _token0.symbol(), "-", _token1.symbol())); } function verifyBalanceAndUpdateEma( uint256 amount0In, uint256 amount1In, uint256 beforeReserve0, uint256 beforeReserve1, uint256 afterReserve0, uint256 afterReserve1 ) internal virtual returns (uint256 feeInPrecision) { // volume = beforeReserve0 * amount1In / beforeReserve1 + amount0In (normalized into amount in token 0) uint256 volume = beforeReserve0.mul(amount1In).div(beforeReserve1).add(amount0In); uint256 rFactorInPrecision = recordNewUpdatedVolume(block.number, volume); feeInPrecision = getFinalFee(FeeFomula.getFee(rFactorInPrecision), ampBps); // verify balance update matches with fomula uint256 balance0Adjusted = afterReserve0.mul(PRECISION); balance0Adjusted = balance0Adjusted.sub(amount0In.mul(feeInPrecision)); balance0Adjusted = balance0Adjusted / PRECISION; uint256 balance1Adjusted = afterReserve1.mul(PRECISION); balance1Adjusted = balance1Adjusted.sub(amount1In.mul(feeInPrecision)); balance1Adjusted = balance1Adjusted / PRECISION; require( balance0Adjusted.mul(balance1Adjusted) >= beforeReserve0.mul(beforeReserve1), "DMM: K" ); } /// @dev update reserves function _update(bool isAmpPool, ReserveData memory data) internal { reserve0 = safeUint112(data.reserve0); reserve1 = safeUint112(data.reserve1); if (isAmpPool) { assert(data.vReserve0 >= data.reserve0 && data.vReserve1 >= data.reserve1); // never happen vReserve0 = safeUint112(data.vReserve0); vReserve1 = safeUint112(data.vReserve1); } emit Sync(data.vReserve0, data.vReserve1, data.reserve0, data.reserve1); } /// @dev if fee is on, mint liquidity equivalent to configured fee of the growth in sqrt(k) function _mintFee(bool isAmpPool, ReserveData memory data) internal returns (bool feeOn) { (address feeTo, uint16 governmentFeeBps) = factory.getFeeConfiguration(); feeOn = feeTo != address(0); uint256 _kLast = kLast; // gas savings if (feeOn) { if (_kLast != 0) { uint256 rootK = MathExt.sqrt(getK(isAmpPool, data)); uint256 rootKLast = MathExt.sqrt(_kLast); if (rootK > rootKLast) { uint256 numerator = totalSupply().mul(rootK.sub(rootKLast)).mul( governmentFeeBps ); uint256 denominator = rootK.add(rootKLast).mul(5000); uint256 liquidity = numerator / denominator; if (liquidity > 0) _mint(feeTo, liquidity); } } } else if (_kLast != 0) { kLast = 0; } } /// @dev gas saving to read reserve data function getReservesData() internal view returns (bool isAmpPool, ReserveData memory data) { data.reserve0 = reserve0; data.reserve1 = reserve1; isAmpPool = ampBps != BPS; if (isAmpPool) { data.vReserve0 = vReserve0; data.vReserve1 = vReserve1; } } function getFinalFee(uint256 feeInPrecision, uint32 _ampBps) internal pure returns (uint256) { if (_ampBps <= 20000) { return feeInPrecision; } else if (_ampBps <= 50000) { return (feeInPrecision * 20) / 30; } else if (_ampBps <= 200000) { return (feeInPrecision * 10) / 30; } else { return (feeInPrecision * 4) / 30; } } function getK(bool isAmpPool, ReserveData memory data) internal pure returns (uint256) { return isAmpPool ? data.vReserve0 * data.vReserve1 : data.reserve0 * data.reserve1; } function safeUint112(uint256 x) internal pure returns (uint112) { require(x <= MAX_UINT112, "DMM: OVERFLOW"); return uint112(x); } }
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0In","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1In","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount0Out","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1Out","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"feeInPrecision","type":"uint256"}],"name":"Swap","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"vReserve0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"vReserve1","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"reserve0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"reserve1","type":"uint256"}],"name":"Sync","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"shortEMA","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"longEMA","type":"uint256"},{"indexed":false,"internalType":"uint128","name":"lastBlockVolume","type":"uint128"},{"indexed":false,"internalType":"uint256","name":"skipBlock","type":"uint256"}],"name":"UpdateEMA","type":"event"},{"inputs":[],"name":"MINIMUM_LIQUIDITY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ampBps","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"burn","outputs":[{"internalType":"uint256","name":"amount0","type":"uint256"},{"internalType":"uint256","name":"amount1","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"domainSeparator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"contract IDMMFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReserves","outputs":[{"internalType":"uint112","name":"_reserve0","type":"uint112"},{"internalType":"uint112","name":"_reserve1","type":"uint112"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTradeInfo","outputs":[{"internalType":"uint112","name":"_reserve0","type":"uint112"},{"internalType":"uint112","name":"_reserve1","type":"uint112"},{"internalType":"uint112","name":"_vReserve0","type":"uint112"},{"internalType":"uint112","name":"_vReserve1","type":"uint112"},{"internalType":"uint256","name":"feeInPrecision","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVolumeTrendData","outputs":[{"internalType":"uint128","name":"_shortEMA","type":"uint128"},{"internalType":"uint128","name":"_longEMA","type":"uint128"},{"internalType":"uint128","name":"_currentBlockVolume","type":"uint128"},{"internalType":"uint128","name":"_lastTradeBlock","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_token0","type":"address"},{"internalType":"contract IERC20","name":"_token1","type":"address"},{"internalType":"uint32","name":"_ampBps","type":"uint32"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"kLast","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"skim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount0Out","type":"uint256"},{"internalType":"uint256","name":"amount1Out","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"callbackData","type":"bytes"}],"name":"swap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sync","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"token0","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token1","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b5060006040518060400160405280600b81526020016a04b79626572444d4d204c560ac1b815250604051806040016040528060068152602001650444d4d2d4c560d41b815250604051806040016040528060018152602001603160f81b815250828281600390805190602001906200008b929190620001ee565b508051620000a1906004906020840190620001ee565b50506005805460ff19166012179055508251602093840120815191840191909120604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f818701528082019390935260608301919091524660808301523060a0808401919091528151808403909101815260c09092019052805192019190912060065550600160085560098054600160801b6001600160801b038085169182026001600160801b03199093169190911716179055620001624362000198565b600a80546001600160801b03928316600160801b02921691909117905550600b80546001600160a01b0319163317905562000280565b60006001600160801b03821115620001ea576040805162461bcd60e51b815260206004820152601060248201526f0deeccae4ccd8deee40ead2dce86264760831b604482015290519081900360640190fd5b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200023157805160ff191683800117855562000261565b8280016001018555821562000261579182015b828111156200026157825182559160200191906001019062000244565b50620001ea9291505b80821115620001ea57600081556001016200026a565b614ae880620002906000396000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c80637464fc3d11610104578063bc25cf77116100a2578063d669402711610071578063d669402714610736578063dd62ed3e14610780578063f698da25146107bb578063fff6cae9146107c3576101da565b8063bc25cf7714610695578063c45a0155146106c8578063d21220a7146106d0578063d505accf146106d8576101da565b806395d89b41116100de57806395d89b4114610613578063a457c2d71461061b578063a9059cbb14610654578063ba9a7a561461068d576101da565b80637464fc3d1461058c5780637ecebe001461059457806389afcb44146105c7576101da565b806323b872dd1161017c57806349386b161161014b57806349386b16146104bb5780636a627842146104dc5780636ecf2b221461050f57806370a0823114610559576101da565b806323b872dd1461041957806330adf81f1461045c578063313ce567146104645780633950935114610482576101da565b8063095ea7b3116101b8578063095ea7b31461033c5780630d94d50b146103895780630dfe1681146103ce57806318160ddd146103ff576101da565b8063022c0d9f146101df57806306fdde031461027a5780630902f1ac146102f7575b600080fd5b610278600480360360808110156101f557600080fd5b81359160208101359173ffffffffffffffffffffffffffffffffffffffff604083013516919081019060808101606082013564010000000081111561023957600080fd5b82018360208201111561024b57600080fd5b8035906020019184600183028401116401000000008311171561026d57600080fd5b5090925090506107cb565b005b610282610e6a565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102bc5781810151838201526020016102a4565b50505050905090810190601f1680156102e95780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102ff611282565b60405180836dffffffffffffffffffffffffffff168152602001826dffffffffffffffffffffffffffff1681526020019250505060405180910390f35b6103756004803603604081101561035257600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356112af565b604080519115158252519081900360200190f35b6103916112cd565b604080516fffffffffffffffffffffffffffffffff9586168152938516602085015291841683830152909216606082015290519081900360800190f35b6103d661130c565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b610407611328565b60408051918252519081900360200190f35b6103756004803603606081101561042f57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020810135909116906040013561132e565b6104076113d0565b61046c6113f4565b6040805160ff9092168252519081900360200190f35b6103756004803603604081101561049857600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356113fd565b6104c3611458565b6040805163ffffffff9092168252519081900360200190f35b610407600480360360208110156104f257600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611484565b6102786004803603606081101561052557600080fd5b50803573ffffffffffffffffffffffffffffffffffffffff908116916020810135909116906040013563ffffffff166118f4565b6104076004803603602081101561056f57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611a22565b610407611a4e565b610407600480360360208110156105aa57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611a54565b6105fa600480360360208110156105dd57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611a66565b6040805192835260208301919091528051918290030190f35b610282612044565b6103756004803603604081101561063157600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013561238c565b6103756004803603604081101561066a57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135612401565b610407612415565b610278600480360360208110156106ab57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661241b565b6103d661263d565b6103d6612659565b610278600480360360e08110156106ee57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135612675565b61073e612941565b604080516dffffffffffffffffffffffffffff968716815294861660208601529285168484015293166060830152608082019290925290519081900360a00190f35b6104076004803603604081101561079657600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160200135166129dd565b610407612a15565b610278612a1b565b6002600854141561083d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002600855841515806108505750600084115b6108bb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f444d4d3a20494e53554646494349454e545f4f55545055545f414d4f554e5400604482015290519081900360640190fd5b60006108c5614891565b6108cd612cd8565b80519193509150871080156108e55750806020015186105b61095057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f444d4d3a20494e53554646494349454e545f4c49515549444954590000000000604482015290519081900360640190fd5b610958614891565b600c54600d5473ffffffffffffffffffffffffffffffffffffffff9182169190811690881682148015906109b857508073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614155b610a2357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f444d4d3a20494e56414c49445f544f0000000000000000000000000000000000604482015290519081900360640190fd5b8915610a4a57610a4a73ffffffffffffffffffffffffffffffffffffffff8316898c612d7c565b8815610a7157610a7173ffffffffffffffffffffffffffffffffffffffff8216898b612d7c565b8515610b3d578773ffffffffffffffffffffffffffffffffffffffff166381279c7e338c8c8b8b6040518663ffffffff1660e01b8152600401808673ffffffffffffffffffffffffffffffffffffffff168152602001858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f8201169050808301925050509650505050505050600060405180830381600087803b158015610b2457600080fd5b505af1158015610b38573d6000803e3d6000fd5b505050505b604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905173ffffffffffffffffffffffffffffffffffffffff8416916370a08231916024808301926020929190829003018186803b158015610ba957600080fd5b505afa158015610bbd573d6000803e3d6000fd5b505050506040513d6020811015610bd357600080fd5b50518352604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905173ffffffffffffffffffffffffffffffffffffffff8316916370a08231916024808301926020929190829003018186803b158015610c4357600080fd5b505afa158015610c57573d6000803e3d6000fd5b505050506040513d6020811015610c6d57600080fd5b505160208401528415610cc157835183516040860151610c989291610c929190612e0e565b90612e82565b6040840152602080850151908401516060860151610cbb9291610c929190612e0e565b60608401525b5050815181516000918a900310610cd9576000610ce4565b82518251908a900390035b9050600088846020015103836020015111610d00576000610d0e565b888460200151038360200151035b90506000821180610d1f5750600081115b610d8a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f444d4d3a20494e53554646494349454e545f494e5055545f414d4f554e540000604482015290519081900360640190fd5b6000610de4838388610d9d578751610da3565b87604001515b89610db2578860200151610db8565b88606001515b8a610dc4578851610dca565b88604001515b8b610dd9578960200151610ddf565b89606001515b612ef9565b9050610df0868561305e565b60408051848152602081018490528082018d9052606081018c905260808101839052905173ffffffffffffffffffffffffffffffffffffffff8b169133917f606ecd02b3e3b4778f8e97b2e03351de14224efaa5fa64e62200afc9395c24999181900360a00190a350506001600855505050505050505050565b600c54600d54604080517f95d89b41000000000000000000000000000000000000000000000000000000008152905160609373ffffffffffffffffffffffffffffffffffffffff90811693169183916395d89b4191600480820192600092909190829003018186803b158015610edf57600080fd5b505afa158015610ef3573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526020811015610f3a57600080fd5b8101908080516040519392919084640100000000821115610f5a57600080fd5b908301906020820185811115610f6f57600080fd5b8251640100000000811182820188101715610f8957600080fd5b82525081516020918201929091019080838360005b83811015610fb6578181015183820152602001610f9e565b50505050905090810190601f168015610fe35780820380516001836020036101000a031916815260200191505b506040525050508173ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b15801561103057600080fd5b505afa158015611044573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052602081101561108b57600080fd5b81019080805160405193929190846401000000008211156110ab57600080fd5b9083019060208201858111156110c057600080fd5b82516401000000008111828201881017156110da57600080fd5b82525081516020918201929091019080838360005b838110156111075781810151838201526020016110ef565b50505050905090810190601f1680156111345780820380516001836020036101000a031916815260200191505b5060405250505060405160200180807f4b79626572444d4d204c50200000000000000000000000000000000000000000815250600c0183805190602001908083835b602083106111b357805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611176565b6001836020036101000a038019825116818451168082178552505050505050905001807f2d0000000000000000000000000000000000000000000000000000000000000081525060010182805190602001908083835b6020831061124657805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611209565b6001836020036101000a038019825116818451168082178552505050505050905001925050506040516020818303038152906040529250505090565b600e546dffffffffffffffffffffffffffff808216926e0100000000000000000000000000009092041690565b60006112c36112bc6131f9565b84846131fd565b5060015b92915050565b600954600a546fffffffffffffffffffffffffffffffff8083169370010000000000000000000000000000000093849004821693838316930490911690565b600c5473ffffffffffffffffffffffffffffffffffffffff1681565b60025490565b600061133b848484613344565b6113c5846113476131f9565b6113c0856040518060600160405280602881526020016149b06028913973ffffffffffffffffffffffffffffffffffffffff8a166000908152600160205260408120906113926131f9565b73ffffffffffffffffffffffffffffffffffffffff1681526020810191909152604001600020549190613514565b6131fd565b5060015b9392505050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60055460ff1690565b60006112c361140a6131f9565b846113c0856001600061141b6131f9565b73ffffffffffffffffffffffffffffffffffffffff908116825260208083019390935260409182016000908120918c168152925290205490612e0e565b600e547c0100000000000000000000000000000000000000000000000000000000900463ffffffff1681565b6000600260085414156114f857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026008556000611507614891565b61150f612cd8565b9150915061151b614891565b600c54604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905173ffffffffffffffffffffffffffffffffffffffff909216916370a0823191602480820192602092909190829003018186803b15801561158c57600080fd5b505afa1580156115a0573d6000803e3d6000fd5b505050506040513d60208110156115b657600080fd5b50518152600d54604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905173ffffffffffffffffffffffffffffffffffffffff909216916370a0823191602480820192602092909190829003018186803b15801561162b57600080fd5b505afa15801561163f573d6000803e3d6000fd5b505050506040513d602081101561165557600080fd5b505160208201528151815160009161166d9190612e82565b9050600061168c84602001518460200151612e8290919063ffffffff16565b9050600061169a86866135c5565b905060006116a6611328565b90508061177457861561172957600e54855163ffffffff7c0100000000000000000000000000000000000000000000000000000000909204821691612710916116f191849061373416565b816116f857fe5b04604087015260208601516127109061171a9063ffffffff8085169061373416565b8161172157fe5b046060870152505b6117416103e8610c9261173c8787613734565b6137a7565b975061176f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6103e86137f8565b611827565b85516117b1906117848684613734565b8161178b57fe5b0487602001516117a4848761373490919063ffffffff16565b816117ab57fe5b04613929565b975086156118275760006117c58983612e0e565b90506117f4826117e2838a6040015161373490919063ffffffff16565b816117e957fe5b04876000015161393f565b6040870152606087015161182090839061180e9084613734565b8161181557fe5b04876020015161393f565b6060870152505b60008811611880576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806149d86022913960400191505060405180910390fd5b61188a89896137f8565b611894878661305e565b81156118a8576118a4878661394f565b6010555b6040805185815260208101859052815133927f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f928290030190a250506001600855509395945050505050565b600b5473ffffffffffffffffffffffffffffffffffffffff16331461197a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f444d4d3a20464f5242494444454e000000000000000000000000000000000000604482015290519081900360640190fd5b600c805473ffffffffffffffffffffffffffffffffffffffff9485167fffffffffffffffffffffffff000000000000000000000000000000000000000091821617909155600d805493909416921691909117909155600e805463ffffffff9092167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602081905260409020545b919050565b60105481565b60076020526000908152604090205481565b60008060026008541415611adb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026008556000611aea614891565b611af2612cd8565b600c54600d54604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905194965092945073ffffffffffffffffffffffffffffffffffffffff9182169391169160009184916370a08231916024808301926020929190829003018186803b158015611b7357600080fd5b505afa158015611b87573d6000803e3d6000fd5b505050506040513d6020811015611b9d57600080fd5b5051604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905191925060009173ffffffffffffffffffffffffffffffffffffffff8516916370a08231916024808301926020929190829003018186803b158015611c1157600080fd5b505afa158015611c25573d6000803e3d6000fd5b505050506040513d6020811015611c3b57600080fd5b505185519091508210801590611c55575084602001518110155b611cc057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f444d4d3a20554e53594e435f5245534552564553000000000000000000000000604482015290519081900360640190fd5b6000611ccb30611a22565b90506000611cd988886135c5565b90506000611ce5611328565b905080611cf28487613734565b81611cf957fe5b049a5080611d078486613734565b81611d0e57fe5b04995060008b118015611d21575060008a115b611d76576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602281526020018061496d6022913960400191505060405180910390fd5b611d803084613975565b611da173ffffffffffffffffffffffffffffffffffffffff88168d8d612d7c565b611dc273ffffffffffffffffffffffffffffffffffffffff87168d8c612d7c565b611dca614891565b604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905173ffffffffffffffffffffffffffffffffffffffff8a16916370a08231916024808301926020929190829003018186803b158015611e3657600080fd5b505afa158015611e4a573d6000803e3d6000fd5b505050506040513d6020811015611e6057600080fd5b50518152604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905173ffffffffffffffffffffffffffffffffffffffff8916916370a08231916024808301926020929190829003018186803b158015611ed057600080fd5b505afa158015611ee4573d6000803e3d6000fd5b505050506040513d6020811015611efa57600080fd5b505160208201528915611fa25788518151600091611f4091611f1c9086613734565b81611f2357fe5b048b602001516117a486866020015161373490919063ffffffff16565b9050611f6f83611f5d838d6040015161373490919063ffffffff16565b81611f6457fe5b04836000015161393f565b604083015260608a0151611f9b908490611f899084613734565b81611f9057fe5b04836020015161393f565b6060830152505b611fac8a8261305e565b8215611fc057611fbc8a8261394f565b6010555b8c73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d819364968e8e604051808381526020018281526020019250505060405180910390a3505050505050505050506001600881905550915091565b600c54600d54604080517f95d89b41000000000000000000000000000000000000000000000000000000008152905160609373ffffffffffffffffffffffffffffffffffffffff90811693169183916395d89b4191600480820192600092909190829003018186803b1580156120b957600080fd5b505afa1580156120cd573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052602081101561211457600080fd5b810190808051604051939291908464010000000082111561213457600080fd5b90830190602082018581111561214957600080fd5b825164010000000081118282018810171561216357600080fd5b82525081516020918201929091019080838360005b83811015612190578181015183820152602001612178565b50505050905090810190601f1680156121bd5780820380516001836020036101000a031916815260200191505b506040525050508173ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b15801561220a57600080fd5b505afa15801561221e573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052602081101561226557600080fd5b810190808051604051939291908464010000000082111561228557600080fd5b90830190602082018581111561229a57600080fd5b82516401000000008111828201881017156122b457600080fd5b82525081516020918201929091019080838360005b838110156122e15781810151838201526020016122c9565b50505050905090810190601f16801561230e5780820380516001836020036101000a031916815260200191505b5060405250505060405160200180807f444d4d2d4c5020000000000000000000000000000000000000000000000000008152506007018380519060200190808383602083106111b357805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611176565b60006112c36123996131f9565b846113c085604051806060016040528060258152602001614a8e60259139600160006123c36131f9565b73ffffffffffffffffffffffffffffffffffffffff908116825260208083019390935260409182016000908120918d16815292529020549190613514565b60006112c361240e6131f9565b8484613344565b6103e881565b6002600854141561248d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002600855600e54600c54604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051612574938593612554936dffffffffffffffffffffffffffff9092169273ffffffffffffffffffffffffffffffffffffffff909116916370a08231916024808301926020929190829003018186803b15801561252257600080fd5b505afa158015612536573d6000803e3d6000fd5b505050506040513d602081101561254c57600080fd5b505190612e82565b600c5473ffffffffffffffffffffffffffffffffffffffff169190612d7c565b600e54600d54604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051612635938593612615936e0100000000000000000000000000009092046dffffffffffffffffffffffffffff169273ffffffffffffffffffffffffffffffffffffffff909116916370a08231916024808301926020929190829003018186803b15801561252257600080fd5b600d5473ffffffffffffffffffffffffffffffffffffffff169190612d7c565b506001600855565b600b5473ffffffffffffffffffffffffffffffffffffffff1681565b600d5473ffffffffffffffffffffffffffffffffffffffff1681565b428410156126e457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f45524332305065726d69743a2045585049524544000000000000000000000000604482015290519081900360640190fd5b60065473ffffffffffffffffffffffffffffffffffffffff80891660008181526007602090815260408083208054600180820190925582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98186015280840196909652958d166060860152608085018c905260a085019590955260c08085018b90528151808603909101815260e0850182528051908301207f19010000000000000000000000000000000000000000000000000000000000006101008601526101028501969096526101228085019690965280518085039096018652610142840180825286519683019690962095839052610162840180825286905260ff89166101828501526101a284018890526101c28401879052519193926101e2808201937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081019281900390910190855afa158015612845573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116158015906128c057508873ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b61292b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f45524332305065726d69743a20494e56414c49445f5349474e41545552450000604482015290519081900360640190fd5b6129368989896131fd565b505050505050505050565b600e54600f546dffffffffffffffffffffffffffff808316926e0100000000000000000000000000008082048316938381169391900416906000907c0100000000000000000000000000000000000000000000000000000000900463ffffffff166127108114156129b3578593508492505b60006129be43613abf565b90506129d26129cc82613c63565b83613e44565b925050509091929394565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b60065481565b60026008541415612a8d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026008556000612a9c614891565b612aa4612cd8565b915091506000612ab483836135c5565b9050612abe614891565b600c54604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905173ffffffffffffffffffffffffffffffffffffffff909216916370a0823191602480820192602092909190829003018186803b158015612b2f57600080fd5b505afa158015612b43573d6000803e3d6000fd5b505050506040513d6020811015612b5957600080fd5b50518152600d54604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905173ffffffffffffffffffffffffffffffffffffffff909216916370a0823191602480820192602092909190829003018186803b158015612bce57600080fd5b505afa158015612be2573d6000803e3d6000fd5b505050506040513d6020811015612bf857600080fd5b505160208201528315612caf576000612c0f611328565b84518351919250600091612c4c9190612c289085613734565b81612c2f57fe5b0486602001516117a485876020015161373490919063ffffffff16565b9050612c7b82612c6983886040015161373490919063ffffffff16565b81612c7057fe5b04846000015161393f565b60408401526060850151612ca7908390612c959084613734565b81612c9c57fe5b04846020015161393f565b606084015250505b612cb9848261305e565b8115612ccd57612cc9848261394f565b6010555b505060016008555050565b6000612ce2614891565b600e546dffffffffffffffffffffffffffff80821683526e010000000000000000000000000000820416602083015263ffffffff7c0100000000000000000000000000000000000000000000000000000000909104166127101480159250612d7857600f546dffffffffffffffffffffffffffff80821660408401526e0100000000000000000000000000009091041660608201525b9091565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052612e09908490613ea0565b505050565b6000828201838110156113c957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600082821115612ef357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b600080612f1a88612f1487612f0e8a8c613734565b90613f78565b90612e0e565b90506000612f284383613ff9565b9050612f64612f3682613c63565b600e547c0100000000000000000000000000000000000000000000000000000000900463ffffffff16613e44565b92506000612f7a86670de0b6b3a7640000613734565b9050612f90612f898b86613734565b8290612e82565b9050670de0b6b3a7640000810490506000612fb386670de0b6b3a7640000613734565b9050612fc2612f898b87613734565b670de0b6b3a764000090049050612fd98989613734565b612fe38383613734565b101561305057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600660248201527f444d4d3a204b0000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b505050509695505050505050565b80516130699061434c565b600e80547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000166dffffffffffffffffffffffffffff9290921691909117905560208101516130b69061434c565b600e806101000a8154816dffffffffffffffffffffffffffff02191690836dffffffffffffffffffffffffffff16021790555081156131a157805160408201511080159061310c57508060200151816060015110155b61311257fe5b61311f816040015161434c565b600f80547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000166dffffffffffffffffffffffffffff92909216919091179055606081015161316c9061434c565b600f600e6101000a8154816dffffffffffffffffffffffffffff02191690836dffffffffffffffffffffffffffff1602179055505b6040808201516060808401518451602080870151865195865290850192909252838501529082015290517f2f9d55abfefdfd4c3a83e00a1b419b3c2fe4b83100c559f0e2213e57f6e0bba99181900360800190a15050565b3390565b73ffffffffffffffffffffffffffffffffffffffff8316613269576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180614a406024913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166132d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806148ff6022913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b73ffffffffffffffffffffffffffffffffffffffff83166133b0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180614a1b6025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821661341c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806148ba6023913960400191505060405180910390fd5b613427838383612e09565b613471816040518060600160405280602681526020016149216026913973ffffffffffffffffffffffffffffffffffffffff86166000908152602081905260409020549190613514565b73ffffffffffffffffffffffffffffffffffffffff80851660009081526020819052604080822093909355908416815220546134ad9082612e0e565b73ffffffffffffffffffffffffffffffffffffffff8084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600081848411156135bd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561358257818101518382015260200161356a565b50505050905090810190601f1680156135af5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6000806000600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ad5cb2e16040518163ffffffff1660e01b8152600401604080518083038186803b15801561363157600080fd5b505afa158015613645573d6000803e3d6000fd5b505050506040513d604081101561365b57600080fd5b50805160209091015160105473ffffffffffffffffffffffffffffffffffffffff831615801596509294509092509061371f57801561371a5760006136a361173c888861394f565b905060006136b0836137a7565b9050808211156137175760006136df61ffff86166136d96136d18686612e82565b6136d9611328565b90613734565b905060006136f36113886136d98686612e0e565b9050600081838161370057fe5b04905080156137135761371388826137f8565b5050505b50505b61372b565b801561372b5760006010555b50505092915050565b600082613743575060006112c7565b8282028284828161375057fe5b04146113c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061498f6021913960400191505060405180910390fd5b600060038211156137ea575080600160028204015b818110156137e4578091506002818285816137d357fe5b0401816137dc57fe5b0490506137bc565b50611a49565b8115611a4957506001919050565b73ffffffffffffffffffffffffffffffffffffffff821661387a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b61388660008383612e09565b6002546138939082612e0e565b60025573ffffffffffffffffffffffffffffffffffffffff82166000908152602081905260409020546138c69082612e0e565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b600081831061393857816113c9565b5090919050565b60008183101561393857816113c9565b6000826139635760208201518251026113c9565b50606081015160409091015102919050565b73ffffffffffffffffffffffffffffffffffffffff82166139e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806149fa6021913960400191505060405180910390fd5b6139ed82600083612e09565b613a37816040518060600160405280602281526020016148dd6022913973ffffffffffffffffffffffffffffffffffffffff85166000908152602081905260409020549190613514565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040902055600254613a6a9082612e82565b60025560408051828152905160009173ffffffffffffffffffffffffffffffffffffffff8516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b600a5460009070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16820380613b3057600954613b28906fffffffffffffffffffffffffffffffff808216917001000000000000000000000000000000009004166143cf565b915050611a49565b600954600090613b77906fffffffffffffffffffffffffffffffff16611519671bc16d674ec800005b600a54919004906fffffffffffffffffffffffffffffffff166143f1565b600954909150600090613bbb9070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612a31671bc16d674ec80000613b59565b9050613c0b613c047fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8501611519671bc16d674ec800005b04670de0b6b3a76400000390614452565b8390614523565b9150613c4e613c477fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8501612a31671bc16d674ec80000613bf3565b8290614523565b9050613c5a82826143cf565b95945050505050565b6000671480cc142da92a848210613c825750661550f7dca70000611a49565b670de0b6b3a76400008210613d8a576710a741a462780000821115613d2b577fffffffffffffffffffffffffffffffffffffffffffffffffef58be5b9d88000082016000613cd1826003614452565b9050612710613d1a613cf1846009680d8d726b7177a800005b0490614523565b612f14613d0a85601b69043c33c1937564800000613cea565b6801fa48421ec7b1ed0990612e0e565b81613d2157fe5b0492505050611a49565b6710a741a4627800008290036000613d44826003614452565b9050612710613d1a613d61846009680d8d726b7177a80000613cea565b610c92613d7a85601b69043c33c1937564800000613cea565b6801fa48421ec7b1ed0990612e82565b6000670b9a1192183a00008311613dac57670b9a1192183a0000839003613dd0565b7ffffffffffffffffffffffffffffffffffffffffffffffffff465ee6de7c6000083015b9050613ddd816002614452565b90506000613e06613df48365b5e620f48000612e0e565b612f0e674563918244f4000085613734565b9050670b9a1192183a0000841115613e2e57612710613d1a6801161163ae0de59a9283612e0e565b612710613d1a6801161163ae0de59a9283612e82565b6000614e208263ffffffff1611613e5c5750816112c7565b61c3508263ffffffff1611613e7a57601e601484025b0490506112c7565b62030d408263ffffffff1611613e9557601e600a8402613e72565b601e60048402613e72565b6060613f02826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661453f9092919063ffffffff16565b805190915015612e0957808060200190516020811015613f2157600080fd5b5051612e09576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180614a64602a913960400191505060405180910390fd5b6000808211613fe857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381613ff157fe5b049392505050565b600a5460009070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff168303806140f457600a5461408a9061404f906fffffffffffffffffffffffffffffffff1685612e0e565b6040518060400160405280601a81526020017f766f6c756d6520657863656564732076616c69642072616e6765000000000000815250614556565b600a80547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff9283161790556009546140ec91818116917001000000000000000000000000000000009004166143cf565b9150506112c7565b600a546009546fffffffffffffffffffffffffffffffff918216916000916141289116611519671bc16d674ec80000613b59565b60095490915060009061416c9070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612a31671bc16d674ec80000613b59565b90506141a8613c047fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8601611519671bc16d674ec80000613bf3565b91506141e4613c477fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8601612a31671bc16d674ec80000613bf3565b90506141ef826145da565b600980547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff92909216919091179055614239816145da565b600980546fffffffffffffffffffffffffffffffff928316700100000000000000000000000000000000029216919091179055614275866145da565b600a80547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff929092169190911790556142bf876145da565b600a80546fffffffffffffffffffffffffffffffff9283167001000000000000000000000000000000000290831617905560408051848152602081018490529185168282015260608201869052517f96e2c334d3c0fa98c8b728ee84471864ffe5b28e05f46e52f8a469d0ab3a8b8b9181900360800190a161434182826143cf565b979650505050505050565b60006dffffffffffffffffffffffffffff8211156143cb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f444d4d3a204f564552464c4f5700000000000000000000000000000000000000604482015290519081900360640190fd5b5090565b6000816143de575060006112c7565b81670de0b6b3a7640000840281613ff157fe5b6000670de0b6b3a7640000831061440457fe5b670de0b6b3a7640000826fffffffffffffffffffffffffffffffff168402856fffffffffffffffffffffffffffffffff1685670de0b6b3a76400000302018161444957fe5b04949350505050565b6000670de0b6b3a76400008311156144cb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d6174684578743a2078203e20505245434953494f4e00000000000000000000604482015290519081900360640190fd5b600282066144e157670de0b6b3a76400006144e3565b825b90506002820491505b81156112c757670de0b6b3a7640000838002049250600282061561451857670de0b6b3a7640000908302045b6002820491506144ec565b6000670de0b6b3a76400006145388484613734565b81613ff157fe5b606061454e848460008561465b565b949350505050565b6000816fffffffffffffffffffffffffffffffff8411156145d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181815283516024840152835190928392604490910191908501908083836000831561358257818101518382015260200161356a565b509192915050565b60006fffffffffffffffffffffffffffffffff8211156143cb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6f766572666c6f772075696e7431323800000000000000000000000000000000604482015290519081900360640190fd5b6060824710156146b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806149476026913960400191505060405180910390fd5b6146bf8561480b565b61472a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b6020831061479457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101614757565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146147f6576040519150601f19603f3d011682016040523d82523d6000602084013e6147fb565b606091505b5091509150614341828286614811565b3b151590565b606083156148205750816113c9565b8251156148305782518084602001fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181815284516024840152845185939192839260440191908501908083836000831561358257818101518382015260200161356a565b604051806080016040528060008152602001600081526020016000815260200160008152509056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e6365416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c444d4d3a20494e53554646494349454e545f4c49515549444954595f4255524e4544536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7745524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e6365444d4d3a20494e53554646494349454e545f4c49515549444954595f4d494e54454445524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f20616464726573735361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122049f6f8528b3e4b37e72b9bde0aa804ce74fda17a3dc51ea424bf85cf5943707e64736f6c634300060c0033
Deployed ByteCode Sourcemap
52253:15783:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;58595:2397;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;58595:2397:0;;-1:-1:-1;58595:2397:0;-1:-1:-1;58595:2397:0;:::i;:::-;;63384:302;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63213:163;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34895:169;;;;;;;;;;;;;;;;-1:-1:-1;34895:169:0;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;48121:401;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52877:29;;;:::i;:::-;;;;;;;;;;;;;;;;;;;33848:108;;;:::i;:::-;;;;;;;;;;;;;;;;35546:321;;;;;;;;;;;;;;;;-1:-1:-1;35546:321:0;;;;;;;;;;;;;;;;;;:::i;42364:117::-;;;:::i;33692:91::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;36276:218;;;;;;;;;;;;;;;;-1:-1:-1;36276:218:0;;;;;;;;;:::i;53086:29::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;54495:1812;;;;;;;;;;;;;;;;-1:-1:-1;54495:1812:0;;;;:::i;54084:268::-;;;;;;;;;;;;;;;;-1:-1:-1;54084:268:0;;;;;;;;;;;;;;;;;;;;;:::i;34019:127::-;;;;;;;;;;;;;;;;-1:-1:-1;34019:127:0;;;;:::i;53347:29::-;;;:::i;42490:41::-;;;;;;;;;;;;;;;;-1:-1:-1;42490:41:0;;;;:::i;56515:1948::-;;;;;;;;;;;;;;;;-1:-1:-1;56515:1948:0;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;63694:299;;;:::i;36997:269::-;;;;;;;;;;;;;;;;-1:-1:-1;36997:269:0;;;;;;;;;:::i;34359:175::-;;;;;;;;;;;;;;;;-1:-1:-1;34359:175:0;;;;;;;;;:::i;52691:49::-;;;:::i;61047:218::-;;;;;;;;;;;;;;;;-1:-1:-1;61047:218:0;;;;:::i;52835:35::-;;;:::i;52913:29::-;;;:::i;43171:839::-;;;;;;;;;;;;;;;;-1:-1:-1;43171:839:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;62361:772::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34597:151;;;;;;;;;;;;;;;;-1:-1:-1;34597:151:0;;;;;;;;;;;:::i;42222:30::-;;;:::i;61320:973::-;;;:::i;58595:2397::-;10122:1;10728:7;;:19;;10720:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10122:1;10861:7;:18;58783:14;;;;:32:::1;;;58814:1;58801:10;:14;58783:32;58775:76;;;::::0;;::::1;::::0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;58863:14;58879:23;;:::i;:::-;58906:17;:15;:17::i;:::-;58984:13:::0;;58862:61;;-1:-1:-1;58862:61:0;-1:-1:-1;58971:26:0;::::1;:56:::0;::::1;;;;59014:4;:13;;;59001:10;:26;58971:56;58949:133;;;::::0;;::::1;::::0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;59095:26;;:::i;:::-;59232:6;::::0;59270::::1;::::0;59232::::1;::::0;;::::1;::::0;59270;;::::1;::::0;59299:22;::::1;::::0;::::1;::::0;::::1;::::0;:48:::1;;;59339:7;59325:22;;:2;:22;;;;59299:48;59291:76;;;::::0;;::::1;::::0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;59386:14:::0;;59382:56:::1;;59402:36;:20;::::0;::::1;59423:2:::0;59427:10;59402:20:::1;:36::i;:::-;59491:14:::0;;59487:56:::1;;59507:36;:20;::::0;::::1;59528:2:::0;59532:10;59507:20:::1;:36::i;:::-;59596:23:::0;;59592:122:::1;;59649:2;59638:26;;;59665:10;59677;59689;59701:12;;59638:76;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;59592:122;59748:32;::::0;;;;;59774:4:::1;59748:32;::::0;::::1;::::0;;;:17:::1;::::0;::::1;::::0;::::1;::::0;:32;;;;;::::1;::::0;;;;;;;;:17;:32;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;59748:32:0;59729:51;;59814:32:::1;::::0;;;;;59840:4:::1;59814:32;::::0;::::1;::::0;;;:17:::1;::::0;::::1;::::0;::::1;::::0;:32;;;;;59748::::1;::::0;59814;;;;;;;:17;:32;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;59814:32:0;::::1;59795:16:::0;::::1;:51:::0;59861:219;::::1;;;59956:13:::0;;59934:16;;59915:14:::1;::::0;::::1;::::0;:55:::1;::::0;59956:13;59915:36:::1;::::0;:14;:18:::1;:36::i;:::-;:40:::0;::::1;:55::i;:::-;59895:17;::::0;::::1;:75:::0;60050:13:::1;::::0;;::::1;::::0;60028:16;;::::1;::::0;60009:14:::1;::::0;::::1;::::0;:55:::1;::::0;60050:13;60009:36:::1;::::0;:14;:18:::1;:36::i;:55::-;59989:17;::::0;::::1;:75:::0;59861:219:::1;-1:-1:-1::0;;60140:13:0;;60121:16;;60101:17:::1;::::0;60140:26;;::::1;-1:-1:-1::0;60121:125:0::1;;60245:1;60121:125;;;60202:13:::0;;60182:16;;60202:26;;;::::1;60182:47:::0;::::1;60121:125;60101:145;;60257:17;60312:10;60296:4;:13;;;:26;60277:7;:16;;;:45;:125;;60401:1;60277:125;;;60374:10;60358:4;:13;;;:26;60338:7;:16;;;:47;60277:125;60257:145;;60433:1;60421:9;:13;:30;;;;60450:1;60438:9;:13;60421:30;60413:73;;;::::0;;::::1;::::0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;60497:22;60522:324;60562:9;60586;60610;:42;;60639:13:::0;;60610:42:::1;;;60622:4;:14;;;60610:42;60667:9;:42;;60696:4;:13;;;60667:42;;;60679:4;:14;;;60667:42;60724:9;:48;;60756:16:::0;;60724:48:::1;;;60736:7;:17;;;60724:48;60787:9;:48;;60819:7;:16;;;60787:48;;;60799:7;:17;;;60787:48;60522:25;:324::i;:::-;60497:349;;60859:27;60867:9;60878:7;60859;:27::i;:::-;60902:82;::::0;;;;;::::1;::::0;::::1;::::0;;;;;;;;;;;;;;;;;;;;;;;::::1;::::0;::::1;::::0;60907:10:::1;::::0;60902:82:::1;::::0;;;;;;;::::1;-1:-1:-1::0;;10078:1:0;11040:7;:22;-1:-1:-1;;;;;;;;;58595:2397:0:o;63384:302::-;63504:6;;63571;;63637:16;;;;;;;;63430:13;;63504:6;;;;;63571;;63504;;63637:14;;:16;;;;;63456:22;;63637:16;;;;;;;;63504:6;63637:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;63637:16:0;;;;;;;;;;-1:-1:-1;63637:16:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63660:7;:14;;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;63660:16:0;;;;;;;;;;-1:-1:-1;63660:16:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63604:73;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63590:88;;;;63384:302;:::o;63213:163::-;63329:8;;;;;;;63360;;;;;;63213:163::o;34895:169::-;34978:4;34995:39;35004:12;:10;:12::i;:::-;35018:7;35027:6;34995:8;:39::i;:::-;-1:-1:-1;35052:4:0;34895:169;;;;;:::o;48121:401::-;48383:8;;48453:18;;48383:8;;;;;48413:7;;;;;;;;48453:18;;;;48500:14;;;;;48121:401::o;52877:29::-;;;;;;:::o;33848:108::-;33936:12;;33848:108;:::o;35546:321::-;35652:4;35669:36;35679:6;35687:9;35698:6;35669:9;:36::i;:::-;35716:121;35725:6;35733:12;:10;:12::i;:::-;35747:89;35785:6;35747:89;;;;;;;;;;;;;;;;;:19;;;;;;;:11;:19;;;;;;35767:12;:10;:12::i;:::-;35747:33;;;;;;;;;;;;;-1:-1:-1;35747:33:0;;;:89;:37;:89::i;:::-;35716:8;:121::i;:::-;-1:-1:-1;35855:4:0;35546:321;;;;;;:::o;42364:117::-;42415:66;42364:117;:::o;33692:91::-;33766:9;;;;33692:91;:::o;36276:218::-;36364:4;36381:83;36390:12;:10;:12::i;:::-;36404:7;36413:50;36452:10;36413:11;:25;36425:12;:10;:12::i;:::-;36413:25;;;;;;;;;;;;;;;;;;-1:-1:-1;36413:25:0;;;:34;;;;;;;;;;;:38;:50::i;53086:29::-;;;;;;;;;:::o;54495:1812::-;54561:17;10122:1;10728:7;;:19;;10720:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10122:1;10861:7;:18;54592:14:::1;54608:23;;:::i;:::-;54635:17;:15;:17::i;:::-;54591:61;;;;54663:24;;:::i;:::-;54715:6;::::0;:31:::1;::::0;;;;;54740:4:::1;54715:31;::::0;::::1;::::0;;;:6:::1;::::0;;::::1;::::0;:16:::1;::::0;:31;;;;;::::1;::::0;;;;;;;;;:6;:31;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;54715:31:0;54698:48;;54774:6:::1;::::0;:31:::1;::::0;;;;;54799:4:::1;54774:31;::::0;::::1;::::0;;;:6:::1;::::0;;::::1;::::0;:16:::1;::::0;:31;;;;;54715::::1;::::0;54774;;;;;;;;:6;:31;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;54774:31:0;::::1;54757:14:::0;::::1;:48:::0;54853:13;;54834:14;;54816:15:::1;::::0;54834:33:::1;::::0;:14;:18:::1;:33::i;:::-;54816:51;;54878:15;54896:33;54915:4;:13;;;54896:5;:14;;;:18;;:33;;;;:::i;:::-;54878:51;;54942:10;54955:25;54964:9;54975:4;54955:8;:25::i;:::-;54942:38;;54991:20;55014:13;:11;:13::i;:::-;54991:36:::0;-1:-1:-1;55120:17:0;55116:942:::1;;55158:9;55154:213;;;55205:6;::::0;55248:14;;55205:6:::1;::::0;;;::::1;::::0;::::1;::::0;52497:5:::1;::::0;55248:27:::1;::::0;55205:6;;55248:18:::1;:27;:::i;:::-;:33;;;;;;55230:15;::::0;::::1;:51:::0;55318:14:::1;::::0;::::1;::::0;52497:5:::1;::::0;55318:27:::1;::::0;::::1;::::0;;::::1;::::0;:18:::1;:27;:::i;:::-;:33;;;;;;55300:15;::::0;::::1;:51:::0;-1:-1:-1;55154:213:0::1;55393:57;52735:5;55393:34;55406:20;:7:::0;55418;55406:11:::1;:20::i;:::-;55393:12;:34::i;:57::-;55381:69;;55465:37;55479:2;52735:5;55465;:37::i;:::-;55116:942;;;55657:13:::0;;55602:143:::1;::::0;55629:25:::1;:7:::0;55641:12;55629:11:::1;:25::i;:::-;:41;;;;;;55717:4;:13;;;55689:25;55701:12;55689:7;:11;;:25;;;;:::i;:::-;:41;;;;;;55602:8;:143::i;:::-;55590:155;;55764:9;55760:287;;;55794:9;55806:27;:9:::0;55820:12;55806:13:::1;:27::i;:::-;55794:39;;55870:62;55903:12;55879:21;55898:1;55879:4;:14;;;:18;;:21;;;;:::i;:::-;:36;;;;;;55917:5;:14;;;55870:8;:62::i;:::-;55852:15;::::0;::::1;:80:::0;55978:14:::1;::::0;::::1;::::0;55969:62:::1;::::0;56002:12;;55978:21:::1;::::0;55997:1;55978:18:::1;:21::i;:::-;:36;;;;;;56016:5;:14;;;55969:8;:62::i;:::-;55951:15;::::0;::::1;:80:::0;-1:-1:-1;55760:287:0::1;56088:1;56076:9;:13;56068:60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56139:20;56145:2;56149:9;56139:5;:20::i;:::-;56172:25;56180:9;56191:5;56172:7;:25::i;:::-;56212:5;56208:41;;;56227:22;56232:9;56243:5;56227:4;:22::i;:::-;56219:5;:30:::0;56208:41:::1;56265:34;::::0;;;;;::::1;::::0;::::1;::::0;;;;;56270:10:::1;::::0;56265:34:::1;::::0;;;;;;::::1;-1:-1:-1::0;;10078:1:0;11040:7;:22;-1:-1:-1;54495:1812:0;;;-1:-1:-1;;;;;54495:1812:0:o;54084:268::-;54236:7;;;;54214:10;:30;54206:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;54274:6;:16;;;;;;;;;;;;;;54301:6;:16;;;;;;;;;;;;;;;54328:6;:16;;;;;;;;;;;;;;;;;;54084:268::o;34019:127::-;34120:18;;;34093:7;34120:18;;;;;;;;;;;34019:127;;;;:::o;53347:29::-;;;;:::o;42490:41::-;;;;;;;;;;;;;:::o;56515:1948::-;56617:15;56634;10122:1;10728:7;;:19;;10720:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10122:1;10861:7;:18;56668:14:::1;56684:23;;:::i;:::-;56711:17;:15;:17::i;:::-;56771:6;::::0;56820::::1;::::0;56873:32:::1;::::0;;;;;56899:4:::1;56873:32;::::0;::::1;::::0;;;56667:61;;-1:-1:-1;56667:61:0;;-1:-1:-1;56771:6:0::1;::::0;;::::1;::::0;56820;::::1;::::0;56754:14:::1;::::0;56771:6;;56873:17:::1;::::0;:32;;;;;::::1;::::0;;;;;;;;56771:6;56873:32;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;56873:32:0;56935::::1;::::0;;;;;56961:4:::1;56935:32;::::0;::::1;::::0;;;56873;;-1:-1:-1;56916:16:0::1;::::0;56935:17:::1;::::0;::::1;::::0;::::1;::::0;:32;;;;;56873::::1;::::0;56935;;;;;;;:17;:32;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;56935:32:0;56998:13;;56935:32;;-1:-1:-1;56986:25:0;::::1;::::0;::::1;::::0;:54:::1;;;57027:4;:13;;;57015:8;:25;;56986:54;56978:87;;;::::0;;::::1;::::0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;57076:17;57096:24;57114:4;57096:9;:24::i;:::-;57076:44;;57133:10;57146:25;57155:9;57166:4;57146:8;:25::i;:::-;57133:38;;57182:20;57205:13;:11;:13::i;:::-;57182:36:::0;-1:-1:-1;57182:36:0;57317:23:::1;:9:::0;57331:8;57317:13:::1;:23::i;:::-;:38;;;;;;::::0;-1:-1:-1;57450:12:0;57424:23:::1;:9:::0;57438:8;57424:13:::1;:23::i;:::-;:38;;;;;;57414:48;;57539:1;57529:7;:11;:26;;;;;57554:1;57544:7;:11;57529:26;57521:73;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;57605:31;57619:4;57626:9;57605:5;:31::i;:::-;57647:33;:20;::::0;::::1;57668:2:::0;57672:7;57647:20:::1;:33::i;:::-;57691;:20;::::0;::::1;57712:2:::0;57716:7;57691:20:::1;:33::i;:::-;57735:24;;:::i;:::-;57787:32;::::0;;;;;57813:4:::1;57787:32;::::0;::::1;::::0;;;:17:::1;::::0;::::1;::::0;::::1;::::0;:32;;;;;::::1;::::0;;;;;;;;:17;:32;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;57787:32:0;57770:49;;57847:32:::1;::::0;;;;;57873:4:::1;57847:32;::::0;::::1;::::0;;;:17:::1;::::0;::::1;::::0;::::1;::::0;:32;;;;;57787::::1;::::0;57847;;;;;;;:17;:32;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;57847:32:0;::::1;57830:14:::0;::::1;:49:::0;57890:401;::::1;;;57994:13:::0;;57959:14;;57920:9:::1;::::0;57932:157:::1;::::0;57959:32:::1;::::0;57978:12;57959:18:::1;:32::i;:::-;:48;;;;;;58061:4;:13;;;58026:32;58045:12;58026:5;:14;;;:18;;:32;;;;:::i;57932:157::-;57920:169;;58122:62;58155:12;58131:21;58150:1;58131:4;:14;;;:18;;:21;;;;:::i;:::-;:36;;;;;;58169:5;:14;;;58122:8;:62::i;:::-;58104:15;::::0;::::1;:80:::0;58226:14:::1;::::0;::::1;::::0;58217:62:::1;::::0;58250:12;;58226:21:::1;::::0;58245:1;58226:18:::1;:21::i;:::-;:36;;;;;;58264:5;:14;;;58217:8;:62::i;:::-;58199:15;::::0;::::1;:80:::0;-1:-1:-1;57890:401:0::1;58301:25;58309:9;58320:5;58301:7;:25::i;:::-;58341:5;58337:41;;;58356:22;58361:9;58372:5;58356:4;:22::i;:::-;58348:5;:30:::0;58337:41:::1;58452:2;58417:38;;58422:10;58417:38;;;58434:7;58443;58417:38;;;;;;;;;;;;;;;;;;;;;;;;10892:1;;;;;;;;;;10078::::0;11040:7;:22;;;;56515:1948;;;:::o;63694:299::-;63816:6;;63883;;63944:16;;;;;;;;63742:13;;63816:6;;;;;63883;;63816;;63944:14;;:16;;;;;63768:22;;63944:16;;;;;;;;63816:6;63944:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;63944:16:0;;;;;;;;;;-1:-1:-1;63944:16:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63967:7;:14;;;:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;63967:16:0;;;;;;;;;;-1:-1:-1;63967:16:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63916:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36997:269;37090:4;37107:129;37116:12;:10;:12::i;:::-;37130:7;37139:96;37178:15;37139:96;;;;;;;;;;;;;;;;;:11;:25;37151:12;:10;:12::i;:::-;37139:25;;;;;;;;;;;;;;;;;;-1:-1:-1;37139:25:0;;;:34;;;;;;;;;;;:96;:38;:96::i;34359:175::-;34445:4;34462:42;34472:12;:10;:12::i;:::-;34486:9;34497:6;34462:9;:42::i;52691:49::-;52735:5;52691:49;:::o;61047:218::-;10122:1;10728:7;;:19;;10720:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10122:1;10861:7;:18;61166:8:::1;::::0;61130:6:::1;::::0;:31:::1;::::0;;;;;61155:4:::1;61130:31;::::0;::::1;::::0;;;61106:70:::1;::::0;61126:2;;61130:45:::1;::::0;61166:8:::1;::::0;;::::1;::::0;61130:6:::1;::::0;;::::1;::::0;:16:::1;::::0;:31;;;;;::::1;::::0;;;;;;;;:6;:31;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;61130:31:0;;:35:::1;:45::i;:::-;61106:6;::::0;::::1;;::::0;:70;:19:::1;:70::i;:::-;61247:8;::::0;61211:6:::1;::::0;:31:::1;::::0;;;;;61236:4:::1;61211:31;::::0;::::1;::::0;;;61187:70:::1;::::0;61207:2;;61211:45:::1;::::0;61247:8;;;::::1;;;::::0;61211:6:::1;::::0;;::::1;::::0;:16:::1;::::0;:31;;;;;::::1;::::0;;;;;;;;:6;:31;::::1;;::::0;::::1;;;;::::0;::::1;:45;61187:6;::::0;::::1;;::::0;:70;:19:::1;:70::i;:::-;-1:-1:-1::0;10078:1:0;11040:7;:22;61047:218::o;52835:35::-;;;;;;:::o;52913:29::-;;;;;;:::o;43171:839::-;43402:15;43390:8;:27;;43382:60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;43558:15;;43675:13;;;;43453:14;43675:13;;;:6;:13;;;;;;;;:15;;;;;;;;;43624:77;;42415:66;43624:77;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;43592:128;;;;;;43494:241;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;43470:276;;;;;;;;;43784:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;43453:14;;43675:15;43784:26;;;;;-1:-1:-1;43784:26:0;;;;;;;;;;43675:15;43784:26;;;;;;;;;;;;;;;-1:-1:-1;;43784:26:0;;;;;;-1:-1:-1;;43843:30:0;;;;;;;:59;;;43897:5;43877:25;;:16;:25;;;43843:59;43821:139;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;43971:31;43980:5;43987:7;43996:5;43971:8;:31::i;:::-;43171:839;;;;;;;;;:::o;62361:772::-;62720:8;;62817:9;;62720:8;;;;;62751;;;;;;;62817:9;;;;62850;;;;;62484:17;;62787:6;;;;;52497:5;62874:14;;62870:106;;;62918:9;62905:22;;62955:9;62942:22;;62870:106;62986:26;63015:24;63026:12;63015:10;:24::i;:::-;62986:53;;63067:58;63079:36;63096:18;63079:16;:36::i;:::-;63117:7;63067:11;:58::i;:::-;63050:75;;62361:772;;;;;;;:::o;34597:151::-;34713:18;;;;34686:7;34713:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;34597:151::o;42222:30::-;;;;:::o;61320:973::-;10122:1;10728:7;;:19;;10720:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10122:1;10861:7;:18;61379:14:::1;61395:23;;:::i;:::-;61422:17;:15;:17::i;:::-;61378:61;;;;61450:10;61463:25;61472:9;61483:4;61463:8;:25::i;:::-;61450:38;;61499:26;;:::i;:::-;61562:6;::::0;61555:39:::1;::::0;;;;;61588:4:::1;61555:39;::::0;::::1;::::0;;;61562:6:::1;::::0;;::::1;::::0;61555:24:::1;::::0;:39;;;;;::::1;::::0;;;;;;;;;61562:6;61555:39;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;61555:39:0;61536:58;;61631:6:::1;::::0;61624:39:::1;::::0;;;;;61657:4:::1;61624:39;::::0;::::1;::::0;;;61631:6:::1;::::0;;::::1;::::0;61624:24:::1;::::0;:39;;;;;61555::::1;::::0;61624;;;;;;;;61631:6;61624:39;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;61624:39:0;::::1;61605:16:::0;::::1;:58:::0;61730:464;::::1;;;61760:20;61783:13;:11;:13::i;:::-;61887::::0;;61850:16;;61760:36;;-1:-1:-1;61811:9:0::1;::::0;61823:161:::1;::::0;61887:13;61850:34:::1;::::0;61760:36;61850:20:::1;:34::i;:::-;:50;;;;;;61956:4;:13;;;61919:34;61940:12;61919:7;:16;;;:20;;:34;;;;:::i;61823:161::-;61811:173;;62019:64;62052:12;62028:21;62047:1;62028:4;:14;;;:18;;:21;;;;:::i;:::-;:36;;;;;;62066:7;:16;;;62019:8;:64::i;:::-;61999:17;::::0;::::1;:84:::0;62127:14:::1;::::0;::::1;::::0;62118:64:::1;::::0;62151:12;;62127:21:::1;::::0;62146:1;62127:18:::1;:21::i;:::-;:36;;;;;;62165:7;:16;;;62118:8;:64::i;:::-;62098:17;::::0;::::1;:84:::0;-1:-1:-1;;61730:464:0::1;62204:27;62212:9;62223:7;62204;:27::i;:::-;62246:5;62242:43;;;62261:24;62266:9;62277:7;62261:4;:24::i;:::-;62253:5;:32:::0;62242:43:::1;-1:-1:-1::0;;10078:1:0;11040:7;:22;-1:-1:-1;;61320:973:0:o;66921:324::-;66971:14;66987:23;;:::i;:::-;67039:8;;;;;;67023:24;;67074:8;;;;67058:13;;;:24;67105:6;;;;;;52497:5;67105:13;;;;-1:-1:-1;67129:109:0;;67176:9;;;;;;67159:14;;;:26;67217:9;;;;;67200:14;;;:26;67129:109;66921:324;;:::o;22608:177::-;22718:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22741:23;22718:58;;;22691:86;;22711:5;;22691:19;:86::i;:::-;22608:177;;;:::o;2828:179::-;2886:7;2918:5;;;2942:6;;;;2934:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3290:158;3348:7;3381:1;3376;:6;;3368:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;3435:5:0;;;3290:158::o;64001:1267::-;64255:22;;64420:64;64474:9;64420:49;64454:14;64420:29;:14;64439:9;64420:18;:29::i;:::-;:33;;:49::i;:::-;:53;;:64::i;:::-;64403:81;;64495:26;64524:44;64547:12;64561:6;64524:22;:44::i;:::-;64495:73;;64596:57;64608:36;64625:18;64608:16;:36::i;:::-;64646:6;;;;;;;64596:11;:57::i;:::-;64579:74;-1:-1:-1;64718:24:0;64745:28;:13;47519:6;64745:17;:28::i;:::-;64718:55;-1:-1:-1;64803:51:0;64824:29;:9;64838:14;64824:13;:29::i;:::-;64803:16;;:20;:51::i;:::-;64784:70;-1:-1:-1;47519:6:0;64784:70;64884:28;;-1:-1:-1;64923:24:0;64950:28;:13;47519:6;64950:17;:28::i;:::-;64923:55;-1:-1:-1;65008:51:0;65029:29;:9;65043:14;65029:13;:29::i;65008:51::-;47519:6;65089:28;;;-1:-1:-1;65192:34:0;:14;65211;65192:18;:34::i;:::-;65150:38;:16;65171;65150:20;:38::i;:::-;:76;;65128:132;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;64001:1267;;;;;;;;;;;;:::o;65306:503::-;65407:13;;65395:26;;:11;:26::i;:::-;65384:8;:37;;;;;;;;;;;;;;;65455:13;;;;65443:26;;:11;:26::i;:::-;65432:8;;:37;;;;;;;;;;;;;;;;;;65484:9;65480:240;;;65535:13;;65517:14;;;;:31;;;;:66;;;65570:4;:13;;;65552:4;:14;;;:31;;65517:66;65510:74;;;;65627:27;65639:4;:14;;;65627:11;:27::i;:::-;65615:9;:39;;;;;;;;;;;;;;;65693:14;;;;65681:27;;:11;:27::i;:::-;65669:9;;:39;;;;;;;;;;;;;;;;;;65480:240;65740:14;;;;;65756;;;;;65772:13;;65787;;;;;65735:66;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;65306:503;;:::o;30220:106::-;30308:10;30220:106;:::o;40144:346::-;40246:19;;;40238:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40325:21;;;40317:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40398:18;;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;40450:32;;;;;;;;;;;;;;;;;40144:346;;;:::o;37756:539::-;37862:20;;;37854:70;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;37943:23;;;37935:71;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38019:47;38040:6;38048:9;38059:6;38019:20;:47::i;:::-;38099:71;38121:6;38099:71;;;;;;;;;;;;;;;;;:17;;;:9;:17;;;;;;;;;;;;:71;:21;:71::i;:::-;38079:17;;;;:9;:17;;;;;;;;;;;:91;;;;38204:20;;;;;;;:32;;38229:6;38204:24;:32::i;:::-;38181:20;;;;:9;:20;;;;;;;;;;;;:55;;;;38252:35;;;;;;;38181:20;;38252:35;;;;;;;;;;;;;37756:539;;;:::o;5655:166::-;5741:7;5777:12;5769:6;;;;5761:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5808:5:0;;;5655:166::o;65914:953::-;65991:10;66015:13;66030:23;66057:7;;;;;;;;;;;:27;;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;66057:29:0;;;;;;;66152:5;;66105:19;;;;;;;-1:-1:-1;66057:29:0;;-1:-1:-1;66057:29:0;;-1:-1:-1;66152:5:0;66183:677;;66213:11;;66209:581;;66245:13;66261:35;66274:21;66279:9;66290:4;66274;:21::i;66261:35::-;66245:51;;66315:17;66335:20;66348:6;66335:12;:20::i;:::-;66315:40;;66386:9;66378:5;:17;66374:401;;;66420:17;66440:109;;;;:39;66458:20;:5;66468:9;66458;:20::i;:::-;66440:13;:11;:13::i;:::-;:17;;:39::i;:109::-;66420:129;-1:-1:-1;66572:19:0;66594:30;66619:4;66594:20;:5;66604:9;66594;:20::i;:30::-;66572:52;;66647:17;66679:11;66667:9;:23;;;;;;;-1:-1:-1;66717:13:0;;66713:42;;66732:23;66738:5;66745:9;66732:5;:23::i;:::-;66374:401;;;;66209:581;;;66183:677;;;66811:11;;66807:53;;66847:1;66839:5;:9;66807:53;65914:953;;;;;;;:::o;3707:220::-;3765:7;3789:6;3785:20;;-1:-1:-1;3804:1:0;3797:8;;3785:20;3828:5;;;3832:1;3828;:5;:1;3852:5;;;;;:10;3844:56;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26859:312;26907:9;26937:1;26933;:5;26929:235;;;-1:-1:-1;26959:1:0;26995;26991;26987:5;;:9;27011:92;27022:1;27018;:5;27011:92;;;27048:1;27044:5;;27086:1;27081;27077;27073;:5;;;;;;:9;27072:15;;;;;;27068:19;;27011:92;;;26929:235;;;;27124:6;;27120:44;;-1:-1:-1;27151:1:0;26859:312;;;:::o;38577:378::-;38661:21;;;38653:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38731:49;38760:1;38764:7;38773:6;38731:20;:49::i;:::-;38808:12;;:24;;38825:6;38808:16;:24::i;:::-;38793:12;:39;38864:18;;;:9;:18;;;;;;;;;;;:30;;38887:6;38864:22;:30::i;:::-;38843:18;;;:9;:18;;;;;;;;;;;:51;;;;38910:37;;;;;;;38843:18;;:9;;38910:37;;;;;;;;;;38577:378;;:::o;7938:106::-;7996:7;8027:1;8023;:5;:13;;8035:1;8023:13;;;-1:-1:-1;8031:1:0;;8016:20;-1:-1:-1;7938:106:0:o;7755:107::-;7813:7;7845:1;7840;:6;;:14;;7853:1;7840:14;;67684:188;67762:7;67789:9;:75;;67851:13;;;;67835;;:29;67789:75;;;-1:-1:-1;67818:14:0;;;;67801;;;;;:31;;67684:188;-1:-1:-1;67684:188:0:o;39288:418::-;39372:21;;;39364:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39444:49;39465:7;39482:1;39486:6;39444:20;:49::i;:::-;39527:68;39550:6;39527:68;;;;;;;;;;;;;;;;;:18;;;:9;:18;;;;;;;;;;;;:68;:22;:68::i;:::-;39506:18;;;:9;:18;;;;;;;;;;:89;39621:12;;:24;;39638:6;39621:16;:24::i;:::-;39606:12;:39;39661:37;;;;;;;;39687:1;;39661:37;;;;;;;;;;;;;39288:418;;:::o;50133:792::-;50327:14;;50197:7;;50327:14;;;;;50313:28;;;50352:89;;50411:8;;50394:35;;50411:8;;;;;50421:7;;;;50394:16;:35::i;:::-;50387:42;;;;;50352:89;50478:8;;50451:17;;50471:49;;50478:8;;47589:4;47572:13;47571:22;50501:18;;47571:22;;;;50501:18;;50471:6;:49::i;:::-;50557:7;;50451:69;;-1:-1:-1;50531:16:0;;50550:47;;50557:7;;;;;47656:5;47639:13;47638:23;;50550:47;50531:66;-1:-1:-1;50620:111:0;50659:61;50706:13;;;47589:4;47572:13;47571:22;;47519:6;50660:23;;50659:46;:61::i;:::-;50620:9;;:24;:111::i;:::-;50608:123;-1:-1:-1;50753:109:0;50791:60;50837:13;;;47656:5;47639:13;47638:23;;50791:60;50753:8;;:23;:109::i;:::-;50742:120;;50880:37;50897:9;50908:8;50880:16;:37::i;:::-;50873:44;50133:792;-1:-1:-1;;;;;50133:792:0:o;28302:1268::-;28369:7;27439:19;28393:18;:24;28389:1174;;-1:-1:-1;27519:24:0;28434:9;;28389:1174;27396:6;28465:18;:31;28461:1102;;27778:23;28563:22;;28559:482;;;28620:22;;;28606:11;28676:27;28620:22;28701:1;28676:24;:27::i;:::-;28661:42;-1:-1:-1;28791:5:0;28730:57;28765:21;28782:3;27675:1;27656:15;27648:28;;;28765:16;:21::i;:::-;28730:30;28737:22;28754:4;27610:2;27589:17;27581:31;;28737:22;27713:29;;28730:6;:30::i;:57::-;28729:67;;;;;;28722:74;;;;;;28559:482;27778:23;28851:22;;;28837:11;28907:27;28851:22;28932:1;28907:24;:27::i;:::-;28892:42;-1:-1:-1;29020:5:0;28960:57;28995:21;29012:3;27675:1;27656:15;27648:28;;28995:21;28960:30;28967:22;28984:4;27610:2;27589:17;27581:31;;28967:22;27713:29;;28960:6;:30::i;28461:1102::-;29151:11;27839:24;29184:22;;:76;;27839:24;29237:22;;;29184:76;;;29210:22;;;29184:76;29151:124;-1:-1:-1;29296:27:0;29151:124;29321:1;29296:24;:27::i;:::-;29290:33;-1:-1:-1;29338:12:0;29353:26;29368:10;29290:33;27948:23;29368:7;:10::i;:::-;29353;27899:13;29359:3;29353:5;:10::i;:26::-;29338:41;-1:-1:-1;27839:24:0;29398:22;;29394:158;;;29463:5;29448:12;28102:20;29455:4;29448:6;:12::i;29394:158::-;29531:5;29516:12;28102:20;29523:4;29516:6;:12::i;67253:423::-;67337:7;67372:5;67361:7;:16;;;67357:312;;-1:-1:-1;67401:14:0;67394:21;;67357:312;67448:5;67437:7;:16;;;67433:236;;67501:2;67495;67478:19;;67477:26;;67470:33;;;;67433:236;67536:6;67525:7;:17;;;67521:148;;67590:2;67584;67567:19;;67566:26;;67521:148;67655:2;67650:1;67633:18;;67632:25;;24913:761;25337:23;25363:69;25391:4;25363:69;;;;;;;;;;;;;;;;;25371:5;25363:27;;;;:69;;;;;:::i;:::-;25447:17;;25337:95;;-1:-1:-1;25447:21:0;25443:224;;25589:10;25578:30;;;;;;;;;;;;;;;-1:-1:-1;25578:30:0;25570:85;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4405:153;4463:7;4495:1;4491;:5;4483:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4549:1;4545;:5;;;;;;;4405:153;-1:-1:-1;;;4405:153:0:o;48672:1400::-;48911:14;;48776:7;;48911:14;;;;;48897:28;;;48936:273;;49030:18;;48992:130;;49022:38;;49030:18;;49054:5;49022:31;:38::i;:::-;48992:130;;;;;;;;;;;;;;;;;:11;:130::i;:::-;48971:18;:151;;;;;;;;;;;49169:8;;49144:53;;49169:8;;;;49188:7;;;;49144:16;:53::i;:::-;49137:60;;;;;48936:273;49249:18;;49305:8;;49249:18;;;;;49219:27;;49298:49;;49305:8;47589:4;47572:13;47571:22;;49298:49;49384:7;;49278:69;;-1:-1:-1;49358:16:0;;49377:47;;49384:7;;;;;47656:5;47639:13;47638:23;;49377:47;49358:66;-1:-1:-1;49497:111:0;49536:61;49583:13;;;47589:4;47572:13;47571:22;;49497:111;49485:123;-1:-1:-1;49630:109:0;49668:60;49714:13;;;47656:5;47639:13;47638:23;;49630:109;49619:120;;49761:22;49773:9;49761:11;:22::i;:::-;49750:8;:33;;;;;;;;;;;;;;;49804:21;49816:8;49804:11;:21::i;:::-;49794:7;:31;;;;;;;;;;;;;;;;49857:18;49869:5;49857:11;:18::i;:::-;49836;:39;;;;;;;;;;;;;;;49903:24;49915:11;49903;:24::i;:::-;49886:14;:41;;;;;;;;;;;;;;49945:62;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50027:37;50044:9;50055:8;50027:16;:37::i;:::-;50020:44;48672:1400;-1:-1:-1;;;;;;;48672:1400:0:o;67880:153::-;67935:7;52448:10;67963:1;:16;;67955:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;68023:1:0;67880:153::o;50933:259::-;51046:7;51075:13;51071:54;;-1:-1:-1;51112:1:0;51105:8;;51071:54;51176:8;25858:6;51143:9;:29;51142:42;;;;51537:260;51653:7;47519:6;51680:5;:17;51673:25;;;;47519:6;51770:5;51762:14;;51754:5;:22;51747:3;51739:12;;51730:5;47519:6;51718:17;51717:34;:59;51716:73;;;;;;;51537:260;-1:-1:-1;;;;51537:260:0:o;26212:529::-;26325:20;25858:6;26371:12;:25;;26363:60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26453:1;26449;:5;:37;;25858:6;26449:37;;;26462:12;26449:37;26434:52;-1:-1:-1;26509:1:0;26504:6;;;;26499:235;26512:6;;26499:235;;25858:6;26559:27;;;26558:41;;-1:-1:-1;26624:1:0;26620;:5;:10;26616:107;;25858:6;26667:27;;;26666:41;26616:107;26525:1;26520:6;;;;26499:235;;25913:124;25982:7;25858:6;26009:8;:1;26015;26009:5;:8::i;:::-;:20;;;;17594:195;17697:12;17729:52;17751:6;17759:4;17765:1;17768:12;17729:21;:52::i;:::-;17722:59;17594:195;-1:-1:-1;;;;17594:195:0:o;51969:178::-;52052:7;52098:12;47464:10;52080:16;;;52072:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;52137:1:0;;51969:178;-1:-1:-1;;51969:178:0:o;51805:156::-;51860:7;47464:10;51888:1;:16;;51880:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18646:530;18773:12;18831:5;18806:21;:30;;18798:81;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18898:18;18909:6;18898:10;:18::i;:::-;18890:60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19024:12;19038:23;19065:6;:11;;19085:5;19093:4;19065:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19023:75;;;;19116:52;19134:7;19143:10;19155:12;19116:17;:52::i;14676:422::-;15043:20;15082:8;;;14676:422::o;21186:742::-;21301:12;21330:7;21326:595;;;-1:-1:-1;21361:10:0;21354:17;;21326:595;21475:17;;:21;21471:439;;21738:10;21732:17;21799:15;21786:10;21782:2;21778:19;21771:44;21686:148;21874:20;;;;;;;;;;;;;;;;;;;;21881:12;;21874:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o
Swarm Source
ipfs://49f6f8528b3e4b37e72b9bde0aa804ce74fda17a3dc51ea424bf85cf5943707e
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.