Overview
ETH Balance
1,176.964062544569623627 ETH
Eth Value
$3,962,729.56 (@ $3,366.91/ETH)Token Holdings
More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 163 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Remove Liquidity | 21447166 | 3 days ago | IN | 0 ETH | 0.00152477 | ||||
Remove Liquidity | 21431084 | 5 days ago | IN | 0 ETH | 0.00459579 | ||||
Remove Liquidity | 21420539 | 6 days ago | IN | 0 ETH | 0.00129676 | ||||
Remove Liquidity | 21398109 | 9 days ago | IN | 0 ETH | 0.0003785 | ||||
Remove Liquidity | 21391526 | 10 days ago | IN | 0 ETH | 0.00157121 | ||||
Remove Liquidity | 21353808 | 16 days ago | IN | 0 ETH | 0.00209704 | ||||
Remove Liquidity | 21347548 | 17 days ago | IN | 0 ETH | 0.00244845 | ||||
Remove Liquidity | 21339221 | 18 days ago | IN | 0 ETH | 0.00363798 | ||||
Remove Liquidity | 21339163 | 18 days ago | IN | 0 ETH | 0.00363483 | ||||
Remove Liquidity | 21286252 | 25 days ago | IN | 0 ETH | 0.00175152 | ||||
Remove Liquidity | 21283993 | 25 days ago | IN | 0 ETH | 0.00130063 | ||||
Remove Liquidity | 21280964 | 26 days ago | IN | 0 ETH | 0.00330719 | ||||
Remove Liquidity | 21264641 | 28 days ago | IN | 0 ETH | 0.00262143 | ||||
Remove Liquidity | 21260047 | 29 days ago | IN | 0 ETH | 0.00158937 | ||||
Remove Liquidity | 21252865 | 30 days ago | IN | 0 ETH | 0.00220977 | ||||
Remove Liquidity | 21250195 | 30 days ago | IN | 0 ETH | 0.00144624 | ||||
Remove Liquidity | 21220048 | 34 days ago | IN | 0 ETH | 0.00177078 | ||||
Remove Liquidity | 21155859 | 43 days ago | IN | 0 ETH | 0.00189982 | ||||
Remove Liquidity | 21149844 | 44 days ago | IN | 0 ETH | 0.00167068 | ||||
Remove Liquidity | 21101384 | 51 days ago | IN | 0 ETH | 0.00179241 | ||||
Remove Liquidity | 21098674 | 51 days ago | IN | 0 ETH | 0.00093973 | ||||
Remove Liquidity | 21095286 | 52 days ago | IN | 0 ETH | 0.00102934 | ||||
Remove Liquidity | 21077497 | 54 days ago | IN | 0 ETH | 0.00179806 | ||||
Remove Liquidity | 21051796 | 58 days ago | IN | 0 ETH | 0.00109728 | ||||
Remove Liquidity | 20867797 | 83 days ago | IN | 0 ETH | 0.00111061 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
21469153 | 29 mins ago | 0.52384483 ETH | ||||
21469030 | 54 mins ago | 1.5 ETH | ||||
21469029 | 54 mins ago | 1.79795853 ETH | ||||
21469019 | 56 mins ago | 1.5 ETH | ||||
21469018 | 56 mins ago | 1.90307967 ETH | ||||
21468873 | 1 hr ago | 1.5 ETH | ||||
21468865 | 1 hr ago | 1.77966372 ETH | ||||
21468778 | 1 hr ago | 1.60097587 ETH | ||||
21468754 | 1 hr ago | 0.13031189 ETH | ||||
21468752 | 1 hr ago | 0.16907831 ETH | ||||
21468650 | 2 hrs ago | 1.5 ETH | ||||
21468638 | 2 hrs ago | 1.5 ETH | ||||
21468456 | 2 hrs ago | 1.5 ETH | ||||
21468397 | 3 hrs ago | 1.07062348 ETH | ||||
21468306 | 3 hrs ago | 0.73929389 ETH | ||||
21468305 | 3 hrs ago | 1.5 ETH | ||||
21468092 | 4 hrs ago | 0.05315158 ETH | ||||
21467761 | 5 hrs ago | 0.75695806 ETH | ||||
21467692 | 5 hrs ago | 0.9603363 ETH | ||||
21467691 | 5 hrs ago | 2.77050983 ETH | ||||
21467600 | 5 hrs ago | 1.5 ETH | ||||
21467538 | 5 hrs ago | 1.5 ETH | ||||
21467517 | 5 hrs ago | 1.81600773 ETH | ||||
21467512 | 6 hrs ago | 1.5 ETH | ||||
21467484 | 6 hrs ago | 0.23321512 ETH |
Loading...
Loading
Contract Name:
StandardPoolConverter
Compiler Version
v0.6.12+commit.27d51765
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2023-10-26 */ // File @openzeppelin/contracts/math/[email protected] // 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/token/ERC20/[email protected] 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/[email protected] 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/[email protected] 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/utility/interfaces/IOwned.sol pragma solidity 0.6.12; /** * @dev Owned interface */ interface IOwned { function owner() external view returns (address); function transferOwnership(address newOwner) external; function acceptOwnership() external; } // File contracts/converter/interfaces/IConverterAnchor.sol pragma solidity 0.6.12; /** * @dev Converter Anchor interface */ interface IConverterAnchor is IOwned { } // File contracts/token/interfaces/IReserveToken.sol pragma solidity 0.6.12; /** * @dev This contract is used to represent reserve tokens, which are tokens that can either be regular ERC20 tokens or * native ETH (represented by the NATIVE_TOKEN_ADDRESS address) * * Please note that this interface is intentionally doesn't inherit from IERC20, so that it'd be possible to effectively * override its balanceOf() function in the ReserveToken library */ interface IReserveToken { } // File contracts/converter/interfaces/IConverter.sol pragma solidity 0.6.12; /** * @dev Converter interface */ interface IConverter is IOwned { function converterType() external pure returns (uint16); function anchor() external view returns (IConverterAnchor); function isActive() external view returns (bool); function targetAmountAndFee( IReserveToken sourceToken, IReserveToken targetToken, uint256 sourceAmount ) external view returns (uint256, uint256); function convert( IReserveToken sourceToken, IReserveToken targetToken, uint256 sourceAmount, address trader, address payable beneficiary ) external payable returns (uint256); function conversionFee() external view returns (uint32); function maxConversionFee() external view returns (uint32); function reserveBalance(IReserveToken reserveToken) external view returns (uint256); receive() external payable; function transferAnchorOwnership(address newOwner) external; function acceptAnchorOwnership() external; function setConversionFee(uint32 fee) external; function addReserve(IReserveToken token, uint32 weight) external; function transferReservesOnUpgrade(address newConverter) external; function onUpgradeComplete() external; // deprecated, backward compatibility function token() external view returns (IConverterAnchor); function transferTokenOwnership(address newOwner) external; function acceptTokenOwnership() external; function reserveTokenCount() external view returns (uint16); function reserveTokens() external view returns (IReserveToken[] memory); function connectors(IReserveToken reserveToken) external view returns ( uint256, uint32, bool, bool, bool ); function getConnectorBalance(IReserveToken connectorToken) external view returns (uint256); function connectorTokens(uint256 index) external view returns (IReserveToken); function connectorTokenCount() external view returns (uint16); /** * @dev triggered when the converter is activated */ event Activation(uint16 indexed converterType, IConverterAnchor indexed anchor, bool indexed activated); /** * @dev triggered when a conversion between two tokens occurs */ event Conversion( IReserveToken indexed sourceToken, IReserveToken indexed targetToken, address indexed trader, uint256 sourceAmount, uint256 targetAmount, int256 conversionFee ); /** * @dev triggered when the rate between two tokens in the converter changes * * note that the event might be dispatched for rate updates between any two tokens in the converter */ event TokenRateUpdate(address indexed token1, address indexed token2, uint256 rateN, uint256 rateD); /** * @dev triggered when the conversion fee is updated */ event ConversionFeeUpdate(uint32 prevFee, uint32 newFee); } // File @openzeppelin/contracts/utils/[email protected] 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 contracts/converter/ConverterVersion.sol pragma solidity 0.6.12; contract ConverterVersion { // note that the version is defined as is for backward compatibility with older converters // solhint-disable-next-line const-name-snakecase uint16 public constant version = 48; } // File contracts/converter/interfaces/IConverterUpgrader.sol pragma solidity 0.6.12; /** * @dev Converter Upgrader interface */ interface IConverterUpgrader { function upgrade(bytes32 version) external; function upgrade(uint16 version) external; } // File contracts/utility/interfaces/ITokenHolder.sol pragma solidity 0.6.12; /** * @dev Token Holder interface */ interface ITokenHolder is IOwned { receive() external payable; function withdrawTokens( IReserveToken reserveToken, address payable to, uint256 amount ) external; function withdrawTokensMultiple( IReserveToken[] calldata reserveTokens, address payable to, uint256[] calldata amounts ) external; } // File contracts/INetworkSettings.sol pragma solidity 0.6.12; interface INetworkSettings { function networkFeeParams() external view returns (ITokenHolder, uint32); function networkFeeWallet() external view returns (ITokenHolder); function networkFee() external view returns (uint32); } // File contracts/token/interfaces/IDSToken.sol pragma solidity 0.6.12; /** * @dev DSToken interface */ interface IDSToken is IConverterAnchor, IERC20 { function issue(address recipient, uint256 amount) external; function destroy(address recipient, uint256 amount) external; } // File contracts/token/SafeERC20Ex.sol pragma solidity 0.6.12; /** * @dev Extends the SafeERC20 library with additional operations */ library SafeERC20Ex { using SafeERC20 for IERC20; /** * @dev ensures that the spender has sufficient allowance */ function ensureApprove( IERC20 token, address spender, uint256 amount ) internal { if (amount == 0) { return; } uint256 allowance = token.allowance(address(this), spender); if (allowance >= amount) { return; } if (allowance > 0) { token.safeApprove(spender, 0); } token.safeApprove(spender, amount); } } // File contracts/token/ReserveToken.sol pragma solidity 0.6.12; /** * @dev This library implements ERC20 and SafeERC20 utilities for reserve tokens, which can be either ERC20 tokens or ETH */ library ReserveToken { using SafeERC20 for IERC20; using SafeERC20Ex for IERC20; // the address that represents an ETH reserve IReserveToken public constant NATIVE_TOKEN_ADDRESS = IReserveToken(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); /** * @dev returns whether the provided token represents an ERC20 or ETH reserve */ function isNativeToken(IReserveToken reserveToken) internal pure returns (bool) { return reserveToken == NATIVE_TOKEN_ADDRESS; } /** * @dev returns the balance of the reserve token */ function balanceOf(IReserveToken reserveToken, address account) internal view returns (uint256) { if (isNativeToken(reserveToken)) { return account.balance; } return toIERC20(reserveToken).balanceOf(account); } /** * @dev transfers a specific amount of the reserve token */ function safeTransfer( IReserveToken reserveToken, address to, uint256 amount ) internal { if (amount == 0) { return; } if (isNativeToken(reserveToken)) { payable(to).transfer(amount); } else { toIERC20(reserveToken).safeTransfer(to, amount); } } /** * @dev transfers a specific amount of the reserve token from a specific holder using the allowance mechanism * * note that the function ignores a reserve token which represents an ETH reserve */ function safeTransferFrom( IReserveToken reserveToken, address from, address to, uint256 amount ) internal { if (amount == 0 || isNativeToken(reserveToken)) { return; } toIERC20(reserveToken).safeTransferFrom(from, to, amount); } /** * @dev ensures that the spender has sufficient allowance * * note that this function ignores a reserve token which represents an ETH reserve */ function ensureApprove( IReserveToken reserveToken, address spender, uint256 amount ) internal { if (isNativeToken(reserveToken)) { return; } toIERC20(reserveToken).ensureApprove(spender, amount); } /** * @dev utility function that converts an IReserveToken to an IERC20 */ function toIERC20(IReserveToken reserveToken) private pure returns (IERC20) { return IERC20(address(reserveToken)); } } // File contracts/utility/interfaces/IContractRegistry.sol pragma solidity 0.6.12; /** * @dev Contract Registry interface */ interface IContractRegistry { function addressOf(bytes32 contractName) external view returns (address); } // File contracts/utility/Owned.sol pragma solidity 0.6.12; /** * @dev This contract provides support and utilities for contract ownership. */ contract Owned is IOwned { address private _owner; address private _newOwner; /** * @dev triggered when the owner is updated */ event OwnerUpdate(address indexed prevOwner, address indexed newOwner); /** * @dev initializes a new Owned instance */ constructor() public { _owner = msg.sender; } // allows execution by the owner only modifier ownerOnly() { _ownerOnly(); _; } // error message binary size optimization function _ownerOnly() private view { require(msg.sender == _owner, "ERR_ACCESS_DENIED"); } /** * @dev allows transferring the contract ownership * * Requirements: * * - the caller must be the owner of the contract * * note the new owner still needs to accept the transfer */ function transferOwnership(address newOwner) public override ownerOnly { require(newOwner != _owner, "ERR_SAME_OWNER"); _newOwner = newOwner; } /** * @dev used by a new owner to accept an ownership transfer */ function acceptOwnership() public override { require(msg.sender == _newOwner, "ERR_ACCESS_DENIED"); emit OwnerUpdate(_owner, _newOwner); _owner = _newOwner; _newOwner = address(0); } /** * @dev returns the address of the current owner */ function owner() public view override returns (address) { return _owner; } /** * @dev returns the address of the new owner candidate */ function newOwner() external view returns (address) { return _newOwner; } } // File contracts/utility/Utils.sol pragma solidity 0.6.12; /** * @dev Utilities & Common Modifiers */ contract Utils { uint32 internal constant PPM_RESOLUTION = 1000000; // verifies that a value is greater than zero modifier greaterThanZero(uint256 value) { _greaterThanZero(value); _; } // error message binary size optimization function _greaterThanZero(uint256 value) internal pure { require(value > 0, "ERR_ZERO_VALUE"); } // validates an address - currently only checks that it isn't null modifier validAddress(address addr) { _validAddress(addr); _; } // error message binary size optimization function _validAddress(address addr) internal pure { require(addr != address(0), "ERR_INVALID_ADDRESS"); } // ensures that the portion is valid modifier validPortion(uint32 _portion) { _validPortion(_portion); _; } // error message binary size optimization function _validPortion(uint32 _portion) internal pure { require(_portion > 0 && _portion <= PPM_RESOLUTION, "ERR_INVALID_PORTION"); } // validates an external address - currently only checks that it isn't null or this modifier validExternalAddress(address addr) { _validExternalAddress(addr); _; } // error message binary size optimization function _validExternalAddress(address addr) internal view { require(addr != address(0) && addr != address(this), "ERR_INVALID_EXTERNAL_ADDRESS"); } // ensures that the fee is valid modifier validFee(uint32 fee) { _validFee(fee); _; } // error message binary size optimization function _validFee(uint32 fee) internal pure { require(fee <= PPM_RESOLUTION, "ERR_INVALID_FEE"); } } // File contracts/utility/ContractRegistryClient.sol pragma solidity 0.6.12; /** * @dev This is the base contract for ContractRegistry clients. */ contract ContractRegistryClient is Owned, Utils { bytes32 internal constant CONTRACT_REGISTRY = "ContractRegistry"; bytes32 internal constant BANCOR_NETWORK = "BancorNetwork"; bytes32 internal constant CONVERTER_FACTORY = "ConverterFactory"; bytes32 internal constant CONVERSION_PATH_FINDER = "ConversionPathFinder"; bytes32 internal constant CONVERTER_UPGRADER = "BancorConverterUpgrader"; bytes32 internal constant CONVERTER_REGISTRY = "BancorConverterRegistry"; bytes32 internal constant CONVERTER_REGISTRY_DATA = "BancorConverterRegistryData"; bytes32 internal constant BNT_TOKEN = "BNTToken"; bytes32 internal constant BANCOR_X = "BancorX"; bytes32 internal constant BANCOR_X_UPGRADER = "BancorXUpgrader"; bytes32 internal constant LIQUIDITY_PROTECTION = "LiquidityProtection"; bytes32 internal constant NETWORK_SETTINGS = "NetworkSettings"; // address of the current contract registry IContractRegistry private _registry; // address of the previous contract registry IContractRegistry private _prevRegistry; // only the owner can update the contract registry bool private _onlyOwnerCanUpdateRegistry; /** * @dev verifies that the caller is mapped to the given contract name */ modifier only(bytes32 contractName) { _only(contractName); _; } // error message binary size optimization function _only(bytes32 contractName) internal view { require(msg.sender == _addressOf(contractName), "ERR_ACCESS_DENIED"); } /** * @dev initializes a new ContractRegistryClient instance */ constructor(IContractRegistry initialRegistry) internal validAddress(address(initialRegistry)) { _registry = IContractRegistry(initialRegistry); _prevRegistry = IContractRegistry(initialRegistry); } /** * @dev updates to the new contract registry */ function updateRegistry() external { // verify that this function is permitted require(msg.sender == owner() || !_onlyOwnerCanUpdateRegistry, "ERR_ACCESS_DENIED"); // get the new contract registry IContractRegistry newRegistry = IContractRegistry(_addressOf(CONTRACT_REGISTRY)); // verify that the new contract registry is different and not zero require(newRegistry != _registry && address(newRegistry) != address(0), "ERR_INVALID_REGISTRY"); // verify that the new contract registry is pointing to a non-zero contract registry require(newRegistry.addressOf(CONTRACT_REGISTRY) != address(0), "ERR_INVALID_REGISTRY"); // save a backup of the current contract registry before replacing it _prevRegistry = _registry; // replace the current contract registry with the new contract registry _registry = newRegistry; } /** * @dev restores the previous contract registry */ function restoreRegistry() external ownerOnly { // restore the previous contract registry _registry = _prevRegistry; } /** * @dev restricts the permission to update the contract registry */ function restrictRegistryUpdate(bool restrictOwnerOnly) public ownerOnly { // change the permission to update the contract registry _onlyOwnerCanUpdateRegistry = restrictOwnerOnly; } /** * @dev returns the address of the current contract registry */ function registry() public view returns (IContractRegistry) { return _registry; } /** * @dev returns the address of the previous contract registry */ function prevRegistry() external view returns (IContractRegistry) { return _prevRegistry; } /** * @dev returns whether only the owner can update the contract registry */ function onlyOwnerCanUpdateRegistry() external view returns (bool) { return _onlyOwnerCanUpdateRegistry; } /** * @dev returns the address associated with the given contract name */ function _addressOf(bytes32 contractName) internal view returns (address) { return _registry.addressOf(contractName); } } // File contracts/utility/MathEx.sol pragma solidity 0.6.12; /** * @dev This library provides a set of complex math operations. */ library MathEx { uint256 private constant MAX_EXP_BIT_LEN = 4; uint256 private constant MAX_EXP = 2**MAX_EXP_BIT_LEN - 1; uint256 private constant MAX_UINT256 = uint256(-1); /** * @dev returns the largest integer smaller than or equal to the square root of a positive integer */ function floorSqrt(uint256 num) internal pure returns (uint256) { uint256 x = num / 2 + 1; uint256 y = (x + num / x) / 2; while (x > y) { x = y; y = (x + num / x) / 2; } return x; } /** * @dev returns the smallest integer larger than or equal to the square root of a positive integer */ function ceilSqrt(uint256 num) internal pure returns (uint256) { uint256 x = floorSqrt(num); return x * x == num ? x : x + 1; } /** * @dev computes the product of two given ratios */ function productRatio( uint256 xn, uint256 yn, uint256 xd, uint256 yd ) internal pure returns (uint256, uint256) { uint256 n = mulDivC(xn, yn, MAX_UINT256); uint256 d = mulDivC(xd, yd, MAX_UINT256); uint256 z = n > d ? n : d; if (z > 1) { return (mulDivC(xn, yn, z), mulDivC(xd, yd, z)); } return (xn * yn, xd * yd); } /** * @dev computes a reduced-scalar ratio */ function reducedRatio( uint256 n, uint256 d, uint256 max ) internal pure returns (uint256, uint256) { (uint256 newN, uint256 newD) = (n, d); if (newN > max || newD > max) { (newN, newD) = normalizedRatio(newN, newD, max); } if (newN != newD) { return (newN, newD); } return (1, 1); } /** * @dev computes "scale * a / (a + b)" and "scale * b / (a + b)". */ function normalizedRatio( uint256 a, uint256 b, uint256 scale ) internal pure returns (uint256, uint256) { if (a <= b) { return accurateRatio(a, b, scale); } (uint256 y, uint256 x) = accurateRatio(b, a, scale); return (x, y); } /** * @dev computes "scale * a / (a + b)" and "scale * b / (a + b)", assuming that "a <= b". */ function accurateRatio( uint256 a, uint256 b, uint256 scale ) internal pure returns (uint256, uint256) { uint256 maxVal = MAX_UINT256 / scale; if (a > maxVal) { uint256 c = a / (maxVal + 1) + 1; a /= c; // we can now safely compute `a * scale` b /= c; } if (a != b) { uint256 newN = a * scale; uint256 newD = unsafeAdd(a, b); // can overflow if (newD >= a) { // no overflow in `a + b` uint256 x = roundDiv(newN, newD); // we can now safely compute `scale - x` uint256 y = scale - x; return (x, y); } if (newN < b - (b - a) / 2) { return (0, scale); // `a * scale < (a + b) / 2 < MAX_UINT256 < a + b` } return (1, scale - 1); // `(a + b) / 2 < a * scale < MAX_UINT256 < a + b` } return (scale / 2, scale / 2); // allow reduction to `(1, 1)` in the calling function } /** * @dev computes the nearest integer to a given quotient without overflowing or underflowing. */ function roundDiv(uint256 n, uint256 d) internal pure returns (uint256) { return n / d + (n % d) / (d - d / 2); } /** * @dev returns the average number of decimal digits in a given list of positive integers */ function geometricMean(uint256[] memory values) internal pure returns (uint256) { uint256 numOfDigits = 0; uint256 length = values.length; for (uint256 i = 0; i < length; ++i) { numOfDigits += decimalLength(values[i]); } return uint256(10)**(roundDivUnsafe(numOfDigits, length) - 1); } /** * @dev returns the number of decimal digits in a given positive integer */ function decimalLength(uint256 x) internal pure returns (uint256) { uint256 y = 0; for (uint256 tmpX = x; tmpX > 0; tmpX /= 10) { ++y; } return y; } /** * @dev returns the nearest integer to a given quotient * * note the computation is overflow-safe assuming that the input is sufficiently small */ function roundDivUnsafe(uint256 n, uint256 d) internal pure returns (uint256) { return (n + d / 2) / d; } /** * @dev returns the largest integer smaller than or equal to `x * y / z` */ function mulDivF( uint256 x, uint256 y, uint256 z ) internal pure returns (uint256) { (uint256 xyh, uint256 xyl) = mul512(x, y); // if `x * y < 2 ^ 256` if (xyh == 0) { return xyl / z; } // assert `x * y / z < 2 ^ 256` require(xyh < z, "ERR_OVERFLOW"); uint256 m = mulMod(x, y, z); // `m = x * y % z` (uint256 nh, uint256 nl) = sub512(xyh, xyl, m); // `n = x * y - m` hence `n / z = floor(x * y / z)` // if `n < 2 ^ 256` if (nh == 0) { return nl / z; } uint256 p = unsafeSub(0, z) & z; // `p` is the largest power of 2 which `z` is divisible by uint256 q = div512(nh, nl, p); // `n` is divisible by `p` because `n` is divisible by `z` and `z` is divisible by `p` uint256 r = inv256(z / p); // `z / p = 1 mod 2` hence `inverse(z / p) = 1 mod 2 ^ 256` return unsafeMul(q, r); // `q * r = (n / p) * inverse(z / p) = n / z` } /** * @dev returns the smallest integer larger than or equal to `x * y / z` */ function mulDivC( uint256 x, uint256 y, uint256 z ) internal pure returns (uint256) { uint256 w = mulDivF(x, y, z); if (mulMod(x, y, z) > 0) { require(w < MAX_UINT256, "ERR_OVERFLOW"); return w + 1; } return w; } /** * @dev returns the value of `x * y` as a pair of 256-bit values */ function mul512(uint256 x, uint256 y) private pure returns (uint256, uint256) { uint256 p = mulModMax(x, y); uint256 q = unsafeMul(x, y); if (p >= q) { return (p - q, q); } return (unsafeSub(p, q) - 1, q); } /** * @dev returns the value of `2 ^ 256 * xh + xl - y`, where `2 ^ 256 * xh + xl >= y` */ function sub512( uint256 xh, uint256 xl, uint256 y ) private pure returns (uint256, uint256) { if (xl >= y) { return (xh, xl - y); } return (xh - 1, unsafeSub(xl, y)); } /** * @dev returns the value of `(2 ^ 256 * xh + xl) / pow2n`, where `xl` is divisible by `pow2n` */ function div512( uint256 xh, uint256 xl, uint256 pow2n ) private pure returns (uint256) { uint256 pow2nInv = unsafeAdd(unsafeSub(0, pow2n) / pow2n, 1); // `1 << (256 - n)` return unsafeMul(xh, pow2nInv) | (xl / pow2n); // `(xh << (256 - n)) | (xl >> n)` } /** * @dev returns the inverse of `d` modulo `2 ^ 256`, where `d` is congruent to `1` modulo `2` */ function inv256(uint256 d) private pure returns (uint256) { // approximate the root of `f(x) = 1 / x - d` using the newton–raphson convergence method uint256 x = 1; for (uint256 i = 0; i < 8; ++i) { x = unsafeMul(x, unsafeSub(2, unsafeMul(x, d))); // `x = x * (2 - x * d) mod 2 ^ 256` } return x; } /** * @dev returns `(x + y) % 2 ^ 256` */ function unsafeAdd(uint256 x, uint256 y) private pure returns (uint256) { return x + y; } /** * @dev returns `(x - y) % 2 ^ 256` */ function unsafeSub(uint256 x, uint256 y) private pure returns (uint256) { return x - y; } /** * @dev returns `(x * y) % 2 ^ 256` */ function unsafeMul(uint256 x, uint256 y) private pure returns (uint256) { return x * y; } /** * @dev returns `x * y % (2 ^ 256 - 1)` */ function mulModMax(uint256 x, uint256 y) private pure returns (uint256) { return mulmod(x, y, MAX_UINT256); } /** * @dev returns `x * y % z` */ function mulMod( uint256 x, uint256 y, uint256 z ) private pure returns (uint256) { return mulmod(x, y, z); } } // File contracts/utility/Time.sol pragma solidity 0.6.12; /* Time implementing contract */ contract Time { /** * @dev returns the current time */ function _time() internal view virtual returns (uint256) { return block.timestamp; } } // File contracts/converter/types/standard-pool/StandardPoolConverter.sol pragma solidity 0.6.12; /** * @dev This contract is a specialized version of the converter, which is optimized for a liquidity pool that has 2 * reserves with 50%/50% weights */ contract StandardPoolConverter is ConverterVersion, IConverter, ContractRegistryClient, ReentrancyGuard, Time { using SafeMath for uint256; using ReserveToken for IReserveToken; using SafeERC20 for IERC20; using Address for address payable; using MathEx for *; uint256 private constant MAX_UINT128 = 2**128 - 1; uint256 private constant MAX_UINT112 = 2**112 - 1; uint256 private constant MAX_UINT32 = 2**32 - 1; uint256 private constant AVERAGE_RATE_PERIOD = 10 minutes; uint256 private _reserveBalances; uint256 private _reserveBalancesProduct; IReserveToken[] private _reserveTokens; mapping(IReserveToken => uint256) private _reserveIds; IConverterAnchor private _anchor; // converter anchor contract uint32 private _maxConversionFee; // maximum conversion fee, represented in ppm, 0...1000000 uint32 private _conversionFee; // current conversion fee, represented in ppm, 0...maxConversionFee // average rate details: // bits 0...111 represent the numerator of the rate between reserve token 0 and reserve token 1 // bits 111...223 represent the denominator of the rate between reserve token 0 and reserve token 1 // bits 224...255 represent the update-time of the rate between reserve token 0 and reserve token 1 // where `numerator / denominator` gives the worth of one reserve token 0 in units of reserve token 1 uint256 private _averageRateInfo; /** * @dev triggered after liquidity is added */ event LiquidityAdded( address indexed provider, IReserveToken indexed reserveToken, uint256 amount, uint256 newBalance, uint256 newSupply ); /** * @dev triggered after liquidity is removed */ event LiquidityRemoved( address indexed provider, IReserveToken indexed reserveToken, uint256 amount, uint256 newBalance, uint256 newSupply ); /** * @dev initializes a new StandardPoolConverter instance */ constructor( IConverterAnchor anchor, IContractRegistry registry, uint32 maxConversionFee ) public ContractRegistryClient(registry) validAddress(address(anchor)) validConversionFee(maxConversionFee) { _anchor = anchor; _maxConversionFee = maxConversionFee; } // ensures that the converter is active modifier active() { _active(); _; } // error message binary size optimization function _active() private view { require(isActive(), "ERR_INACTIVE"); } // ensures that the converter is not active modifier inactive() { _inactive(); _; } // error message binary size optimization function _inactive() private view { require(!isActive(), "ERR_ACTIVE"); } // validates a reserve token address - verifies that the address belongs to one of the reserve tokens modifier validReserve(IReserveToken reserveToken) { _validReserve(reserveToken); _; } // error message binary size optimization function _validReserve(IReserveToken reserveToken) private view { require(_reserveIds[reserveToken] != 0, "ERR_INVALID_RESERVE"); } // validates conversion fee modifier validConversionFee(uint32 fee) { _validConversionFee(fee); _; } // error message binary size optimization function _validConversionFee(uint32 fee) private pure { require(fee <= PPM_RESOLUTION, "ERR_INVALID_CONVERSION_FEE"); } // validates reserve weight modifier validReserveWeight(uint32 weight) { _validReserveWeight(weight); _; } // error message binary size optimization function _validReserveWeight(uint32 weight) private pure { require(weight == PPM_RESOLUTION / 2, "ERR_INVALID_RESERVE_WEIGHT"); } /** * @dev returns the converter type */ function converterType() public pure virtual override returns (uint16) { return 3; } /** * @dev checks whether or not the converter version is 28 or higher */ function isV28OrHigher() external pure returns (bool) { return true; } /** * @dev returns the converter anchor */ function anchor() external view override returns (IConverterAnchor) { return _anchor; } /** * @dev returns the maximum conversion fee (in units of PPM) */ function maxConversionFee() external view override returns (uint32) { return _maxConversionFee; } /** * @dev returns the current conversion fee (in units of PPM) */ function conversionFee() external view override returns (uint32) { return _conversionFee; } /** * @dev returns the average rate info */ function averageRateInfo() external view returns (uint256) { return _averageRateInfo; } /** * @dev deposits ether * * Requirements: * * - can only be used if the converter has an ETH reserve */ receive() external payable override(IConverter) validReserve(ReserveToken.NATIVE_TOKEN_ADDRESS) {} /** * @dev returns true if the converter is active, false otherwise */ function isActive() public view virtual override returns (bool) { return _anchor.owner() == address(this); } /** * @dev transfers the anchor ownership * * Requirements: * * - the new owner needs to accept the transfer * - can only be called by the converter upgrader while the upgrader is the owner * * note that prior to version 28, you should use 'transferAnchorOwnership' instead */ function transferAnchorOwnership(address newOwner) public override ownerOnly only(CONVERTER_UPGRADER) { _anchor.transferOwnership(newOwner); } /** * @dev accepts ownership of the anchor after an ownership transfer * * Requirements: * * - most converters are also activated as soon as they accept the anchor ownership * - the caller must be the owner of the contract * * note that prior to version 28, you should use 'acceptTokenOwnership' instead */ function acceptAnchorOwnership() public virtual override ownerOnly { require(_reserveTokens.length == 2, "ERR_INVALID_RESERVE_COUNT"); _anchor.acceptOwnership(); _syncReserveBalances(0); emit Activation(converterType(), _anchor, true); } /** * @dev updates the current conversion fee * * Requirements: * * - the caller must be the owner of the contract */ function setConversionFee(uint32 fee) external override ownerOnly { require(fee <= _maxConversionFee, "ERR_INVALID_CONVERSION_FEE"); emit ConversionFeeUpdate(_conversionFee, fee); _conversionFee = fee; } /** * @dev transfers reserve balances to a new converter during an upgrade * * Requirements: * * - can only be called by the converter upgrader which should have been set at its owner */ function transferReservesOnUpgrade(address newConverter) external override nonReentrant ownerOnly only(CONVERTER_UPGRADER) { uint256 reserveCount = _reserveTokens.length; for (uint256 i = 0; i < reserveCount; ++i) { IReserveToken reserveToken = _reserveTokens[i]; reserveToken.safeTransfer(newConverter, reserveToken.balanceOf(address(this))); _syncReserveBalance(reserveToken); } } /** * @dev upgrades the converter to the latest version * * Requirements: * * - the caller must be the owner of the contract * * note that the owner needs to call acceptOwnership on the new converter after the upgrade */ function upgrade() external ownerOnly { IConverterUpgrader converterUpgrader = IConverterUpgrader(_addressOf(CONVERTER_UPGRADER)); // trigger de-activation event emit Activation(converterType(), _anchor, false); transferOwnership(address(converterUpgrader)); converterUpgrader.upgrade(version); acceptOwnership(); } /** * @dev executed by the upgrader at the end of the upgrade process to handle custom pool logic */ function onUpgradeComplete() external override nonReentrant ownerOnly only(CONVERTER_UPGRADER) { (uint256 reserveBalance0, uint256 reserveBalance1) = _loadReserveBalances(1, 2); _reserveBalancesProduct = reserveBalance0 * reserveBalance1; } /** * @dev returns the number of reserve tokens * * note that prior to version 17, you should use 'connectorTokenCount' instead */ function reserveTokenCount() public view override returns (uint16) { return uint16(_reserveTokens.length); } /** * @dev returns the array of reserve tokens */ function reserveTokens() external view override returns (IReserveToken[] memory) { return _reserveTokens; } /** * @dev defines a new reserve token for the converter * * Requirements: * * - the caller must be the owner of the contract * - the converter must be inactive */ function addReserve(IReserveToken token, uint32 weight) external virtual override ownerOnly inactive validExternalAddress(address(token)) validReserveWeight(weight) { require(address(token) != address(_anchor) && _reserveIds[token] == 0, "ERR_INVALID_RESERVE"); require(reserveTokenCount() < 2, "ERR_INVALID_RESERVE_COUNT"); _reserveTokens.push(token); _reserveIds[token] = _reserveTokens.length; } /** * @dev returns the reserve's weight */ function reserveWeight(IReserveToken reserveToken) external view validReserve(reserveToken) returns (uint32) { return PPM_RESOLUTION / 2; } /** * @dev returns the balance of a given reserve token */ function reserveBalance(IReserveToken reserveToken) public view override returns (uint256) { uint256 reserveId = _reserveIds[reserveToken]; require(reserveId != 0, "ERR_INVALID_RESERVE"); return _reserveBalance(reserveId); } /** * @dev returns the balances of both reserve tokens */ function reserveBalances() public view returns (uint256, uint256) { return _loadReserveBalances(1, 2); } /** * @dev syncs all stored reserve balances */ function syncReserveBalances() external { _syncReserveBalances(0); } /** * @dev calculates the accumulated network fee and transfers it to the network fee wallet */ function processNetworkFees() external nonReentrant { (uint256 reserveBalance0, uint256 reserveBalance1) = _processNetworkFees(0); _reserveBalancesProduct = reserveBalance0 * reserveBalance1; } /** * @dev calculates the accumulated network fee and transfers it to the network fee wallet */ function _processNetworkFees(uint256 value) private returns (uint256, uint256) { _syncReserveBalances(value); (uint256 reserveBalance0, uint256 reserveBalance1) = _loadReserveBalances(1, 2); (ITokenHolder wallet, uint256 fee0, uint256 fee1) = _networkWalletAndFees(reserveBalance0, reserveBalance1); reserveBalance0 -= fee0; reserveBalance1 -= fee1; _setReserveBalances(1, 2, reserveBalance0, reserveBalance1); // using a regular transfer here for the native token would revert due to exceeding // the 2300 gas limit which is why we're using call instead (via sendValue), // which the 2300 gas limit does not apply for if (_reserveTokens[0].isNativeToken()) { payable(address(wallet)).sendValue(fee0); } else { _reserveTokens[0].safeTransfer(address(wallet), fee0); } if (_reserveTokens[1].isNativeToken()) { payable(address(wallet)).sendValue(fee1); } else { _reserveTokens[1].safeTransfer(address(wallet), fee1); } return (reserveBalance0, reserveBalance1); } /** * @dev returns the reserve balances of the given reserve tokens minus their corresponding fees */ function _baseReserveBalances(IReserveToken[] memory baseReserveTokens) private view returns (uint256[2] memory) { uint256 reserveId0 = _reserveIds[baseReserveTokens[0]]; uint256 reserveId1 = _reserveIds[baseReserveTokens[1]]; (uint256 reserveBalance0, uint256 reserveBalance1) = _loadReserveBalances(reserveId0, reserveId1); (, uint256 fee0, uint256 fee1) = _networkWalletAndFees(reserveBalance0, reserveBalance1); return [reserveBalance0 - fee0, reserveBalance1 - fee1]; } /** * @dev converts a specific amount of source tokens to target tokens * * Requirements: * * - the caller must be the bancor network contract */ function convert( IReserveToken sourceToken, IReserveToken targetToken, uint256 sourceAmount, address trader, address payable beneficiary ) external payable override nonReentrant only(BANCOR_NETWORK) returns (uint256) { require(sourceToken != targetToken, "ERR_SAME_SOURCE_TARGET"); return _doConvert(sourceToken, targetToken, sourceAmount, trader, beneficiary); } /** * @dev returns the conversion fee for a given target amount */ function _calculateFee(uint256 targetAmount) private view returns (uint256) { return targetAmount.mul(_conversionFee) / PPM_RESOLUTION; } /** * @dev returns the conversion fee taken from a given target amount */ function _calculateFeeInv(uint256 targetAmount) private view returns (uint256) { return targetAmount.mul(_conversionFee).div(PPM_RESOLUTION - _conversionFee); } /** * @dev loads the stored reserve balance for a given reserve id */ function _reserveBalance(uint256 reserveId) private view returns (uint256) { return _decodeReserveBalance(_reserveBalances, reserveId); } /** * @dev loads the stored reserve balances */ function _loadReserveBalances(uint256 sourceId, uint256 targetId) private view returns (uint256, uint256) { require((sourceId == 1 && targetId == 2) || (sourceId == 2 && targetId == 1), "ERR_INVALID_RESERVES"); return _decodeReserveBalances(_reserveBalances, sourceId, targetId); } /** * @dev stores the stored reserve balance for a given reserve id */ function _setReserveBalance(uint256 reserveId, uint256 balance) private { require(balance <= MAX_UINT128, "ERR_RESERVE_BALANCE_OVERFLOW"); uint256 otherBalance = _decodeReserveBalance(_reserveBalances, 3 - reserveId); _reserveBalances = _encodeReserveBalances(balance, reserveId, otherBalance, 3 - reserveId); } /** * @dev stores the stored reserve balances */ function _setReserveBalances( uint256 sourceId, uint256 targetId, uint256 sourceBalance, uint256 targetBalance ) private { require(sourceBalance <= MAX_UINT128 && targetBalance <= MAX_UINT128, "ERR_RESERVE_BALANCE_OVERFLOW"); _reserveBalances = _encodeReserveBalances(sourceBalance, sourceId, targetBalance, targetId); } /** * @dev syncs the stored reserve balance for a given reserve with the real reserve balance */ function _syncReserveBalance(IReserveToken reserveToken) private { uint256 reserveId = _reserveIds[reserveToken]; _setReserveBalance(reserveId, reserveToken.balanceOf(address(this))); } /** * @dev syncs all stored reserve balances, excluding a given amount of ether from the ether reserve balance (if relevant) */ function _syncReserveBalances(uint256 value) private { IReserveToken _reserveToken0 = _reserveTokens[0]; IReserveToken _reserveToken1 = _reserveTokens[1]; uint256 balance0 = _reserveToken0.balanceOf(address(this)) - (_reserveToken0.isNativeToken() ? value : 0); uint256 balance1 = _reserveToken1.balanceOf(address(this)) - (_reserveToken1.isNativeToken() ? value : 0); _setReserveBalances(1, 2, balance0, balance1); } /** * @dev helper, dispatches the Conversion event */ function _dispatchConversionEvent( IReserveToken sourceToken, IReserveToken targetToken, address trader, uint256 sourceAmount, uint256 targetAmount, uint256 feeAmount ) private { emit Conversion(sourceToken, targetToken, trader, sourceAmount, targetAmount, int256(feeAmount)); } /** * @dev returns the expected amount and expected fee for converting one reserve to another */ function targetAmountAndFee( IReserveToken sourceToken, IReserveToken targetToken, uint256 sourceAmount ) public view virtual override active returns (uint256, uint256) { uint256 sourceId = _reserveIds[sourceToken]; uint256 targetId = _reserveIds[targetToken]; (uint256 sourceBalance, uint256 targetBalance) = _loadReserveBalances(sourceId, targetId); return _targetAmountAndFee(sourceToken, targetToken, sourceBalance, targetBalance, sourceAmount); } /** * @dev returns the expected amount and expected fee for converting one reserve to another */ function _targetAmountAndFee( IReserveToken, /* sourceToken */ IReserveToken, /* targetToken */ uint256 sourceBalance, uint256 targetBalance, uint256 sourceAmount ) private view returns (uint256, uint256) { uint256 targetAmount = _crossReserveTargetAmount(sourceBalance, targetBalance, sourceAmount); uint256 fee = _calculateFee(targetAmount); return (targetAmount - fee, fee); } /** * @dev returns the required amount and expected fee for converting one reserve to another */ function sourceAmountAndFee( IReserveToken sourceToken, IReserveToken targetToken, uint256 targetAmount ) public view virtual active returns (uint256, uint256) { uint256 sourceId = _reserveIds[sourceToken]; uint256 targetId = _reserveIds[targetToken]; (uint256 sourceBalance, uint256 targetBalance) = _loadReserveBalances(sourceId, targetId); uint256 fee = _calculateFeeInv(targetAmount); uint256 sourceAmount = _crossReserveSourceAmount(sourceBalance, targetBalance, targetAmount.add(fee)); return (sourceAmount, fee); } /** * @dev converts a specific amount of source tokens to target tokens and returns the amount of tokens received * (in units of the target token) */ function _doConvert( IReserveToken sourceToken, IReserveToken targetToken, uint256 sourceAmount, address trader, address payable beneficiary ) private returns (uint256) { // update the recent average rate _updateRecentAverageRate(); uint256 sourceId = _reserveIds[sourceToken]; uint256 targetId = _reserveIds[targetToken]; (uint256 sourceBalance, uint256 targetBalance) = _loadReserveBalances(sourceId, targetId); // get the target amount minus the conversion fee and the conversion fee (uint256 targetAmount, uint256 fee) = _targetAmountAndFee( sourceToken, targetToken, sourceBalance, targetBalance, sourceAmount ); // ensure that the trade gives something in return require(targetAmount != 0, "ERR_ZERO_TARGET_AMOUNT"); // ensure that the trade won't deplete the reserve balance assert(targetAmount < targetBalance); // ensure that the input amount was already deposited uint256 actualSourceBalance = sourceToken.balanceOf(address(this)); if (sourceToken.isNativeToken()) { require(msg.value == sourceAmount, "ERR_ETH_AMOUNT_MISMATCH"); } else { require(msg.value == 0 && actualSourceBalance.sub(sourceBalance) >= sourceAmount, "ERR_INVALID_AMOUNT"); } // sync the reserve balances _setReserveBalances(sourceId, targetId, actualSourceBalance, targetBalance - targetAmount); // transfer funds to the beneficiary in the to reserve token targetToken.safeTransfer(beneficiary, targetAmount); // dispatch the conversion event _dispatchConversionEvent(sourceToken, targetToken, trader, sourceAmount, targetAmount, fee); // dispatch rate updates _dispatchTokenRateUpdateEvents(sourceToken, targetToken, actualSourceBalance, targetBalance - targetAmount); return targetAmount; } /** * @dev returns the recent average rate of 1 token in the other reserve token units */ function recentAverageRate(IReserveToken token) external view validReserve(token) returns (uint256, uint256) { // get the recent average rate of reserve 0 uint256 rate = _calcRecentAverageRate(_averageRateInfo); uint256 rateN = _decodeAverageRateN(rate); uint256 rateD = _decodeAverageRateD(rate); if (token == _reserveTokens[0]) { return (rateN, rateD); } return (rateD, rateN); } /** * @dev updates the recent average rate if needed */ function _updateRecentAverageRate() private { uint256 averageRateInfo1 = _averageRateInfo; uint256 averageRateInfo2 = _calcRecentAverageRate(averageRateInfo1); if (averageRateInfo1 != averageRateInfo2) { _averageRateInfo = averageRateInfo2; } } /** * @dev returns the recent average rate of 1 reserve token 0 in reserve token 1 units */ function _calcRecentAverageRate(uint256 averageRateInfoData) private view returns (uint256) { // get the previous average rate and its update-time uint256 prevAverageRateT = _decodeAverageRateT(averageRateInfoData); uint256 prevAverageRateN = _decodeAverageRateN(averageRateInfoData); uint256 prevAverageRateD = _decodeAverageRateD(averageRateInfoData); // get the elapsed time since the previous average rate was calculated uint256 currentTime = _time(); uint256 timeElapsed = currentTime.sub(prevAverageRateT); // if the previous average rate was calculated in the current block, the average rate remains unchanged if (timeElapsed == 0) { return averageRateInfoData; } // get the current rate between the reserves (uint256 currentRateD, uint256 currentRateN) = reserveBalances(); // if the previous average rate was calculated a while ago or never, the average rate is equal to the current rate if (timeElapsed >= AVERAGE_RATE_PERIOD || prevAverageRateT == 0) { (currentRateN, currentRateD) = MathEx.reducedRatio(currentRateN, currentRateD, MAX_UINT112); return _encodeAverageRateInfo(currentTime, currentRateN, currentRateD); } uint256 x = prevAverageRateD.mul(currentRateN); uint256 y = prevAverageRateN.mul(currentRateD); // since we know that timeElapsed < AVERAGE_RATE_PERIOD, we can avoid using SafeMath: uint256 newRateN = y.mul(AVERAGE_RATE_PERIOD - timeElapsed).add(x.mul(timeElapsed)); uint256 newRateD = prevAverageRateD.mul(currentRateD).mul(AVERAGE_RATE_PERIOD); (newRateN, newRateD) = MathEx.reducedRatio(newRateN, newRateD, MAX_UINT112); return _encodeAverageRateInfo(currentTime, newRateN, newRateD); } /** * @dev increases the pool's liquidity and mints new shares in the pool to the caller and returns the amount of pool * tokens issued */ function addLiquidity( IReserveToken[] memory reserves, uint256[] memory reserveAmounts, uint256 minReturn ) external payable nonReentrant active returns (uint256) { _verifyLiquidityInput(reserves, reserveAmounts, minReturn); // if one of the reserves is ETH, then verify that the input amount of ETH is equal to the input value of ETH require( (!reserves[0].isNativeToken() || reserveAmounts[0] == msg.value) && (!reserves[1].isNativeToken() || reserveAmounts[1] == msg.value), "ERR_ETH_AMOUNT_MISMATCH" ); // if the input value of ETH is larger than zero, then verify that one of the reserves is ETH if (msg.value > 0) { require(_reserveIds[ReserveToken.NATIVE_TOKEN_ADDRESS] != 0, "ERR_NO_ETH_RESERVE"); } // save a local copy of the pool token IDSToken poolToken = IDSToken(address(_anchor)); // get the total supply uint256 totalSupply = poolToken.totalSupply(); uint256[2] memory prevReserveBalances; uint256[2] memory newReserveBalances; // process the network fees and get the reserve balances (prevReserveBalances[0], prevReserveBalances[1]) = _processNetworkFees(msg.value); uint256 amount; uint256[2] memory newReserveAmounts; // calculate the amount of pool tokens to mint for the caller // and the amount of reserve tokens to transfer from the caller if (totalSupply == 0) { amount = MathEx.geometricMean(reserveAmounts); newReserveAmounts[0] = reserveAmounts[0]; newReserveAmounts[1] = reserveAmounts[1]; } else { (amount, newReserveAmounts) = _addLiquidityAmounts( reserves, reserveAmounts, prevReserveBalances, totalSupply ); } uint256 newPoolTokenSupply = totalSupply.add(amount); for (uint256 i = 0; i < 2; i++) { IReserveToken reserveToken = reserves[i]; uint256 reserveAmount = newReserveAmounts[i]; require(reserveAmount > 0, "ERR_ZERO_TARGET_AMOUNT"); assert(reserveAmount <= reserveAmounts[i]); // transfer each one of the reserve amounts from the user to the pool if (!reserveToken.isNativeToken()) { // ETH has already been transferred as part of the transaction reserveToken.safeTransferFrom(msg.sender, address(this), reserveAmount); } else if (reserveAmounts[i] > reserveAmount) { // transfer the extra amount of ETH back to the user reserveToken.safeTransfer(msg.sender, reserveAmounts[i] - reserveAmount); } // save the new reserve balance newReserveBalances[i] = prevReserveBalances[i].add(reserveAmount); emit LiquidityAdded(msg.sender, reserveToken, reserveAmount, newReserveBalances[i], newPoolTokenSupply); // dispatch the `TokenRateUpdate` event for the pool token emit TokenRateUpdate(address(poolToken), address(reserveToken), newReserveBalances[i], newPoolTokenSupply); } // set the reserve balances _setReserveBalances(1, 2, newReserveBalances[0], newReserveBalances[1]); // set the reserve balances product _reserveBalancesProduct = newReserveBalances[0] * newReserveBalances[1]; // verify that the equivalent amount of tokens is equal to or larger than the user's expectation require(amount >= minReturn, "ERR_RETURN_TOO_LOW"); // issue the tokens to the user poolToken.issue(msg.sender, amount); // return the amount of pool tokens issued return amount; } /** * @dev get the amount of pool tokens to mint for the caller and the amount of reserve tokens to transfer from * the caller */ function _addLiquidityAmounts( IReserveToken[] memory, /* reserves */ uint256[] memory amounts, uint256[2] memory balances, uint256 totalSupply ) private pure returns (uint256, uint256[2] memory) { uint256 index = amounts[0].mul(balances[1]) < amounts[1].mul(balances[0]) ? 0 : 1; uint256 amount = _fundSupplyAmount(totalSupply, balances[index], amounts[index]); uint256[2] memory newAmounts = [ _fundCost(totalSupply, balances[0], amount), _fundCost(totalSupply, balances[1], amount) ]; return (amount, newAmounts); } /** * @dev decreases the pool's liquidity and burns the caller's shares in the pool and returns the amount of each * reserve token granted for the given amount of pool tokens */ function removeLiquidity( uint256 amount, IReserveToken[] memory reserves, uint256[] memory minReturnAmounts ) external nonReentrant active returns (uint256[] memory) { // verify the user input bool inputRearranged = _verifyLiquidityInput(reserves, minReturnAmounts, amount); // save a local copy of the pool token IDSToken poolToken = IDSToken(address(_anchor)); // get the total supply BEFORE destroying the user tokens uint256 totalSupply = poolToken.totalSupply(); // destroy the user tokens poolToken.destroy(msg.sender, amount); uint256 newPoolTokenSupply = totalSupply.sub(amount); uint256[2] memory prevReserveBalances; uint256[2] memory newReserveBalances; // process the network fees and get the reserve balances (prevReserveBalances[0], prevReserveBalances[1]) = _processNetworkFees(0); uint256[] memory reserveAmounts = _removeLiquidityReserveAmounts(amount, totalSupply, prevReserveBalances); for (uint256 i = 0; i < 2; i++) { IReserveToken reserveToken = reserves[i]; uint256 reserveAmount = reserveAmounts[i]; require(reserveAmount >= minReturnAmounts[i], "ERR_ZERO_TARGET_AMOUNT"); // save the new reserve balance newReserveBalances[i] = prevReserveBalances[i].sub(reserveAmount); // transfer each one of the reserve amounts from the pool to the user reserveToken.safeTransfer(msg.sender, reserveAmount); emit LiquidityRemoved(msg.sender, reserveToken, reserveAmount, newReserveBalances[i], newPoolTokenSupply); // dispatch the `TokenRateUpdate` event for the pool token emit TokenRateUpdate(address(poolToken), address(reserveToken), newReserveBalances[i], newPoolTokenSupply); } // set the reserve balances _setReserveBalances(1, 2, newReserveBalances[0], newReserveBalances[1]); // set the reserve balances product _reserveBalancesProduct = newReserveBalances[0] * newReserveBalances[1]; if (inputRearranged) { uint256 tempReserveAmount = reserveAmounts[0]; reserveAmounts[0] = reserveAmounts[1]; reserveAmounts[1] = tempReserveAmount; } // return the amount of each reserve token granted for the given amount of pool tokens return reserveAmounts; } /** * @dev given the amount of one of the reserve tokens to add liquidity of, returns the required amount of each one * of the other reserve tokens since an empty pool can be funded with any list of non-zero input amounts * * Requirements: * * - this function assumes that the pool is not empty (has already been funded) */ function addLiquidityCost( IReserveToken[] memory reserves, uint256 index, uint256 amount ) external view returns (uint256[] memory) { uint256 totalSupply = IDSToken(address(_anchor)).totalSupply(); uint256[2] memory baseBalances = _baseReserveBalances(reserves); uint256 supplyAmount = _fundSupplyAmount(totalSupply, baseBalances[index], amount); uint256[] memory reserveAmounts = new uint256[](2); reserveAmounts[0] = _fundCost(totalSupply, baseBalances[0], supplyAmount); reserveAmounts[1] = _fundCost(totalSupply, baseBalances[1], supplyAmount); return reserveAmounts; } /** * @dev returns the amount of pool tokens entitled for given amounts of reserve tokens * * Requirements: * * - since an empty pool can be funded with any list of non-zero input amounts, this function assumes that the pool * is not empty (has already been funded) */ function addLiquidityReturn(IReserveToken[] memory reserves, uint256[] memory amounts) external view returns (uint256) { uint256 totalSupply = IDSToken(address(_anchor)).totalSupply(); uint256[2] memory baseBalances = _baseReserveBalances(reserves); (uint256 amount, ) = _addLiquidityAmounts(reserves, amounts, baseBalances, totalSupply); return amount; } /** * @dev returns the amount of each reserve token entitled for a given amount of pool tokens */ function removeLiquidityReturn(uint256 amount, IReserveToken[] memory reserves) external view returns (uint256[] memory) { uint256 totalSupply = IDSToken(address(_anchor)).totalSupply(); uint256[2] memory baseBalances = _baseReserveBalances(reserves); return _removeLiquidityReserveAmounts(amount, totalSupply, baseBalances); } /** * @dev verifies that a given array of tokens is identical to the converter's array of reserve tokens * note that we take this input in order to allow specifying the corresponding reserve amounts in any order and that * this function rearranges the input arrays according to the converter's array of reserve tokens */ function _verifyLiquidityInput( IReserveToken[] memory reserves, uint256[] memory amounts, uint256 amount ) private view returns (bool) { require(_validReserveAmounts(amounts) && amount > 0, "ERR_ZERO_AMOUNT"); uint256 reserve0Id = _reserveIds[reserves[0]]; uint256 reserve1Id = _reserveIds[reserves[1]]; if (reserve0Id == 2 && reserve1Id == 1) { IReserveToken tempReserveToken = reserves[0]; reserves[0] = reserves[1]; reserves[1] = tempReserveToken; uint256 tempReserveAmount = amounts[0]; amounts[0] = amounts[1]; amounts[1] = tempReserveAmount; return true; } require(reserve0Id == 1 && reserve1Id == 2, "ERR_INVALID_RESERVE"); return false; } /** * @dev checks whether or not both reserve amounts are larger than zero */ function _validReserveAmounts(uint256[] memory amounts) private pure returns (bool) { return amounts[0] > 0 && amounts[1] > 0; } /** * @dev returns the amount of each reserve token entitled for a given amount of pool tokens */ function _removeLiquidityReserveAmounts( uint256 amount, uint256 totalSupply, uint256[2] memory balances ) private pure returns (uint256[] memory) { uint256[] memory reserveAmounts = new uint256[](2); reserveAmounts[0] = _liquidateReserveAmount(totalSupply, balances[0], amount); reserveAmounts[1] = _liquidateReserveAmount(totalSupply, balances[1], amount); return reserveAmounts; } /** * @dev dispatches token rate update events for the reserve tokens and the pool token */ function _dispatchTokenRateUpdateEvents( IReserveToken sourceToken, IReserveToken targetToken, uint256 sourceBalance, uint256 targetBalance ) private { // save a local copy of the pool token IDSToken poolToken = IDSToken(address(_anchor)); // get the total supply of pool tokens uint256 poolTokenSupply = poolToken.totalSupply(); // dispatch token rate update event for the reserve tokens emit TokenRateUpdate(address(sourceToken), address(targetToken), targetBalance, sourceBalance); // dispatch token rate update events for the pool token emit TokenRateUpdate(address(poolToken), address(sourceToken), sourceBalance, poolTokenSupply); emit TokenRateUpdate(address(poolToken), address(targetToken), targetBalance, poolTokenSupply); } function _encodeReserveBalance(uint256 balance, uint256 id) private pure returns (uint256) { assert(balance <= MAX_UINT128 && (id == 1 || id == 2)); return balance << ((id - 1) * 128); } function _decodeReserveBalance(uint256 balances, uint256 id) private pure returns (uint256) { assert(id == 1 || id == 2); return (balances >> ((id - 1) * 128)) & MAX_UINT128; } function _encodeReserveBalances( uint256 balance0, uint256 id0, uint256 balance1, uint256 id1 ) private pure returns (uint256) { return _encodeReserveBalance(balance0, id0) | _encodeReserveBalance(balance1, id1); } function _decodeReserveBalances( uint256 balances, uint256 id0, uint256 id1 ) private pure returns (uint256, uint256) { return (_decodeReserveBalance(balances, id0), _decodeReserveBalance(balances, id1)); } function _encodeAverageRateInfo( uint256 averageRateT, uint256 averageRateN, uint256 averageRateD ) private pure returns (uint256) { assert(averageRateT <= MAX_UINT32 && averageRateN <= MAX_UINT112 && averageRateD <= MAX_UINT112); return (averageRateT << 224) | (averageRateN << 112) | averageRateD; } function _decodeAverageRateT(uint256 averageRateInfoData) private pure returns (uint256) { return averageRateInfoData >> 224; } function _decodeAverageRateN(uint256 averageRateInfoData) private pure returns (uint256) { return (averageRateInfoData >> 112) & MAX_UINT112; } function _decodeAverageRateD(uint256 averageRateInfoData) private pure returns (uint256) { return averageRateInfoData & MAX_UINT112; } /** * @dev returns the largest integer smaller than or equal to the square root of a given value */ function _floorSqrt(uint256 x) private pure returns (uint256) { return x > 0 ? MathEx.floorSqrt(x) : 0; } function _crossReserveTargetAmount( uint256 sourceReserveBalance, uint256 targetReserveBalance, uint256 sourceAmount ) private pure returns (uint256) { require(sourceReserveBalance > 0 && targetReserveBalance > 0, "ERR_INVALID_RESERVE_BALANCE"); return targetReserveBalance.mul(sourceAmount) / sourceReserveBalance.add(sourceAmount); } function _crossReserveSourceAmount( uint256 sourceReserveBalance, uint256 targetReserveBalance, uint256 targetAmount ) private pure returns (uint256) { require(sourceReserveBalance > 0, "ERR_INVALID_RESERVE_BALANCE"); require(targetAmount < targetReserveBalance, "ERR_INVALID_AMOUNT"); if (targetAmount == 0) { return 0; } return (sourceReserveBalance.mul(targetAmount) - 1) / (targetReserveBalance - targetAmount) + 1; } function _fundCost( uint256 supply, uint256 balance, uint256 amount ) private pure returns (uint256) { require(supply > 0, "ERR_INVALID_SUPPLY"); require(balance > 0, "ERR_INVALID_RESERVE_BALANCE"); // special case for 0 amount if (amount == 0) { return 0; } return (amount.mul(balance) - 1) / supply + 1; } function _fundSupplyAmount( uint256 supply, uint256 balance, uint256 amount ) private pure returns (uint256) { require(supply > 0, "ERR_INVALID_SUPPLY"); require(balance > 0, "ERR_INVALID_RESERVE_BALANCE"); // special case for 0 amount if (amount == 0) { return 0; } return amount.mul(supply) / balance; } function _liquidateReserveAmount( uint256 supply, uint256 balance, uint256 amount ) private pure returns (uint256) { require(supply > 0, "ERR_INVALID_SUPPLY"); require(balance > 0, "ERR_INVALID_RESERVE_BALANCE"); require(amount <= supply, "ERR_INVALID_AMOUNT"); // special case for 0 amount if (amount == 0) { return 0; } // special case for liquidating the entire supply if (amount == supply) { return balance; } return amount.mul(balance) / supply; } /** * @dev returns the network wallet and fees */ function _networkWalletAndFees(uint256 reserveBalance0, uint256 reserveBalance1) private view returns ( ITokenHolder, uint256, uint256 ) { uint256 prevPoint = _floorSqrt(_reserveBalancesProduct); uint256 currPoint = _floorSqrt(reserveBalance0 * reserveBalance1); if (prevPoint >= currPoint) { return (ITokenHolder(address(0)), 0, 0); } (ITokenHolder networkFeeWallet, uint32 networkFee) = INetworkSettings(_addressOf(NETWORK_SETTINGS)) .networkFeeParams(); uint256 n = (currPoint - prevPoint) * networkFee; uint256 d = currPoint * PPM_RESOLUTION; return (networkFeeWallet, reserveBalance0.mul(n).div(d), reserveBalance1.mul(n).div(d)); } /** * @dev deprecated since version 28, backward compatibility - use only for earlier versions */ function token() external view override returns (IConverterAnchor) { return _anchor; } /** * @dev deprecated, backward compatibility */ function transferTokenOwnership(address newOwner) external override ownerOnly { transferAnchorOwnership(newOwner); } /** * @dev deprecated, backward compatibility */ function acceptTokenOwnership() public override ownerOnly { acceptAnchorOwnership(); } /** * @dev deprecated, backward compatibility */ function connectors(IReserveToken reserveToken) external view override returns ( uint256, uint32, bool, bool, bool ) { uint256 reserveId = _reserveIds[reserveToken]; if (reserveId != 0) { return (_reserveBalance(reserveId), PPM_RESOLUTION / 2, false, false, true); } return (0, 0, false, false, false); } /** * @dev deprecated, backward compatibility */ function connectorTokens(uint256 index) external view override returns (IReserveToken) { return _reserveTokens[index]; } /** * @dev deprecated, backward compatibility */ function connectorTokenCount() external view override returns (uint16) { return reserveTokenCount(); } /** * @dev deprecated, backward compatibility */ function getConnectorBalance(IReserveToken reserveToken) external view override returns (uint256) { return reserveBalance(reserveToken); } /** * @dev deprecated, backward compatibility */ function getReturn( IReserveToken sourceToken, IReserveToken targetToken, uint256 sourceAmount ) external view returns (uint256, uint256) { return targetAmountAndFee(sourceToken, targetToken, sourceAmount); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract IConverterAnchor","name":"anchor","type":"address"},{"internalType":"contract IContractRegistry","name":"registry","type":"address"},{"internalType":"uint32","name":"maxConversionFee","type":"uint32"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint16","name":"converterType","type":"uint16"},{"indexed":true,"internalType":"contract IConverterAnchor","name":"anchor","type":"address"},{"indexed":true,"internalType":"bool","name":"activated","type":"bool"}],"name":"Activation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IReserveToken","name":"sourceToken","type":"address"},{"indexed":true,"internalType":"contract IReserveToken","name":"targetToken","type":"address"},{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":false,"internalType":"uint256","name":"sourceAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"targetAmount","type":"uint256"},{"indexed":false,"internalType":"int256","name":"conversionFee","type":"int256"}],"name":"Conversion","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"prevFee","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"newFee","type":"uint32"}],"name":"ConversionFeeUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"provider","type":"address"},{"indexed":true,"internalType":"contract IReserveToken","name":"reserveToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newSupply","type":"uint256"}],"name":"LiquidityAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"provider","type":"address"},{"indexed":true,"internalType":"contract IReserveToken","name":"reserveToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newSupply","type":"uint256"}],"name":"LiquidityRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"prevOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token1","type":"address"},{"indexed":true,"internalType":"address","name":"token2","type":"address"},{"indexed":false,"internalType":"uint256","name":"rateN","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rateD","type":"uint256"}],"name":"TokenRateUpdate","type":"event"},{"inputs":[],"name":"acceptAnchorOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"acceptTokenOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IReserveToken[]","name":"reserves","type":"address[]"},{"internalType":"uint256[]","name":"reserveAmounts","type":"uint256[]"},{"internalType":"uint256","name":"minReturn","type":"uint256"}],"name":"addLiquidity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract IReserveToken[]","name":"reserves","type":"address[]"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"addLiquidityCost","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IReserveToken[]","name":"reserves","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"addLiquidityReturn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IReserveToken","name":"token","type":"address"},{"internalType":"uint32","name":"weight","type":"uint32"}],"name":"addReserve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"anchor","outputs":[{"internalType":"contract IConverterAnchor","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"averageRateInfo","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"connectorTokenCount","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"connectorTokens","outputs":[{"internalType":"contract IReserveToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IReserveToken","name":"reserveToken","type":"address"}],"name":"connectors","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"bool","name":"","type":"bool"},{"internalType":"bool","name":"","type":"bool"},{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"conversionFee","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IReserveToken","name":"sourceToken","type":"address"},{"internalType":"contract IReserveToken","name":"targetToken","type":"address"},{"internalType":"uint256","name":"sourceAmount","type":"uint256"},{"internalType":"address","name":"trader","type":"address"},{"internalType":"address payable","name":"beneficiary","type":"address"}],"name":"convert","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"converterType","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"contract IReserveToken","name":"reserveToken","type":"address"}],"name":"getConnectorBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IReserveToken","name":"sourceToken","type":"address"},{"internalType":"contract IReserveToken","name":"targetToken","type":"address"},{"internalType":"uint256","name":"sourceAmount","type":"uint256"}],"name":"getReturn","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isV28OrHigher","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"maxConversionFee","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"newOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"onUpgradeComplete","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"onlyOwnerCanUpdateRegistry","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"prevRegistry","outputs":[{"internalType":"contract IContractRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"processNetworkFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IReserveToken","name":"token","type":"address"}],"name":"recentAverageRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registry","outputs":[{"internalType":"contract IContractRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"contract IReserveToken[]","name":"reserves","type":"address[]"},{"internalType":"uint256[]","name":"minReturnAmounts","type":"uint256[]"}],"name":"removeLiquidity","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"contract IReserveToken[]","name":"reserves","type":"address[]"}],"name":"removeLiquidityReturn","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IReserveToken","name":"reserveToken","type":"address"}],"name":"reserveBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reserveBalances","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reserveTokenCount","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reserveTokens","outputs":[{"internalType":"contract IReserveToken[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IReserveToken","name":"reserveToken","type":"address"}],"name":"reserveWeight","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"restoreRegistry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"restrictOwnerOnly","type":"bool"}],"name":"restrictRegistryUpdate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"fee","type":"uint32"}],"name":"setConversionFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IReserveToken","name":"sourceToken","type":"address"},{"internalType":"contract IReserveToken","name":"targetToken","type":"address"},{"internalType":"uint256","name":"targetAmount","type":"uint256"}],"name":"sourceAmountAndFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"syncReserveBalances","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IReserveToken","name":"sourceToken","type":"address"},{"internalType":"contract IReserveToken","name":"targetToken","type":"address"},{"internalType":"uint256","name":"sourceAmount","type":"uint256"}],"name":"targetAmountAndFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract IConverterAnchor","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferAnchorOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newConverter","type":"address"}],"name":"transferReservesOnUpgrade","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferTokenOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateRegistry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"upgrade","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60806040523480156200001157600080fd5b5060405162004d7338038062004d73833981810160405260608110156200003757600080fd5b5080516020820151604090920151600080546001600160a01b0319163317905590919081806200006781620000f6565b50600280546001600160a01b039092166001600160a01b0319928316811790915560038054909216179055600160045582620000a381620000f6565b81620000af8162000155565b50506009805463ffffffff909216600160a01b0263ffffffff60a01b196001600160a01b039095166001600160a01b031990931692909217939093161790915550620001b4565b6001600160a01b03811662000152576040805162461bcd60e51b815260206004820152601360248201527f4552525f494e56414c49445f4144445245535300000000000000000000000000604482015290519081900360640190fd5b50565b620f424063ffffffff8216111562000152576040805162461bcd60e51b815260206004820152601a60248201527f4552525f494e56414c49445f434f4e56455253494f4e5f464545000000000000604482015290519081900360640190fd5b614baf80620001c46000396000f3fe6080604052600436106102b25760003560e01c80636a49d2c411610175578063bbcdfdef116100dc578063d895951211610095578063ecbca55d1161006f578063ecbca55d14610e2b578063f0413a1f14610e5b578063f2fde38b14610e70578063fc0c546a14610d40576102d8565b8063d895951214610d7f578063dc8de37914610db2578063e8dc12ff14610de5576102d8565b8063bbcdfdef14610cd3578063cdc91c6914610d16578063d260529c14610d2b578063d3fb73b414610d40578063d4ee1d9014610d55578063d55ec69714610d6a576102d8565b80638da5cb5b1161012e5780638da5cb5b14610b0557806394c275ad14610b1a5780639b99a8e214610b2f578063af94b8d814610b44578063b127c0a514610b87578063b4a176d314610cbe576102d8565b80636a49d2c4146108af57806371f52bf3146108ee57806379ba5097146109035780637b103999146109185780637d8916bd1461092d57806380d9416d14610a52576102d8565b80632e9abc7a1161021957806350dc78f9116101d257806350dc78f91461081357806354fd4d5014610828578063579cd3ca1461083d578063613e53a71461085257806361cd756e1461086757806367b6d57c1461087c576102d8565b80632e9abc7a146106515780632fe8a6ad1461079357806338a5e016146107a85780633cf98fa4146107bd5780633e8ff43f146107d257806349d10b64146107fe576102d8565b80631cfab2901161026b5780631cfab290146105055780631e1401f8146105515780631f0181bc146105ad57806321e6b53d146105e057806322f3e2d41461061357806327ac36c41461063c576102d8565b8063024c7ec7146102dd578063038d09e11461030b5780630e53aae91461033e57806312b6705f146103a557806315458837146103ba57806319b64015146104bf576102d8565b366102d85773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6102d581610ea3565b50005b600080fd5b3480156102e957600080fd5b506103096004803603602081101561030057600080fd5b50351515610f06565b005b34801561031757600080fd5b506103096004803603602081101561032e57600080fd5b50356001600160a01b0316610f2c565b34801561034a57600080fd5b506103716004803603602081101561036157600080fd5b50356001600160a01b0316611013565b6040805195865263ffffffff9094166020860152911515848401521515606084015215156080830152519081900360a00190f35b3480156103b157600080fd5b5061030961107a565b3480156103c657600080fd5b5061046f600480360360408110156103dd57600080fd5b81359190810190604081016020820135600160201b8111156103fe57600080fd5b82018360208201111561041057600080fd5b803590602001918460208302840111600160201b8311171561043157600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506110de945050505050565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156104ab578181015183820152602001610493565b505050509050019250505060405180910390f35b3480156104cb57600080fd5b506104e9600480360360208110156104e257600080fd5b5035611187565b604080516001600160a01b039092168252519081900360200190f35b34801561051157600080fd5b506105386004803603602081101561052857600080fd5b50356001600160a01b03166111b3565b6040805163ffffffff9092168252519081900360200190f35b34801561055d57600080fd5b506105946004803603606081101561057457600080fd5b506001600160a01b038135811691602081013590911690604001356111ca565b6040805192835260208301919091528051918290030190f35b3480156105b957600080fd5b50610594600480360360208110156105d057600080fd5b50356001600160a01b03166111e5565b3480156105ec57600080fd5b506103096004803603602081101561060357600080fd5b50356001600160a01b0316611260565b34801561061f57600080fd5b50610628611271565b604080519115158252519081900360200190f35b34801561064857600080fd5b5061046f611306565b34801561065d57600080fd5b506107816004803603604081101561067457600080fd5b810190602081018135600160201b81111561068e57600080fd5b8201836020820111156106a057600080fd5b803590602001918460208302840111600160201b831117156106c157600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561071057600080fd5b82018360208201111561072257600080fd5b803590602001918460208302840111600160201b8311171561074357600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611368945050505050565b60408051918252519081900360200190f35b34801561079f57600080fd5b50610628611413565b3480156107b457600080fd5b50610309611423565b3480156107c957600080fd5b50610309611435565b3480156107de57600080fd5b506107e761143f565b6040805161ffff9092168252519081900360200190f35b34801561080a57600080fd5b50610309611444565b34801561081f57600080fd5b5061030961165a565b34801561083457600080fd5b506107e76116ee565b34801561084957600080fd5b506105386116f3565b34801561085e57600080fd5b50610594611706565b34801561087357600080fd5b506104e961171d565b34801561088857600080fd5b506103096004803603602081101561089f57600080fd5b50356001600160a01b031661172c565b3480156108bb57600080fd5b50610309600480360360408110156108d257600080fd5b5080356001600160a01b0316906020013563ffffffff166117c2565b3480156108fa57600080fd5b506107e761191f565b34801561090f57600080fd5b5061030961192e565b34801561092457600080fd5b506104e96119e5565b6107816004803603606081101561094357600080fd5b810190602081018135600160201b81111561095d57600080fd5b82018360208201111561096f57600080fd5b803590602001918460208302840111600160201b8311171561099057600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b8111156109df57600080fd5b8201836020820111156109f157600080fd5b803590602001918460208302840111600160201b83111715610a1257600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092955050913592506119f4915050565b348015610a5e57600080fd5b5061046f60048036036060811015610a7557600080fd5b810190602081018135600160201b811115610a8f57600080fd5b820183602082011115610aa157600080fd5b803590602001918460208302840111600160201b83111715610ac257600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295505082359350505060200135611fbd565b348015610b1157600080fd5b506104e96120ed565b348015610b2657600080fd5b506105386120fc565b348015610b3b57600080fd5b506107e761210f565b348015610b5057600080fd5b5061059460048036036060811015610b6757600080fd5b506001600160a01b03813581169160208101359091169060400135612115565b348015610b9357600080fd5b5061046f60048036036060811015610baa57600080fd5b81359190810190604081016020820135600160201b811115610bcb57600080fd5b820183602082011115610bdd57600080fd5b803590602001918460208302840111600160201b83111715610bfe57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b811115610c4d57600080fd5b820183602082011115610c5f57600080fd5b803590602001918460208302840111600160201b83111715610c8057600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550612170945050505050565b348015610cca57600080fd5b50610309612537565b348015610cdf57600080fd5b5061059460048036036060811015610cf657600080fd5b506001600160a01b03813581169160208101359091169060400135612563565b348015610d2257600080fd5b506103096125d5565b348015610d3757600080fd5b506106286126eb565b348015610d4c57600080fd5b506104e96126f0565b348015610d6157600080fd5b506104e96126ff565b348015610d7657600080fd5b5061030961270e565b348015610d8b57600080fd5b5061078160048036036020811015610da257600080fd5b50356001600160a01b03166127f6565b348015610dbe57600080fd5b5061078160048036036020811015610dd557600080fd5b50356001600160a01b03166127fd565b610781600480360360a0811015610dfb57600080fd5b506001600160a01b0381358116916020810135821691604082013591606081013582169160809091013516612867565b348015610e3757600080fd5b5061030960048036036020811015610e4e57600080fd5b503563ffffffff1661294b565b348015610e6757600080fd5b50610781612a2d565b348015610e7c57600080fd5b5061030960048036036020811015610e9357600080fd5b50356001600160a01b0316612a33565b6001600160a01b038116600090815260086020526040902054610f03576040805162461bcd60e51b81526020600482015260136024820152724552525f494e56414c49445f5245534552564560681b604482015290519081900360640190fd5b50565b610f0e612ab1565b60038054911515600160a01b0260ff60a01b19909216919091179055565b60026004541415610f72576040805162461bcd60e51b815260206004820152601f6024820152600080516020614a6f833981519152604482015290519081900360640190fd5b6002600455610f7f612ab1565b762130b731b7b921b7b73b32b93a32b92ab833b930b232b960491b610fa381612b04565b60075460005b8181101561100857600060078281548110610fc057fe5b6000918252602090912001546001600160a01b03169050610ff685610fe58330612b66565b6001600160a01b0384169190612c0f565b610fff81612c86565b50600101610fa9565b505060016004555050565b6001600160a01b0381166000908152600860205260408120548190819081908190801561105d5761104381612cb9565b95506207a120945060009350839250600191506110719050565b600080600080600095509550955095509550505b91939590929450565b600260045414156110c0576040805162461bcd60e51b815260206004820152601f6024820152600080516020614a6f833981519152604482015290519081900360640190fd5b60026004556000806110d181612cc7565b0260065550506001600455565b60606000600960009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561113057600080fd5b505afa158015611144573d6000803e3d6000fd5b505050506040513d602081101561115a57600080fd5b50519050611166614a50565b61116f84612dd9565b905061117c858383612ea0565b925050505b92915050565b60006007828154811061119657fe5b6000918252602090912001546001600160a01b031690505b919050565b6000816111bf81610ea3565b506207a12092915050565b6000806111d8858585612115565b915091505b935093915050565b600080826111f281610ea3565b60006111ff600a54612f1b565b9050600061120c82613050565b905060006112198361305f565b9050600760008154811061122957fe5b6000918252602090912001546001600160a01b038881169116141561125457909450925061125a9050565b94509250505b50915091565b611268612ab1565b610f038161172c565b6000306001600160a01b0316600960009054906101000a90046001600160a01b03166001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156112cb57600080fd5b505afa1580156112df573d6000803e3d6000fd5b505050506040513d60208110156112f557600080fd5b50516001600160a01b031614905090565b6060600780548060200260200160405190810160405280929190818152602001828054801561135e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611340575b5050505050905090565b600080600960009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156113b957600080fd5b505afa1580156113cd573d6000803e3d6000fd5b505050506040513d60208110156113e357600080fd5b505190506113ef614a50565b6113f885612dd9565b905060006114088686848661306b565b509695505050505050565b600354600160a01b900460ff1690565b61142b612ab1565b6114336125d5565b565b611433600061314b565b600390565b61144c6120ed565b6001600160a01b0316336001600160a01b031614806114755750600354600160a01b900460ff16155b6114ba576040805162461bcd60e51b815260206004820152601160248201527011549497d050d0d154d4d7d11153925151607a1b604482015290519081900360640190fd5b60006114d86f436f6e7472616374526567697374727960801b613215565b6002549091506001600160a01b0380831691161480159061150157506001600160a01b03811615155b611549576040805162461bcd60e51b81526020600482015260146024820152734552525f494e56414c49445f524547495354525960601b604482015290519081900360640190fd5b60006001600160a01b0316816001600160a01b031663bb34534c6f436f6e7472616374526567697374727960801b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156115ab57600080fd5b505afa1580156115bf573d6000803e3d6000fd5b505050506040513d60208110156115d557600080fd5b50516001600160a01b0316141561162a576040805162461bcd60e51b81526020600482015260146024820152734552525f494e56414c49445f524547495354525960601b604482015290519081900360640190fd5b60028054600380546001600160a01b038084166001600160a01b0319928316179092559091169216919091179055565b600260045414156116a0576040805162461bcd60e51b815260206004820152601f6024820152600080516020614a6f833981519152604482015290519081900360640190fd5b60026004556116ad612ab1565b762130b731b7b921b7b73b32b93a32b92ab833b930b232b960491b6116d181612b04565b6000806116e060016002613293565b026006555050600160045550565b603081565b600954600160c01b900463ffffffff1690565b60008061171560016002613293565b915091509091565b6003546001600160a01b031690565b611734612ab1565b762130b731b7b921b7b73b32b93a32b92ab833b930b232b960491b61175881612b04565b6009546040805163f2fde38b60e01b81526001600160a01b0385811660048301529151919092169163f2fde38b91602480830192600092919082900301818387803b1580156117a657600080fd5b505af11580156117ba573d6000803e3d6000fd5b505050505050565b6117ca612ab1565b6117d261331c565b816117dc81613363565b816117e6816133d5565b6009546001600160a01b0385811691161480159061181a57506001600160a01b038416600090815260086020526040902054155b611861576040805162461bcd60e51b81526020600482015260136024820152724552525f494e56414c49445f5245534552564560681b604482015290519081900360640190fd5b600261186b61210f565b61ffff16106118bd576040805162461bcd60e51b815260206004820152601960248201527811549497d253959053125117d49154d154959157d0d3d55395603a1b604482015290519081900360640190fd5b5050600780546001810182557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6880180546001600160a01b039094166001600160a01b031990941684179055546000928352600860205260409092209190915550565b600061192961210f565b905090565b6001546001600160a01b03163314611981576040805162461bcd60e51b815260206004820152601160248201527011549497d050d0d154d4d7d11153925151607a1b604482015290519081900360640190fd5b600154600080546040516001600160a01b0393841693909116917f343765429aea5a34b3ff6a3785a98a5abb2597aca87bfbb58632c173d585373a91a360018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b6002546001600160a01b031690565b600060026004541415611a3c576040805162461bcd60e51b815260206004820152601f6024820152600080516020614a6f833981519152604482015290519081900360640190fd5b6002600455611a49613432565b611a5484848461347a565b50611a7b84600081518110611a6557fe5b60200260200101516001600160a01b03166136bf565b1580611a9a57503483600081518110611a9057fe5b6020026020010151145b8015611ad05750611ab184600181518110611a6557fe5b1580611ad057503483600181518110611ac657fe5b6020026020010151145b611b1b576040805162461bcd60e51b815260206004820152601760248201527608aa4a4be8aa890be829a9eaa9ca8be9a92a69a82a8869604b1b604482015290519081900360640190fd5b3415611ba65773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee60005260086020527f353c2eb9e53a4a4a6d45d72082ff2e9dc829d1125618772a83eb0e7f86632c4254611ba6576040805162461bcd60e51b81526020600482015260126024820152714552525f4e4f5f4554485f5245534552564560701b604482015290519081900360640190fd5b600954604080516318160ddd60e01b815290516001600160a01b039092169160009183916318160ddd91600480820192602092909190829003018186803b158015611bf057600080fd5b505afa158015611c04573d6000803e3d6000fd5b505050506040513d6020811015611c1a57600080fd5b50519050611c26614a50565b611c2e614a50565b611c3734612cc7565b602084015282526000611c48614a50565b84611cad57611c56896136e4565b915088600081518110611c6557fe5b602002602001015181600060028110611c7a57fe5b6020020152885189906001908110611c8e57fe5b602002602001015181600160028110611ca357fe5b6020020152611cbf565b611cb98a8a868861306b565b90925090505b6000611ccb8684613736565b905060005b6002811015611ed45760008c8281518110611ce757fe5b602002602001015190506000848360028110611cff57fe5b6020020151905060008111611d54576040805162461bcd60e51b815260206004820152601660248201527511549497d6915493d7d5105491d15517d05353d5539560521b604482015290519081900360640190fd5b8c8381518110611d6057fe5b6020026020010151811115611d7157fe5b611d83826001600160a01b03166136bf565b611da157611d9c6001600160a01b038316333084613790565b611def565b808d8481518110611dae57fe5b60200260200101511115611def57611def33828f8681518110611dcd57fe5b602002602001015103846001600160a01b0316612c0f9092919063ffffffff16565b611e0a81898560028110611dff57fe5b602002015190613736565b878460028110611e1657fe5b60200201526001600160a01b038216337f4a1a2a6176e9646d9e3157f7c2ab3c499f18337c0b0828cfb28e0a61de4a11f7838a8760028110611e5457fe5b602090810291909101516040805193845291830152818101899052519081900360600190a3816001600160a01b03168a6001600160a01b0316600080516020614aef833981519152898660028110611ea857fe5b602002015187604051808381526020018281526020019250505060405180910390a35050600101611cd0565b508351611eee9060019060029087835b60200201516137d1565b602084015184510260065588831015611f43576040805162461bcd60e51b81526020600482015260126024820152714552525f52455455524e5f544f4f5f4c4f5760701b604482015290519081900360640190fd5b6040805163219e412d60e21b81523360048201526024810185905290516001600160a01b0389169163867904b491604480830192600092919082900301818387803b158015611f9157600080fd5b505af1158015611fa5573d6000803e3d6000fd5b5050600160045550929b9a5050505050505050505050565b60606000600960009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561200f57600080fd5b505afa158015612023573d6000803e3d6000fd5b505050506040513d602081101561203957600080fd5b50519050612045614a50565b61204e86612dd9565b9050600061206d8383886002811061206257fe5b602002015187613855565b6040805160028082526060808301845293945090916020830190803683370190505090506120a4848460005b60200201518461390b565b816000815181106120b157fe5b60209081029190910101526120c884846001612099565b816001815181106120d557fe5b602090810291909101015293505050505b9392505050565b6000546001600160a01b031690565b600954600160a01b900463ffffffff1690565b60075490565b600080612120613432565b6001600160a01b03808616600090815260086020526040808220549287168252812054908061214f8484613293565b91509150612160898984848b6139c8565b9550955050505050935093915050565b6060600260045414156121b8576040805162461bcd60e51b815260206004820152601f6024820152600080516020614a6f833981519152604482015290519081900360640190fd5b60026004556121c5613432565b60006121d284848761347a565b90506000600960009054906101000a90046001600160a01b031690506000816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561222957600080fd5b505afa15801561223d573d6000803e3d6000fd5b505050506040513d602081101561225357600080fd5b50516040805163a24835d160e01b8152336004820152602481018a905290519192506001600160a01b0384169163a24835d19160448082019260009290919082900301818387803b1580156122a757600080fd5b505af11580156122bb573d6000803e3d6000fd5b5050505060006122d488836139f890919063ffffffff16565b90506122de614a50565b6122e6614a50565b6122f06000612cc7565b6020840152825260606123048b8685612ea0565b905060005b600281101561249c5760008b828151811061232057fe5b60200260200101519050600083838151811061233857fe5b602002602001015190508b838151811061234e57fe5b60200260200101518110156123a3576040805162461bcd60e51b815260206004820152601660248201527511549497d6915493d7d5105491d15517d05353d5539560521b604482015290519081900360640190fd5b6123be818785600281106123b357fe5b6020020151906139f8565b8584600281106123ca57fe5b60200201526123e36001600160a01b0383163383612c0f565b6001600160a01b038216337fbc7d19d505c7ec4db83f3b51f19fb98c4c8a99922e7839d1ee608dfbee29501b8388876002811061241c57fe5b6020908102919091015160408051938452918301528181018c9052519081900360600190a3816001600160a01b0316896001600160a01b0316600080516020614aef83398151915287866002811061247057fe5b60200201518a604051808381526020018281526020019250505060405180910390a35050600101612309565b5081516124b0906001906002908583611ee4565b60208201518251026006558615612524576000816000815181106124d057fe5b60200260200101519050816001815181106124e757fe5b6020026020010151826000815181106124fc57fe5b602002602001018181525050808260018151811061251657fe5b602002602001018181525050505b60016004559a9950505050505050505050565b61253f612ab1565b600354600280546001600160a01b0319166001600160a01b03909216919091179055565b60008061256e613432565b6001600160a01b03808616600090815260086020526040808220549287168252812054908061259d8484613293565b9150915060006125ac88613a55565b905060006125c484846125bf8c86613736565b613a8a565b9b919a509098505050505050505050565b6125dd612ab1565b600754600214612630576040805162461bcd60e51b815260206004820152601960248201527811549497d253959053125117d49154d154959157d0d3d55395603a1b604482015290519081900360640190fd5b600960009054906101000a90046001600160a01b03166001600160a01b03166379ba50976040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561268057600080fd5b505af1158015612694573d6000803e3d6000fd5b505050506126a2600061314b565b6009546001906001600160a01b03166126b961143f565b61ffff167f6b08c2e2c9969e55a647a764db9b554d64dc42f1a704da11a6d5b129ad163f2c60405160405180910390a4565b600190565b6009546001600160a01b031690565b6001546001600160a01b031690565b612716612ab1565b600061273b762130b731b7b921b7b73b32b93a32b92ab833b930b232b960491b613215565b6009549091506000906001600160a01b031661275561143f565b61ffff167f6b08c2e2c9969e55a647a764db9b554d64dc42f1a704da11a6d5b129ad163f2c60405160405180910390a461278e81612a33565b6040805163487ac64b60e11b81526030600482015290516001600160a01b038316916390f58c9691602480830192600092919082900301818387803b1580156127d657600080fd5b505af11580156127ea573d6000803e3d6000fd5b50505050610f0361192e565b6000611181825b6001600160a01b0381166000908152600860205260408120548061285e576040805162461bcd60e51b81526020600482015260136024820152724552525f494e56414c49445f5245534552564560681b604482015290519081900360640190fd5b6120e681612cb9565b6000600260045414156128af576040805162461bcd60e51b815260206004820152601f6024820152600080516020614a6f833981519152604482015290519081900360640190fd5b60026004556c42616e636f724e6574776f726b60981b6128ce81612b04565b856001600160a01b0316876001600160a01b0316141561292e576040805162461bcd60e51b815260206004820152601660248201527511549497d4d0535157d4d3d55490d157d5105491d15560521b604482015290519081900360640190fd5b61293b8787878787613b33565b6001600455979650505050505050565b612953612ab1565b60095463ffffffff600160a01b909104811690821611156129bb576040805162461bcd60e51b815260206004820152601a60248201527f4552525f494e56414c49445f434f4e56455253494f4e5f464545000000000000604482015290519081900360640190fd5b6009546040805163ffffffff600160c01b90930483168152918316602083015280517f81cd2ffb37dd237c0e4e2a3de5265fcf9deb43d3e7801e80db9f1ccfba7ee6009281900390910190a16009805463ffffffff909216600160c01b0263ffffffff60c01b19909216919091179055565b600a5490565b612a3b612ab1565b6000546001600160a01b0382811691161415612a8f576040805162461bcd60e51b815260206004820152600e60248201526d22a9292fa9a0a6a2afa7aba722a960911b604482015290519081900360640190fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314611433576040805162461bcd60e51b815260206004820152601160248201527011549497d050d0d154d4d7d11153925151607a1b604482015290519081900360640190fd5b612b0d81613215565b6001600160a01b0316336001600160a01b031614610f03576040805162461bcd60e51b815260206004820152601160248201527011549497d050d0d154d4d7d11153925151607a1b604482015290519081900360640190fd5b6000612b71836136bf565b15612b8757506001600160a01b03811631611181565b612b9083613d09565b6001600160a01b03166370a08231836040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015612bdc57600080fd5b505afa158015612bf0573d6000803e3d6000fd5b505050506040513d6020811015612c0657600080fd5b50519392505050565b80612c1957612c81565b612c22836136bf565b15612c63576040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015612c5d573d6000803e3d6000fd5b50612c81565b612c818282612c7186613d09565b6001600160a01b03169190613d0c565b505050565b6001600160a01b03811660008181526008602052604090205490612cb5908290612cb09030612b66565b613d5e565b5050565b600061118160055483613de4565b600080612cd38361314b565b600080612ce260016002613293565b915091506000806000612cf58585613e16565b92509250925081850394508084039350612d136001600287876137d1565b612d3e6007600081548110612d2457fe5b6000918252602090912001546001600160a01b03166136bf565b15612d5b57612d566001600160a01b03841683613f2a565b612d8a565b612d8a83836007600081548110612d6e57fe5b6000918252602090912001546001600160a01b03169190612c0f565b612d9b6007600181548110612d2457fe5b15612db857612db36001600160a01b03841682613f2a565b612dcb565b612dcb83826007600181548110612d6e57fe5b509294509092505050915091565b612de1614a50565b60006008600084600081518110612df457fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054905060006008600085600181518110612e3257fe5b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020549050600080612e6a8484613293565b91509150600080612e7b8484613e16565b6040805180820190915291909603815294909303602085015250919695505050505050565b604080516002808252606080830184529283929190602083019080368337019050509050612ed7848460005b60200201518761400f565b81600081518110612ee457fe5b6020908102919091010152612efb84846001612ecc565b81600181518110612f0857fe5b6020908102919091010152949350505050565b600080612f278361410e565b90506000612f3484613050565b90506000612f418561305f565b90506000612f4d614114565b90506000612f5b82866139f8565b905080612f6f5786955050505050506111ae565b600080612f7a611706565b9150915061025883101580612f8d575086155b15612fc157612fa481836001600160701b03614118565b92509050612fb3848284614160565b9750505050505050506111ae565b6000612fcd86836141ab565b90506000612fdb88856141ab565b90506000613001612fec84886141ab565b612ffb846102588a90036141ab565b90613736565b9050600061301b6102586130158b896141ab565b906141ab565b905061302f82826001600160701b03614118565b909250905061303f888383614160565b9d9c50505050505050505050505050565b60701c6001600160701b031690565b6001600160701b031690565b6000613075614a50565b60006130a4858260200201518760018151811061308e57fe5b60200260200101516141ab90919063ffffffff16565b6130bc86600160200201518860008151811061308e57fe5b106130c85760016130cb565b60005b60ff1690506000613100858784600281106130e257fe5b60200201518985815181106130f357fe5b6020026020010151613855565b905061310a614a50565b6040805180820190915280613128888a60005b60200201518661390b565b8152602001613139888a600161311d565b90529199919850909650505050505050565b6000600760008154811061315b57fe5b6000918252602082200154600780546001600160a01b03909216935090600190811061318357fe5b60009182526020822001546001600160a01b0390811692506131a69084166136bf565b6131b15760006131b3565b835b6131c66001600160a01b03851630612b66565b03905060006131dd836001600160a01b03166136bf565b6131e85760006131ea565b845b6131fd6001600160a01b03851630612b66565b03905061320e6001600284846137d1565b5050505050565b60025460408051632ecd14d360e21b81526004810184905290516000926001600160a01b03169163bb34534c916024808301926020929190829003018186803b15801561326157600080fd5b505afa158015613275573d6000803e3d6000fd5b505050506040513d602081101561328b57600080fd5b505192915050565b6000808360011480156132a65750826002145b806132bc57508360021480156132bc5750826001145b613304576040805162461bcd60e51b81526020600482015260146024820152734552525f494e56414c49445f524553455256455360601b604482015290519081900360640190fd5b6133116005548585614204565b915091509250929050565b613324611271565b15611433576040805162461bcd60e51b815260206004820152600a6024820152694552525f41435449564560b01b604482015290519081900360640190fd5b6001600160a01b0381161580159061338457506001600160a01b0381163014155b610f03576040805162461bcd60e51b815260206004820152601c60248201527f4552525f494e56414c49445f45585445524e414c5f4144445245535300000000604482015290519081900360640190fd5b63ffffffff81166207a12014610f03576040805162461bcd60e51b815260206004820152601a60248201527f4552525f494e56414c49445f524553455256455f574549474854000000000000604482015290519081900360640190fd5b61343a611271565b611433576040805162461bcd60e51b815260206004820152600c60248201526b4552525f494e41435449564560a01b604482015290519081900360640190fd5b60006134858361421b565b80156134915750600082115b6134d4576040805162461bcd60e51b815260206004820152600f60248201526e11549497d6915493d7d05353d55395608a1b604482015290519081900360640190fd5b600060086000866000815181106134e757fe5b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205490506000600860008760018151811061352557fe5b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205490508160021480156135605750806001145b1561365c5760008660008151811061357457fe5b602002602001015190508660018151811061358b57fe5b6020026020010151876000815181106135a057fe5b60200260200101906001600160a01b031690816001600160a01b03168152505080876001815181106135ce57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250506000866000815181106135fd57fe5b602002602001015190508660018151811061361457fe5b60200260200101518760008151811061362957fe5b602002602001018181525050808760018151811061364357fe5b60200260200101818152505060019450505050506120e6565b81600114801561366c5750806002145b6136b3576040805162461bcd60e51b81526020600482015260136024820152724552525f494e56414c49445f5245534552564560681b604482015290519081900360640190fd5b50600095945050505050565b6001600160a01b03811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14919050565b80516000908190815b8181101561371d5761371185828151811061370457fe5b602002602001015161425a565b909201916001016136ed565b50600161372a838361427c565b03600a0a949350505050565b6000828201838110156120e6576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b8015806137a157506137a1846136bf565b156137ab576137cb565b6137cb8383836137ba88613d09565b6001600160a01b0316929190614294565b50505050565b6001600160801b0382111580156137ef57506001600160801b038111155b613840576040805162461bcd60e51b815260206004820152601c60248201527f4552525f524553455256455f42414c414e43455f4f564552464c4f5700000000604482015290519081900360640190fd5b61384c828583866142ee565b60055550505050565b60008084116138a0576040805162461bcd60e51b81526020600482015260126024820152714552525f494e56414c49445f535550504c5960701b604482015290519081900360640190fd5b600083116138e3576040805162461bcd60e51b815260206004820152601b6024820152600080516020614b5a833981519152604482015290519081900360640190fd5b816138f0575060006120e6565b826138fb83866141ab565b8161390257fe5b04949350505050565b6000808411613956576040805162461bcd60e51b81526020600482015260126024820152714552525f494e56414c49445f535550504c5960701b604482015290519081900360640190fd5b60008311613999576040805162461bcd60e51b815260206004820152601b6024820152600080516020614b5a833981519152604482015290519081900360640190fd5b816139a6575060006120e6565b8360016139b384866141ab565b03816139bb57fe5b0460010190509392505050565b60008060006139d886868661430e565b905060006139e582614372565b9182900399919850909650505050505050565b600082821115613a4f576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6009546000906111819063ffffffff600160c01b9091048116620f4240819003821691613a849186916141ab16565b906143a7565b6000808411613ace576040805162461bcd60e51b815260206004820152601b6024820152600080516020614b5a833981519152604482015290519081900360640190fd5b828210613b17576040805162461bcd60e51b815260206004820152601260248201527111549497d253959053125117d05353d5539560721b604482015290519081900360640190fd5b81613b24575060006120e6565b81830360016139b386856141ab565b6000613b3d614406565b6001600160a01b038087166000908152600860205260408082205492881682528120549080613b6c8484613293565b91509150600080613b808c8c86868e6139c8565b915091508160001415613bd3576040805162461bcd60e51b815260206004820152601660248201527511549497d6915493d7d5105491d15517d05353d5539560521b604482015290519081900360640190fd5b828210613bdc57fe5b6000613bf16001600160a01b038e1630612b66565b9050613c058d6001600160a01b03166136bf565b15613c5d578a3414613c58576040805162461bcd60e51b815260206004820152601760248201527608aa4a4be8aa890be829a9eaa9ca8be9a92a69a82a8869604b1b604482015290519081900360640190fd5b613cba565b34158015613c7457508a613c7182876139f8565b10155b613cba576040805162461bcd60e51b815260206004820152601260248201527111549497d253959053125117d05353d5539560721b604482015290519081900360640190fd5b613cc88787838688036137d1565b613cdc6001600160a01b038d168a85612c0f565b613cea8d8d8c8e8787614423565b613cf88d8d8386880361447f565b50909b9a5050505050505050505050565b90565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052612c819084906145b8565b6001600160801b03811115613dba576040805162461bcd60e51b815260206004820152601c60248201527f4552525f524553455256455f42414c414e43455f4f564552464c4f5700000000604482015290519081900360640190fd5b6000613dcb60055484600303613de4565b9050613ddc828483866003036142ee565b600555505050565b60008160011480613df55750816002145b613dfb57fe5b50608060001982010282901c6001600160801b031692915050565b600080600080613e27600654614669565b90506000613e36868802614669565b9050808210613e515760008060009450945094505050613f23565b600080613e6f6e4e6574776f726b53657474696e677360881b613215565b6001600160a01b031663e33b5f5f6040518163ffffffff1660e01b8152600401604080518083038186803b158015613ea657600080fd5b505afa158015613eba573d6000803e3d6000fd5b505050506040513d6040811015613ed057600080fd5b508051602090910151909250905063ffffffff8082168585030290620f42408502908490613f08908390613a84908f9087906141ab16565b613f1683613a848e876141ab565b9850985098505050505050505b9250925092565b80471015613f7f576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d8060008114613fca576040519150601f19603f3d011682016040523d82523d6000602084013e613fcf565b606091505b5050905080612c815760405162461bcd60e51b815260040180806020018281038252603a815260200180614a8f603a913960400191505060405180910390fd5b600080841161405a576040805162461bcd60e51b81526020600482015260126024820152714552525f494e56414c49445f535550504c5960701b604482015290519081900360640190fd5b6000831161409d576040805162461bcd60e51b815260206004820152601b6024820152600080516020614b5a833981519152604482015290519081900360640190fd5b838211156140e7576040805162461bcd60e51b815260206004820152601260248201527111549497d253959053125117d05353d5539560721b604482015290519081900360640190fd5b816140f4575060006120e6565b838214156141035750816120e6565b836138fb83856141ab565b60e01c90565b4290565b60008084848482118061412a57508481115b156141405761413a828287614682565b90925090505b8082146141515790925090506111dd565b50600196879650945050505050565b600063ffffffff841115801561417d57506001600160701b038311155b801561419057506001600160701b038211155b61419657fe5b5060e083901b607083901b1781179392505050565b6000826141ba57506000611181565b828202828482816141c757fe5b04146120e65760405162461bcd60e51b8152600401808060200182810382526021815260200180614b0f6021913960400191505060405180910390fd5b6000806142118585613de4565b6111d88685613de4565b6000808260008151811061422b57fe5b6020026020010151118015611181575060008260018151811061424a57fe5b6020026020010151119050919050565b600080825b80156142755760019190910190600a900461425f565b5092915050565b6000816002810484018161428c57fe5b049392505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526137cb9085906145b8565b60006142fa83836146bb565b61430486866146bb565b1795945050505050565b6000808411801561431f5750600083115b61435e576040805162461bcd60e51b815260206004820152601b6024820152600080516020614b5a833981519152604482015290519081900360640190fd5b6143688483613736565b6138fb84846141ab565b600954600090620f424090614399908490600160c01b900463ffffffff908116906141ab16565b816143a057fe5b0492915050565b60008082116143fd576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161428c57fe5b600a54600061441482612f1b565b9050808214612cb557600a5550565b604080518481526020810184905280820183905290516001600160a01b038087169288821692918a16917f276856b36cbc45526a0ba64f44611557a2a8b68662c5388e9fe6d72e86e1c8cb9181900360600190a4505050505050565b600954604080516318160ddd60e01b815290516001600160a01b039092169160009183916318160ddd91600480820192602092909190829003018186803b1580156144c957600080fd5b505afa1580156144dd573d6000803e3d6000fd5b505050506040513d60208110156144f357600080fd5b5051604080518581526020810187905281519293506001600160a01b0380891693908a1692600080516020614aef833981519152928290030190a3856001600160a01b0316826001600160a01b0316600080516020614aef8339815191528684604051808381526020018281526020019250505060405180910390a3846001600160a01b0316826001600160a01b0316600080516020614aef8339815191528584604051808381526020018281526020019250505060405180910390a3505050505050565b606061460d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166146f09092919063ffffffff16565b805190915015612c815780806020019051602081101561462c57600080fd5b5051612c815760405162461bcd60e51b815260040180806020018281038252602a815260200180614b30602a913960400191505060405180910390fd5b6000808211614679576000611181565b61118182614707565b6000808385116146a057614697858585614756565b915091506111dd565b6000806146ae868887614756565b9890975095505050505050565b60006001600160801b0383111580156146de575081600114806146de5750816002145b6146e457fe5b50600019016080021b90565b60606146ff848460008561481a565b949350505050565b6000806002830460010190506000600282858161472057fe5b0483018161472a57fe5b0490505b8082111561427557809150600282858161474457fe5b0483018161474e57fe5b04905061472e565b6000806000836000198161476657fe5b0490508086111561479f57600081600101878161477f57fe5b04600101905080878161478e57fe5b04965080868161479a57fe5b049550505b84861461480a5785840260006147b58888614976565b90508781106147db5760006147ca838361497a565b9550505083850392506111dd915050565b60028888030487038210156147f957600086945094505050506111dd565b6001808703945094505050506111dd565b5050600290910493849350915050565b60608247101561485b5760405162461bcd60e51b8152600401808060200182810382526026815260200180614ac96026913960400191505060405180910390fd5b614864856149a6565b6148b5576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b602083106148f45780518252601f1990920191602091820191016148d5565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114614956576040519150601f19603f3d011682016040523d82523d6000602084013e61495b565b606091505b509150915061496b8282866149ac565b979650505050505050565b0190565b600060028204820382848161498b57fe5b068161499357fe5b0482848161499d57fe5b04019392505050565b3b151590565b606083156149bb5750816120e6565b8251156149cb5782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015614a155781810151838201526020016149fd565b50505050905090810190601f168015614a425780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b6040518060400160405280600290602082028036833750919291505056fe5265656e7472616e637947756172643a207265656e7472616e742063616c6c00416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c77f29993cf2c084e726f7e802da0719d6a0ade3e204badc7a3ffd57ecb768c24536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565644552525f494e56414c49445f524553455256455f42414c414e43450000000000a2646970667358221220842dacb7e388376021cadeda051cec41f1b8c334339cbba7a1be95a5308eee9164736f6c634300060c0033000000000000000000000000b1cd6e4153b2a390cf00a6556b0fc1458c4a553300000000000000000000000052ae12abe5d8bd778bd5397f99ca900624cfadd40000000000000000000000000000000000000000000000000000000000007530
Deployed Bytecode
0x6080604052600436106102b25760003560e01c80636a49d2c411610175578063bbcdfdef116100dc578063d895951211610095578063ecbca55d1161006f578063ecbca55d14610e2b578063f0413a1f14610e5b578063f2fde38b14610e70578063fc0c546a14610d40576102d8565b8063d895951214610d7f578063dc8de37914610db2578063e8dc12ff14610de5576102d8565b8063bbcdfdef14610cd3578063cdc91c6914610d16578063d260529c14610d2b578063d3fb73b414610d40578063d4ee1d9014610d55578063d55ec69714610d6a576102d8565b80638da5cb5b1161012e5780638da5cb5b14610b0557806394c275ad14610b1a5780639b99a8e214610b2f578063af94b8d814610b44578063b127c0a514610b87578063b4a176d314610cbe576102d8565b80636a49d2c4146108af57806371f52bf3146108ee57806379ba5097146109035780637b103999146109185780637d8916bd1461092d57806380d9416d14610a52576102d8565b80632e9abc7a1161021957806350dc78f9116101d257806350dc78f91461081357806354fd4d5014610828578063579cd3ca1461083d578063613e53a71461085257806361cd756e1461086757806367b6d57c1461087c576102d8565b80632e9abc7a146106515780632fe8a6ad1461079357806338a5e016146107a85780633cf98fa4146107bd5780633e8ff43f146107d257806349d10b64146107fe576102d8565b80631cfab2901161026b5780631cfab290146105055780631e1401f8146105515780631f0181bc146105ad57806321e6b53d146105e057806322f3e2d41461061357806327ac36c41461063c576102d8565b8063024c7ec7146102dd578063038d09e11461030b5780630e53aae91461033e57806312b6705f146103a557806315458837146103ba57806319b64015146104bf576102d8565b366102d85773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6102d581610ea3565b50005b600080fd5b3480156102e957600080fd5b506103096004803603602081101561030057600080fd5b50351515610f06565b005b34801561031757600080fd5b506103096004803603602081101561032e57600080fd5b50356001600160a01b0316610f2c565b34801561034a57600080fd5b506103716004803603602081101561036157600080fd5b50356001600160a01b0316611013565b6040805195865263ffffffff9094166020860152911515848401521515606084015215156080830152519081900360a00190f35b3480156103b157600080fd5b5061030961107a565b3480156103c657600080fd5b5061046f600480360360408110156103dd57600080fd5b81359190810190604081016020820135600160201b8111156103fe57600080fd5b82018360208201111561041057600080fd5b803590602001918460208302840111600160201b8311171561043157600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506110de945050505050565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156104ab578181015183820152602001610493565b505050509050019250505060405180910390f35b3480156104cb57600080fd5b506104e9600480360360208110156104e257600080fd5b5035611187565b604080516001600160a01b039092168252519081900360200190f35b34801561051157600080fd5b506105386004803603602081101561052857600080fd5b50356001600160a01b03166111b3565b6040805163ffffffff9092168252519081900360200190f35b34801561055d57600080fd5b506105946004803603606081101561057457600080fd5b506001600160a01b038135811691602081013590911690604001356111ca565b6040805192835260208301919091528051918290030190f35b3480156105b957600080fd5b50610594600480360360208110156105d057600080fd5b50356001600160a01b03166111e5565b3480156105ec57600080fd5b506103096004803603602081101561060357600080fd5b50356001600160a01b0316611260565b34801561061f57600080fd5b50610628611271565b604080519115158252519081900360200190f35b34801561064857600080fd5b5061046f611306565b34801561065d57600080fd5b506107816004803603604081101561067457600080fd5b810190602081018135600160201b81111561068e57600080fd5b8201836020820111156106a057600080fd5b803590602001918460208302840111600160201b831117156106c157600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561071057600080fd5b82018360208201111561072257600080fd5b803590602001918460208302840111600160201b8311171561074357600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611368945050505050565b60408051918252519081900360200190f35b34801561079f57600080fd5b50610628611413565b3480156107b457600080fd5b50610309611423565b3480156107c957600080fd5b50610309611435565b3480156107de57600080fd5b506107e761143f565b6040805161ffff9092168252519081900360200190f35b34801561080a57600080fd5b50610309611444565b34801561081f57600080fd5b5061030961165a565b34801561083457600080fd5b506107e76116ee565b34801561084957600080fd5b506105386116f3565b34801561085e57600080fd5b50610594611706565b34801561087357600080fd5b506104e961171d565b34801561088857600080fd5b506103096004803603602081101561089f57600080fd5b50356001600160a01b031661172c565b3480156108bb57600080fd5b50610309600480360360408110156108d257600080fd5b5080356001600160a01b0316906020013563ffffffff166117c2565b3480156108fa57600080fd5b506107e761191f565b34801561090f57600080fd5b5061030961192e565b34801561092457600080fd5b506104e96119e5565b6107816004803603606081101561094357600080fd5b810190602081018135600160201b81111561095d57600080fd5b82018360208201111561096f57600080fd5b803590602001918460208302840111600160201b8311171561099057600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b8111156109df57600080fd5b8201836020820111156109f157600080fd5b803590602001918460208302840111600160201b83111715610a1257600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092955050913592506119f4915050565b348015610a5e57600080fd5b5061046f60048036036060811015610a7557600080fd5b810190602081018135600160201b811115610a8f57600080fd5b820183602082011115610aa157600080fd5b803590602001918460208302840111600160201b83111715610ac257600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295505082359350505060200135611fbd565b348015610b1157600080fd5b506104e96120ed565b348015610b2657600080fd5b506105386120fc565b348015610b3b57600080fd5b506107e761210f565b348015610b5057600080fd5b5061059460048036036060811015610b6757600080fd5b506001600160a01b03813581169160208101359091169060400135612115565b348015610b9357600080fd5b5061046f60048036036060811015610baa57600080fd5b81359190810190604081016020820135600160201b811115610bcb57600080fd5b820183602082011115610bdd57600080fd5b803590602001918460208302840111600160201b83111715610bfe57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b811115610c4d57600080fd5b820183602082011115610c5f57600080fd5b803590602001918460208302840111600160201b83111715610c8057600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550612170945050505050565b348015610cca57600080fd5b50610309612537565b348015610cdf57600080fd5b5061059460048036036060811015610cf657600080fd5b506001600160a01b03813581169160208101359091169060400135612563565b348015610d2257600080fd5b506103096125d5565b348015610d3757600080fd5b506106286126eb565b348015610d4c57600080fd5b506104e96126f0565b348015610d6157600080fd5b506104e96126ff565b348015610d7657600080fd5b5061030961270e565b348015610d8b57600080fd5b5061078160048036036020811015610da257600080fd5b50356001600160a01b03166127f6565b348015610dbe57600080fd5b5061078160048036036020811015610dd557600080fd5b50356001600160a01b03166127fd565b610781600480360360a0811015610dfb57600080fd5b506001600160a01b0381358116916020810135821691604082013591606081013582169160809091013516612867565b348015610e3757600080fd5b5061030960048036036020811015610e4e57600080fd5b503563ffffffff1661294b565b348015610e6757600080fd5b50610781612a2d565b348015610e7c57600080fd5b5061030960048036036020811015610e9357600080fd5b50356001600160a01b0316612a33565b6001600160a01b038116600090815260086020526040902054610f03576040805162461bcd60e51b81526020600482015260136024820152724552525f494e56414c49445f5245534552564560681b604482015290519081900360640190fd5b50565b610f0e612ab1565b60038054911515600160a01b0260ff60a01b19909216919091179055565b60026004541415610f72576040805162461bcd60e51b815260206004820152601f6024820152600080516020614a6f833981519152604482015290519081900360640190fd5b6002600455610f7f612ab1565b762130b731b7b921b7b73b32b93a32b92ab833b930b232b960491b610fa381612b04565b60075460005b8181101561100857600060078281548110610fc057fe5b6000918252602090912001546001600160a01b03169050610ff685610fe58330612b66565b6001600160a01b0384169190612c0f565b610fff81612c86565b50600101610fa9565b505060016004555050565b6001600160a01b0381166000908152600860205260408120548190819081908190801561105d5761104381612cb9565b95506207a120945060009350839250600191506110719050565b600080600080600095509550955095509550505b91939590929450565b600260045414156110c0576040805162461bcd60e51b815260206004820152601f6024820152600080516020614a6f833981519152604482015290519081900360640190fd5b60026004556000806110d181612cc7565b0260065550506001600455565b60606000600960009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561113057600080fd5b505afa158015611144573d6000803e3d6000fd5b505050506040513d602081101561115a57600080fd5b50519050611166614a50565b61116f84612dd9565b905061117c858383612ea0565b925050505b92915050565b60006007828154811061119657fe5b6000918252602090912001546001600160a01b031690505b919050565b6000816111bf81610ea3565b506207a12092915050565b6000806111d8858585612115565b915091505b935093915050565b600080826111f281610ea3565b60006111ff600a54612f1b565b9050600061120c82613050565b905060006112198361305f565b9050600760008154811061122957fe5b6000918252602090912001546001600160a01b038881169116141561125457909450925061125a9050565b94509250505b50915091565b611268612ab1565b610f038161172c565b6000306001600160a01b0316600960009054906101000a90046001600160a01b03166001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156112cb57600080fd5b505afa1580156112df573d6000803e3d6000fd5b505050506040513d60208110156112f557600080fd5b50516001600160a01b031614905090565b6060600780548060200260200160405190810160405280929190818152602001828054801561135e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611340575b5050505050905090565b600080600960009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156113b957600080fd5b505afa1580156113cd573d6000803e3d6000fd5b505050506040513d60208110156113e357600080fd5b505190506113ef614a50565b6113f885612dd9565b905060006114088686848661306b565b509695505050505050565b600354600160a01b900460ff1690565b61142b612ab1565b6114336125d5565b565b611433600061314b565b600390565b61144c6120ed565b6001600160a01b0316336001600160a01b031614806114755750600354600160a01b900460ff16155b6114ba576040805162461bcd60e51b815260206004820152601160248201527011549497d050d0d154d4d7d11153925151607a1b604482015290519081900360640190fd5b60006114d86f436f6e7472616374526567697374727960801b613215565b6002549091506001600160a01b0380831691161480159061150157506001600160a01b03811615155b611549576040805162461bcd60e51b81526020600482015260146024820152734552525f494e56414c49445f524547495354525960601b604482015290519081900360640190fd5b60006001600160a01b0316816001600160a01b031663bb34534c6f436f6e7472616374526567697374727960801b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156115ab57600080fd5b505afa1580156115bf573d6000803e3d6000fd5b505050506040513d60208110156115d557600080fd5b50516001600160a01b0316141561162a576040805162461bcd60e51b81526020600482015260146024820152734552525f494e56414c49445f524547495354525960601b604482015290519081900360640190fd5b60028054600380546001600160a01b038084166001600160a01b0319928316179092559091169216919091179055565b600260045414156116a0576040805162461bcd60e51b815260206004820152601f6024820152600080516020614a6f833981519152604482015290519081900360640190fd5b60026004556116ad612ab1565b762130b731b7b921b7b73b32b93a32b92ab833b930b232b960491b6116d181612b04565b6000806116e060016002613293565b026006555050600160045550565b603081565b600954600160c01b900463ffffffff1690565b60008061171560016002613293565b915091509091565b6003546001600160a01b031690565b611734612ab1565b762130b731b7b921b7b73b32b93a32b92ab833b930b232b960491b61175881612b04565b6009546040805163f2fde38b60e01b81526001600160a01b0385811660048301529151919092169163f2fde38b91602480830192600092919082900301818387803b1580156117a657600080fd5b505af11580156117ba573d6000803e3d6000fd5b505050505050565b6117ca612ab1565b6117d261331c565b816117dc81613363565b816117e6816133d5565b6009546001600160a01b0385811691161480159061181a57506001600160a01b038416600090815260086020526040902054155b611861576040805162461bcd60e51b81526020600482015260136024820152724552525f494e56414c49445f5245534552564560681b604482015290519081900360640190fd5b600261186b61210f565b61ffff16106118bd576040805162461bcd60e51b815260206004820152601960248201527811549497d253959053125117d49154d154959157d0d3d55395603a1b604482015290519081900360640190fd5b5050600780546001810182557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6880180546001600160a01b039094166001600160a01b031990941684179055546000928352600860205260409092209190915550565b600061192961210f565b905090565b6001546001600160a01b03163314611981576040805162461bcd60e51b815260206004820152601160248201527011549497d050d0d154d4d7d11153925151607a1b604482015290519081900360640190fd5b600154600080546040516001600160a01b0393841693909116917f343765429aea5a34b3ff6a3785a98a5abb2597aca87bfbb58632c173d585373a91a360018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b6002546001600160a01b031690565b600060026004541415611a3c576040805162461bcd60e51b815260206004820152601f6024820152600080516020614a6f833981519152604482015290519081900360640190fd5b6002600455611a49613432565b611a5484848461347a565b50611a7b84600081518110611a6557fe5b60200260200101516001600160a01b03166136bf565b1580611a9a57503483600081518110611a9057fe5b6020026020010151145b8015611ad05750611ab184600181518110611a6557fe5b1580611ad057503483600181518110611ac657fe5b6020026020010151145b611b1b576040805162461bcd60e51b815260206004820152601760248201527608aa4a4be8aa890be829a9eaa9ca8be9a92a69a82a8869604b1b604482015290519081900360640190fd5b3415611ba65773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee60005260086020527f353c2eb9e53a4a4a6d45d72082ff2e9dc829d1125618772a83eb0e7f86632c4254611ba6576040805162461bcd60e51b81526020600482015260126024820152714552525f4e4f5f4554485f5245534552564560701b604482015290519081900360640190fd5b600954604080516318160ddd60e01b815290516001600160a01b039092169160009183916318160ddd91600480820192602092909190829003018186803b158015611bf057600080fd5b505afa158015611c04573d6000803e3d6000fd5b505050506040513d6020811015611c1a57600080fd5b50519050611c26614a50565b611c2e614a50565b611c3734612cc7565b602084015282526000611c48614a50565b84611cad57611c56896136e4565b915088600081518110611c6557fe5b602002602001015181600060028110611c7a57fe5b6020020152885189906001908110611c8e57fe5b602002602001015181600160028110611ca357fe5b6020020152611cbf565b611cb98a8a868861306b565b90925090505b6000611ccb8684613736565b905060005b6002811015611ed45760008c8281518110611ce757fe5b602002602001015190506000848360028110611cff57fe5b6020020151905060008111611d54576040805162461bcd60e51b815260206004820152601660248201527511549497d6915493d7d5105491d15517d05353d5539560521b604482015290519081900360640190fd5b8c8381518110611d6057fe5b6020026020010151811115611d7157fe5b611d83826001600160a01b03166136bf565b611da157611d9c6001600160a01b038316333084613790565b611def565b808d8481518110611dae57fe5b60200260200101511115611def57611def33828f8681518110611dcd57fe5b602002602001015103846001600160a01b0316612c0f9092919063ffffffff16565b611e0a81898560028110611dff57fe5b602002015190613736565b878460028110611e1657fe5b60200201526001600160a01b038216337f4a1a2a6176e9646d9e3157f7c2ab3c499f18337c0b0828cfb28e0a61de4a11f7838a8760028110611e5457fe5b602090810291909101516040805193845291830152818101899052519081900360600190a3816001600160a01b03168a6001600160a01b0316600080516020614aef833981519152898660028110611ea857fe5b602002015187604051808381526020018281526020019250505060405180910390a35050600101611cd0565b508351611eee9060019060029087835b60200201516137d1565b602084015184510260065588831015611f43576040805162461bcd60e51b81526020600482015260126024820152714552525f52455455524e5f544f4f5f4c4f5760701b604482015290519081900360640190fd5b6040805163219e412d60e21b81523360048201526024810185905290516001600160a01b0389169163867904b491604480830192600092919082900301818387803b158015611f9157600080fd5b505af1158015611fa5573d6000803e3d6000fd5b5050600160045550929b9a5050505050505050505050565b60606000600960009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561200f57600080fd5b505afa158015612023573d6000803e3d6000fd5b505050506040513d602081101561203957600080fd5b50519050612045614a50565b61204e86612dd9565b9050600061206d8383886002811061206257fe5b602002015187613855565b6040805160028082526060808301845293945090916020830190803683370190505090506120a4848460005b60200201518461390b565b816000815181106120b157fe5b60209081029190910101526120c884846001612099565b816001815181106120d557fe5b602090810291909101015293505050505b9392505050565b6000546001600160a01b031690565b600954600160a01b900463ffffffff1690565b60075490565b600080612120613432565b6001600160a01b03808616600090815260086020526040808220549287168252812054908061214f8484613293565b91509150612160898984848b6139c8565b9550955050505050935093915050565b6060600260045414156121b8576040805162461bcd60e51b815260206004820152601f6024820152600080516020614a6f833981519152604482015290519081900360640190fd5b60026004556121c5613432565b60006121d284848761347a565b90506000600960009054906101000a90046001600160a01b031690506000816001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561222957600080fd5b505afa15801561223d573d6000803e3d6000fd5b505050506040513d602081101561225357600080fd5b50516040805163a24835d160e01b8152336004820152602481018a905290519192506001600160a01b0384169163a24835d19160448082019260009290919082900301818387803b1580156122a757600080fd5b505af11580156122bb573d6000803e3d6000fd5b5050505060006122d488836139f890919063ffffffff16565b90506122de614a50565b6122e6614a50565b6122f06000612cc7565b6020840152825260606123048b8685612ea0565b905060005b600281101561249c5760008b828151811061232057fe5b60200260200101519050600083838151811061233857fe5b602002602001015190508b838151811061234e57fe5b60200260200101518110156123a3576040805162461bcd60e51b815260206004820152601660248201527511549497d6915493d7d5105491d15517d05353d5539560521b604482015290519081900360640190fd5b6123be818785600281106123b357fe5b6020020151906139f8565b8584600281106123ca57fe5b60200201526123e36001600160a01b0383163383612c0f565b6001600160a01b038216337fbc7d19d505c7ec4db83f3b51f19fb98c4c8a99922e7839d1ee608dfbee29501b8388876002811061241c57fe5b6020908102919091015160408051938452918301528181018c9052519081900360600190a3816001600160a01b0316896001600160a01b0316600080516020614aef83398151915287866002811061247057fe5b60200201518a604051808381526020018281526020019250505060405180910390a35050600101612309565b5081516124b0906001906002908583611ee4565b60208201518251026006558615612524576000816000815181106124d057fe5b60200260200101519050816001815181106124e757fe5b6020026020010151826000815181106124fc57fe5b602002602001018181525050808260018151811061251657fe5b602002602001018181525050505b60016004559a9950505050505050505050565b61253f612ab1565b600354600280546001600160a01b0319166001600160a01b03909216919091179055565b60008061256e613432565b6001600160a01b03808616600090815260086020526040808220549287168252812054908061259d8484613293565b9150915060006125ac88613a55565b905060006125c484846125bf8c86613736565b613a8a565b9b919a509098505050505050505050565b6125dd612ab1565b600754600214612630576040805162461bcd60e51b815260206004820152601960248201527811549497d253959053125117d49154d154959157d0d3d55395603a1b604482015290519081900360640190fd5b600960009054906101000a90046001600160a01b03166001600160a01b03166379ba50976040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561268057600080fd5b505af1158015612694573d6000803e3d6000fd5b505050506126a2600061314b565b6009546001906001600160a01b03166126b961143f565b61ffff167f6b08c2e2c9969e55a647a764db9b554d64dc42f1a704da11a6d5b129ad163f2c60405160405180910390a4565b600190565b6009546001600160a01b031690565b6001546001600160a01b031690565b612716612ab1565b600061273b762130b731b7b921b7b73b32b93a32b92ab833b930b232b960491b613215565b6009549091506000906001600160a01b031661275561143f565b61ffff167f6b08c2e2c9969e55a647a764db9b554d64dc42f1a704da11a6d5b129ad163f2c60405160405180910390a461278e81612a33565b6040805163487ac64b60e11b81526030600482015290516001600160a01b038316916390f58c9691602480830192600092919082900301818387803b1580156127d657600080fd5b505af11580156127ea573d6000803e3d6000fd5b50505050610f0361192e565b6000611181825b6001600160a01b0381166000908152600860205260408120548061285e576040805162461bcd60e51b81526020600482015260136024820152724552525f494e56414c49445f5245534552564560681b604482015290519081900360640190fd5b6120e681612cb9565b6000600260045414156128af576040805162461bcd60e51b815260206004820152601f6024820152600080516020614a6f833981519152604482015290519081900360640190fd5b60026004556c42616e636f724e6574776f726b60981b6128ce81612b04565b856001600160a01b0316876001600160a01b0316141561292e576040805162461bcd60e51b815260206004820152601660248201527511549497d4d0535157d4d3d55490d157d5105491d15560521b604482015290519081900360640190fd5b61293b8787878787613b33565b6001600455979650505050505050565b612953612ab1565b60095463ffffffff600160a01b909104811690821611156129bb576040805162461bcd60e51b815260206004820152601a60248201527f4552525f494e56414c49445f434f4e56455253494f4e5f464545000000000000604482015290519081900360640190fd5b6009546040805163ffffffff600160c01b90930483168152918316602083015280517f81cd2ffb37dd237c0e4e2a3de5265fcf9deb43d3e7801e80db9f1ccfba7ee6009281900390910190a16009805463ffffffff909216600160c01b0263ffffffff60c01b19909216919091179055565b600a5490565b612a3b612ab1565b6000546001600160a01b0382811691161415612a8f576040805162461bcd60e51b815260206004820152600e60248201526d22a9292fa9a0a6a2afa7aba722a960911b604482015290519081900360640190fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314611433576040805162461bcd60e51b815260206004820152601160248201527011549497d050d0d154d4d7d11153925151607a1b604482015290519081900360640190fd5b612b0d81613215565b6001600160a01b0316336001600160a01b031614610f03576040805162461bcd60e51b815260206004820152601160248201527011549497d050d0d154d4d7d11153925151607a1b604482015290519081900360640190fd5b6000612b71836136bf565b15612b8757506001600160a01b03811631611181565b612b9083613d09565b6001600160a01b03166370a08231836040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015612bdc57600080fd5b505afa158015612bf0573d6000803e3d6000fd5b505050506040513d6020811015612c0657600080fd5b50519392505050565b80612c1957612c81565b612c22836136bf565b15612c63576040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015612c5d573d6000803e3d6000fd5b50612c81565b612c818282612c7186613d09565b6001600160a01b03169190613d0c565b505050565b6001600160a01b03811660008181526008602052604090205490612cb5908290612cb09030612b66565b613d5e565b5050565b600061118160055483613de4565b600080612cd38361314b565b600080612ce260016002613293565b915091506000806000612cf58585613e16565b92509250925081850394508084039350612d136001600287876137d1565b612d3e6007600081548110612d2457fe5b6000918252602090912001546001600160a01b03166136bf565b15612d5b57612d566001600160a01b03841683613f2a565b612d8a565b612d8a83836007600081548110612d6e57fe5b6000918252602090912001546001600160a01b03169190612c0f565b612d9b6007600181548110612d2457fe5b15612db857612db36001600160a01b03841682613f2a565b612dcb565b612dcb83826007600181548110612d6e57fe5b509294509092505050915091565b612de1614a50565b60006008600084600081518110612df457fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054905060006008600085600181518110612e3257fe5b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020549050600080612e6a8484613293565b91509150600080612e7b8484613e16565b6040805180820190915291909603815294909303602085015250919695505050505050565b604080516002808252606080830184529283929190602083019080368337019050509050612ed7848460005b60200201518761400f565b81600081518110612ee457fe5b6020908102919091010152612efb84846001612ecc565b81600181518110612f0857fe5b6020908102919091010152949350505050565b600080612f278361410e565b90506000612f3484613050565b90506000612f418561305f565b90506000612f4d614114565b90506000612f5b82866139f8565b905080612f6f5786955050505050506111ae565b600080612f7a611706565b9150915061025883101580612f8d575086155b15612fc157612fa481836001600160701b03614118565b92509050612fb3848284614160565b9750505050505050506111ae565b6000612fcd86836141ab565b90506000612fdb88856141ab565b90506000613001612fec84886141ab565b612ffb846102588a90036141ab565b90613736565b9050600061301b6102586130158b896141ab565b906141ab565b905061302f82826001600160701b03614118565b909250905061303f888383614160565b9d9c50505050505050505050505050565b60701c6001600160701b031690565b6001600160701b031690565b6000613075614a50565b60006130a4858260200201518760018151811061308e57fe5b60200260200101516141ab90919063ffffffff16565b6130bc86600160200201518860008151811061308e57fe5b106130c85760016130cb565b60005b60ff1690506000613100858784600281106130e257fe5b60200201518985815181106130f357fe5b6020026020010151613855565b905061310a614a50565b6040805180820190915280613128888a60005b60200201518661390b565b8152602001613139888a600161311d565b90529199919850909650505050505050565b6000600760008154811061315b57fe5b6000918252602082200154600780546001600160a01b03909216935090600190811061318357fe5b60009182526020822001546001600160a01b0390811692506131a69084166136bf565b6131b15760006131b3565b835b6131c66001600160a01b03851630612b66565b03905060006131dd836001600160a01b03166136bf565b6131e85760006131ea565b845b6131fd6001600160a01b03851630612b66565b03905061320e6001600284846137d1565b5050505050565b60025460408051632ecd14d360e21b81526004810184905290516000926001600160a01b03169163bb34534c916024808301926020929190829003018186803b15801561326157600080fd5b505afa158015613275573d6000803e3d6000fd5b505050506040513d602081101561328b57600080fd5b505192915050565b6000808360011480156132a65750826002145b806132bc57508360021480156132bc5750826001145b613304576040805162461bcd60e51b81526020600482015260146024820152734552525f494e56414c49445f524553455256455360601b604482015290519081900360640190fd5b6133116005548585614204565b915091509250929050565b613324611271565b15611433576040805162461bcd60e51b815260206004820152600a6024820152694552525f41435449564560b01b604482015290519081900360640190fd5b6001600160a01b0381161580159061338457506001600160a01b0381163014155b610f03576040805162461bcd60e51b815260206004820152601c60248201527f4552525f494e56414c49445f45585445524e414c5f4144445245535300000000604482015290519081900360640190fd5b63ffffffff81166207a12014610f03576040805162461bcd60e51b815260206004820152601a60248201527f4552525f494e56414c49445f524553455256455f574549474854000000000000604482015290519081900360640190fd5b61343a611271565b611433576040805162461bcd60e51b815260206004820152600c60248201526b4552525f494e41435449564560a01b604482015290519081900360640190fd5b60006134858361421b565b80156134915750600082115b6134d4576040805162461bcd60e51b815260206004820152600f60248201526e11549497d6915493d7d05353d55395608a1b604482015290519081900360640190fd5b600060086000866000815181106134e757fe5b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205490506000600860008760018151811061352557fe5b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205490508160021480156135605750806001145b1561365c5760008660008151811061357457fe5b602002602001015190508660018151811061358b57fe5b6020026020010151876000815181106135a057fe5b60200260200101906001600160a01b031690816001600160a01b03168152505080876001815181106135ce57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250506000866000815181106135fd57fe5b602002602001015190508660018151811061361457fe5b60200260200101518760008151811061362957fe5b602002602001018181525050808760018151811061364357fe5b60200260200101818152505060019450505050506120e6565b81600114801561366c5750806002145b6136b3576040805162461bcd60e51b81526020600482015260136024820152724552525f494e56414c49445f5245534552564560681b604482015290519081900360640190fd5b50600095945050505050565b6001600160a01b03811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14919050565b80516000908190815b8181101561371d5761371185828151811061370457fe5b602002602001015161425a565b909201916001016136ed565b50600161372a838361427c565b03600a0a949350505050565b6000828201838110156120e6576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b8015806137a157506137a1846136bf565b156137ab576137cb565b6137cb8383836137ba88613d09565b6001600160a01b0316929190614294565b50505050565b6001600160801b0382111580156137ef57506001600160801b038111155b613840576040805162461bcd60e51b815260206004820152601c60248201527f4552525f524553455256455f42414c414e43455f4f564552464c4f5700000000604482015290519081900360640190fd5b61384c828583866142ee565b60055550505050565b60008084116138a0576040805162461bcd60e51b81526020600482015260126024820152714552525f494e56414c49445f535550504c5960701b604482015290519081900360640190fd5b600083116138e3576040805162461bcd60e51b815260206004820152601b6024820152600080516020614b5a833981519152604482015290519081900360640190fd5b816138f0575060006120e6565b826138fb83866141ab565b8161390257fe5b04949350505050565b6000808411613956576040805162461bcd60e51b81526020600482015260126024820152714552525f494e56414c49445f535550504c5960701b604482015290519081900360640190fd5b60008311613999576040805162461bcd60e51b815260206004820152601b6024820152600080516020614b5a833981519152604482015290519081900360640190fd5b816139a6575060006120e6565b8360016139b384866141ab565b03816139bb57fe5b0460010190509392505050565b60008060006139d886868661430e565b905060006139e582614372565b9182900399919850909650505050505050565b600082821115613a4f576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6009546000906111819063ffffffff600160c01b9091048116620f4240819003821691613a849186916141ab16565b906143a7565b6000808411613ace576040805162461bcd60e51b815260206004820152601b6024820152600080516020614b5a833981519152604482015290519081900360640190fd5b828210613b17576040805162461bcd60e51b815260206004820152601260248201527111549497d253959053125117d05353d5539560721b604482015290519081900360640190fd5b81613b24575060006120e6565b81830360016139b386856141ab565b6000613b3d614406565b6001600160a01b038087166000908152600860205260408082205492881682528120549080613b6c8484613293565b91509150600080613b808c8c86868e6139c8565b915091508160001415613bd3576040805162461bcd60e51b815260206004820152601660248201527511549497d6915493d7d5105491d15517d05353d5539560521b604482015290519081900360640190fd5b828210613bdc57fe5b6000613bf16001600160a01b038e1630612b66565b9050613c058d6001600160a01b03166136bf565b15613c5d578a3414613c58576040805162461bcd60e51b815260206004820152601760248201527608aa4a4be8aa890be829a9eaa9ca8be9a92a69a82a8869604b1b604482015290519081900360640190fd5b613cba565b34158015613c7457508a613c7182876139f8565b10155b613cba576040805162461bcd60e51b815260206004820152601260248201527111549497d253959053125117d05353d5539560721b604482015290519081900360640190fd5b613cc88787838688036137d1565b613cdc6001600160a01b038d168a85612c0f565b613cea8d8d8c8e8787614423565b613cf88d8d8386880361447f565b50909b9a5050505050505050505050565b90565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052612c819084906145b8565b6001600160801b03811115613dba576040805162461bcd60e51b815260206004820152601c60248201527f4552525f524553455256455f42414c414e43455f4f564552464c4f5700000000604482015290519081900360640190fd5b6000613dcb60055484600303613de4565b9050613ddc828483866003036142ee565b600555505050565b60008160011480613df55750816002145b613dfb57fe5b50608060001982010282901c6001600160801b031692915050565b600080600080613e27600654614669565b90506000613e36868802614669565b9050808210613e515760008060009450945094505050613f23565b600080613e6f6e4e6574776f726b53657474696e677360881b613215565b6001600160a01b031663e33b5f5f6040518163ffffffff1660e01b8152600401604080518083038186803b158015613ea657600080fd5b505afa158015613eba573d6000803e3d6000fd5b505050506040513d6040811015613ed057600080fd5b508051602090910151909250905063ffffffff8082168585030290620f42408502908490613f08908390613a84908f9087906141ab16565b613f1683613a848e876141ab565b9850985098505050505050505b9250925092565b80471015613f7f576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604482015290519081900360640190fd5b6040516000906001600160a01b0384169083908381818185875af1925050503d8060008114613fca576040519150601f19603f3d011682016040523d82523d6000602084013e613fcf565b606091505b5050905080612c815760405162461bcd60e51b815260040180806020018281038252603a815260200180614a8f603a913960400191505060405180910390fd5b600080841161405a576040805162461bcd60e51b81526020600482015260126024820152714552525f494e56414c49445f535550504c5960701b604482015290519081900360640190fd5b6000831161409d576040805162461bcd60e51b815260206004820152601b6024820152600080516020614b5a833981519152604482015290519081900360640190fd5b838211156140e7576040805162461bcd60e51b815260206004820152601260248201527111549497d253959053125117d05353d5539560721b604482015290519081900360640190fd5b816140f4575060006120e6565b838214156141035750816120e6565b836138fb83856141ab565b60e01c90565b4290565b60008084848482118061412a57508481115b156141405761413a828287614682565b90925090505b8082146141515790925090506111dd565b50600196879650945050505050565b600063ffffffff841115801561417d57506001600160701b038311155b801561419057506001600160701b038211155b61419657fe5b5060e083901b607083901b1781179392505050565b6000826141ba57506000611181565b828202828482816141c757fe5b04146120e65760405162461bcd60e51b8152600401808060200182810382526021815260200180614b0f6021913960400191505060405180910390fd5b6000806142118585613de4565b6111d88685613de4565b6000808260008151811061422b57fe5b6020026020010151118015611181575060008260018151811061424a57fe5b6020026020010151119050919050565b600080825b80156142755760019190910190600a900461425f565b5092915050565b6000816002810484018161428c57fe5b049392505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526137cb9085906145b8565b60006142fa83836146bb565b61430486866146bb565b1795945050505050565b6000808411801561431f5750600083115b61435e576040805162461bcd60e51b815260206004820152601b6024820152600080516020614b5a833981519152604482015290519081900360640190fd5b6143688483613736565b6138fb84846141ab565b600954600090620f424090614399908490600160c01b900463ffffffff908116906141ab16565b816143a057fe5b0492915050565b60008082116143fd576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161428c57fe5b600a54600061441482612f1b565b9050808214612cb557600a5550565b604080518481526020810184905280820183905290516001600160a01b038087169288821692918a16917f276856b36cbc45526a0ba64f44611557a2a8b68662c5388e9fe6d72e86e1c8cb9181900360600190a4505050505050565b600954604080516318160ddd60e01b815290516001600160a01b039092169160009183916318160ddd91600480820192602092909190829003018186803b1580156144c957600080fd5b505afa1580156144dd573d6000803e3d6000fd5b505050506040513d60208110156144f357600080fd5b5051604080518581526020810187905281519293506001600160a01b0380891693908a1692600080516020614aef833981519152928290030190a3856001600160a01b0316826001600160a01b0316600080516020614aef8339815191528684604051808381526020018281526020019250505060405180910390a3846001600160a01b0316826001600160a01b0316600080516020614aef8339815191528584604051808381526020018281526020019250505060405180910390a3505050505050565b606061460d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166146f09092919063ffffffff16565b805190915015612c815780806020019051602081101561462c57600080fd5b5051612c815760405162461bcd60e51b815260040180806020018281038252602a815260200180614b30602a913960400191505060405180910390fd5b6000808211614679576000611181565b61118182614707565b6000808385116146a057614697858585614756565b915091506111dd565b6000806146ae868887614756565b9890975095505050505050565b60006001600160801b0383111580156146de575081600114806146de5750816002145b6146e457fe5b50600019016080021b90565b60606146ff848460008561481a565b949350505050565b6000806002830460010190506000600282858161472057fe5b0483018161472a57fe5b0490505b8082111561427557809150600282858161474457fe5b0483018161474e57fe5b04905061472e565b6000806000836000198161476657fe5b0490508086111561479f57600081600101878161477f57fe5b04600101905080878161478e57fe5b04965080868161479a57fe5b049550505b84861461480a5785840260006147b58888614976565b90508781106147db5760006147ca838361497a565b9550505083850392506111dd915050565b60028888030487038210156147f957600086945094505050506111dd565b6001808703945094505050506111dd565b5050600290910493849350915050565b60608247101561485b5760405162461bcd60e51b8152600401808060200182810382526026815260200180614ac96026913960400191505060405180910390fd5b614864856149a6565b6148b5576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b602083106148f45780518252601f1990920191602091820191016148d5565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114614956576040519150601f19603f3d011682016040523d82523d6000602084013e61495b565b606091505b509150915061496b8282866149ac565b979650505050505050565b0190565b600060028204820382848161498b57fe5b068161499357fe5b0482848161499d57fe5b04019392505050565b3b151590565b606083156149bb5750816120e6565b8251156149cb5782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015614a155781810151838201526020016149fd565b50505050905090810190601f168015614a425780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b6040518060400160405280600290602082028036833750919291505056fe5265656e7472616e637947756172643a207265656e7472616e742063616c6c00416464726573733a20756e61626c6520746f2073656e642076616c75652c20726563697069656e74206d61792068617665207265766572746564416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c77f29993cf2c084e726f7e802da0719d6a0ade3e204badc7a3ffd57ecb768c24536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565644552525f494e56414c49445f524553455256455f42414c414e43450000000000a2646970667358221220842dacb7e388376021cadeda051cec41f1b8c334339cbba7a1be95a5308eee9164736f6c634300060c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000b1cd6e4153b2a390cf00a6556b0fc1458c4a553300000000000000000000000052ae12abe5d8bd778bd5397f99ca900624cfadd40000000000000000000000000000000000000000000000000000000000007530
-----Decoded View---------------
Arg [0] : anchor (address): 0xb1CD6e4153B2a390Cf00A6556b0fC1458C4A5533
Arg [1] : registry (address): 0x52Ae12ABe5D8BD778BD5397F99cA900624CfADD4
Arg [2] : maxConversionFee (uint32): 30000
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000b1cd6e4153b2a390cf00a6556b0fc1458c4a5533
Arg [1] : 00000000000000000000000052ae12abe5d8bd778bd5397f99ca900624cfadd4
Arg [2] : 0000000000000000000000000000000000000000000000000000000000007530
Deployed Bytecode Sourcemap
52347:44984:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31913:42;55443:27;55457:12;55443:13;:27::i;:::-;57601:98;52347:44984;;;;;41680:205;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;41680:205:0;;;;:::i;:::-;;59717:507;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;59717:507:0;-1:-1:-1;;;;;59717:507:0;;:::i;95903:473::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;95903:473:0;-1:-1:-1;;;;;95903:473:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63527:216;;;;;;;;;;;;;:::i;86486:393::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;86486:393:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;86486:393:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;86486:393:0;;-1:-1:-1;86486:393:0;;-1:-1:-1;;;;;86486:393:0:i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;96450:134;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;96450:134:0;;:::i;:::-;;;;-1:-1:-1;;;;;96450:134:0;;;;;;;;;;;;;;62555:153;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;62555:153:0;-1:-1:-1;;;;;62555:153:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;97074:254;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;97074:254:0;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;74097:468;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;74097:468:0;-1:-1:-1;;;;;74097:468:0;;:::i;95525:130::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;95525:130:0;-1:-1:-1;;;;;95525:130:0;;:::i;57795:122::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;61638:121;;;;;;;;;;;;;:::i;85933:430::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;85933:430:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;85933:430:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;85933:430:0;;;;;;;;-1:-1:-1;85933:430:0;;-1:-1:-1;;;;;85933:430:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;85933:430:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;85933:430:0;;-1:-1:-1;85933:430:0;;-1:-1:-1;;;;;85933:430:0:i;:::-;;;;;;;;;;;;;;;;42373:120;;;;;;;;;;;;;:::i;95729:100::-;;;;;;;;;;;;;:::i;63324:82::-;;;;;;;;;;;;;:::i;56426:98::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;40429:935;;;;;;;;;;;;;:::i;61010:263::-;;;;;;;;;;;;;:::i;29280:35::-;;;;;;;;;;;;;:::i;57171:105::-;;;;;;;;;;;;;:::i;63133:118::-;;;;;;;;;;;;;:::i;42165:105::-;;;;;;;;;;;;;:::i;58261:156::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;58261:156:0;-1:-1:-1;;;;;58261:156:0;;:::i;61978:509::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;61978:509:0;;-1:-1:-1;;;;;61978:509:0;;;;;;;;:::i;96658:116::-;;;;;;;;;;;;;:::i;35808:227::-;;;;;;;;;;;;;:::i;41977:95::-;;;;;;;;;;;;;:::i;77109:3912::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;77109:3912:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;77109:3912:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;77109:3912:0;;;;;;;;-1:-1:-1;77109:3912:0;;-1:-1:-1;;;;;77109:3912:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;77109:3912:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;77109:3912:0;;-1:-1:-1;;77109:3912:0;;;-1:-1:-1;77109:3912:0;;-1:-1:-1;;77109:3912:0:i;84931:678::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;84931:678:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;84931:678:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;84931:678:0;;-1:-1:-1;;84931:678:0;;;-1:-1:-1;;;84931:678:0;;;;:::i;36115:88::-;;;;;;;;;;;;;:::i;56968:111::-;;;;;;;;;;;;;:::i;61441:122::-;;;;;;;;;;;;;:::i;69869:528::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;69869:528:0;;;;;;;;;;;;;;;;;:::i;82030:2522::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;82030:2522:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;82030:2522:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;82030:2522:0;;;;;;;;-1:-1:-1;82030:2522:0;;-1:-1:-1;;;;;82030:2522:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;82030:2522:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;82030:2522:0;;-1:-1:-1;82030:2522:0;;-1:-1:-1;;;;;82030:2522:0:i;41443:141::-;;;;;;;;;;;;;:::i;71106:620::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;71106:620:0;;;;;;;;;;;;;;;;;:::i;58791:284::-;;;;;;;;;;;;;:::i;56623:84::-;;;;;;;;;;;;;:::i;56775:101::-;;;;;;;;;;;;;:::i;36289:87::-;;;;;;;;;;;;;:::i;60506:378::-;;;;;;;;;;;;;:::i;96848:152::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;96848:152:0;-1:-1:-1;;;;;96848:152:0;;:::i;62792:258::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;62792:258:0;-1:-1:-1;;;;;62792:258:0;;:::i;65882:439::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;65882:439:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;59242:239::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;59242:239:0;;;;:::i;57345:101::-;;;;;;;;;;;;;:::i;35549:168::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;35549:168:0;-1:-1:-1;;;;;35549:168:0;;:::i;55547:145::-;-1:-1:-1;;;;;55630:25:0;;;;;;:11;:25;;;;;;55622:62;;;;;-1:-1:-1;;;55622:62:0;;;;;;;;;;;;-1:-1:-1;;;55622:62:0;;;;;;;;;;;;;;;55547:145;:::o;41680:205::-;35111:12;:10;:12::i;:::-;41830:27:::1;:47:::0;;;::::1;;-1:-1:-1::0;;;41830:47:0::1;-1:-1:-1::0;;;;41830:47:0;;::::1;::::0;;;::::1;::::0;;41680:205::o;59717:507::-;28058:1;28664:7;;:19;;28656:63;;;;;-1:-1:-1;;;28656:63:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;28656:63:0;;;;;;;;;;;;;;;28058:1;28797:7;:18;35111:12:::1;:10;:12::i;:::-;-1:-1:-1::0;;;39811:19:0::2;39817:12;39811:5;:19::i;:::-;59924:14:::3;:21:::0;59901:20:::3;59956:261;59980:12;59976:1;:16;59956:261;;;60014:26;60043:14;60058:1;60043:17;;;;;;;;;::::0;;;::::3;::::0;;;::::3;::::0;-1:-1:-1;;;;;60043:17:0::3;::::0;-1:-1:-1;60077:78:0::3;60103:12:::0;60117:37:::3;60043:17:::0;60148:4:::3;60117:22;:37::i;:::-;-1:-1:-1::0;;;;;60077:25:0;::::3;::::0;:78;:25:::3;:78::i;:::-;60172:33;60192:12;60172:19;:33::i;:::-;-1:-1:-1::0;59994:3:0::3;;59956:261;;;-1:-1:-1::0;;28014:1:0;28976:7;:22;-1:-1:-1;;59717:507:0:o;95903:473::-;-1:-1:-1;;;;;96166:25:0;;96033:7;96166:25;;;:11;:25;;;;;;96033:7;;;;;;;;96206:14;;96202:122;;96245:26;96261:9;96245:15;:26::i;:::-;96237:75;-1:-1:-1;96273:18:0;;-1:-1:-1;96293:5:0;;-1:-1:-1;96293:5:0;;-1:-1:-1;96307:4:0;;-1:-1:-1;96237:75:0;;-1:-1:-1;96237:75:0;96202:122;96342:1;96345;96348:5;96355;96362;96334:34;;;;;;;;;;;95903:473;;;;;;;;:::o;63527:216::-;28058:1;28664:7;;:19;;28656:63;;;;;-1:-1:-1;;;28656:63:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;28656:63:0;;;;;;;;;;;;;;;28058:1;28797:7;:18;63591:23:::1;::::0;63643:22:::1;63591:23:::0;63643:19:::1;:22::i;:::-;63702:33;63676:23;:59:::0;-1:-1:-1;;28014:1:0;28976:7;:22;63527:216::o;86486:393::-;86616:16;86650:19;86689:7;;;;;;;;;-1:-1:-1;;;;;86689:7:0;-1:-1:-1;;;;;86672:38:0;;:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;86672:40:0;;-1:-1:-1;86723:30:0;;:::i;:::-;86756;86777:8;86756:20;:30::i;:::-;86723:63;;86806:65;86837:6;86845:11;86858:12;86806:30;:65::i;:::-;86799:72;;;;86486:393;;;;;:::o;96450:134::-;96522:13;96555:14;96570:5;96555:21;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;96555:21:0;;-1:-1:-1;96450:134:0;;;;:::o;62555:153::-;62656:6;62633:12;55443:27;55457:12;55443:13;:27::i;:::-;-1:-1:-1;62682:18:0;;;-1:-1:-1;;62555:153:0:o;97074:254::-;97226:7;97235;97262:58;97281:11;97294;97307:12;97262:18;:58::i;:::-;97255:65;;;;97074:254;;;;;;;:::o;74097:468::-;74188:7;74197;74172:5;55443:27;55457:12;55443:13;:27::i;:::-;74270:12:::1;74285:40;74308:16;;74285:22;:40::i;:::-;74270:55;;74338:13;74354:25;74374:4;74354:19;:25::i;:::-;74338:41;;74390:13;74406:25;74426:4;74406:19;:25::i;:::-;74390:41;;74457:14;74472:1;74457:17;;;;;;;;;::::0;;;::::1;::::0;;;::::1;::::0;-1:-1:-1;;;;;74448:26:0;;::::1;74457:17:::0;::::1;74448:26;74444:80;;;74499:5:::0;;-1:-1:-1;74506:5:0;-1:-1:-1;74491:21:0::1;::::0;-1:-1:-1;74491:21:0::1;74444:80;74544:5:::0;-1:-1:-1;74551:5:0;-1:-1:-1;;55483:1:0::1;74097:468:::0;;;;:::o;95525:130::-;35111:12;:10;:12::i;:::-;95614:33:::1;95638:8;95614:23;:33::i;57795:122::-:0;57853:4;57904;-1:-1:-1;;;;;57877:32:0;:7;;;;;;;;;-1:-1:-1;;;;;57877:7:0;-1:-1:-1;;;;;57877:13:0;;:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;57877:15:0;-1:-1:-1;;;;;57877:32:0;;;-1:-1:-1;57795:122:0;:::o;61638:121::-;61695:22;61737:14;61730:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;61730:21:0;;;;;;;;;;;;;;;;;;;;;;;61638:121;:::o;85933:430::-;86070:7;86095:19;86134:7;;;;;;;;;-1:-1:-1;;;;;86134:7:0;-1:-1:-1;;;;;86117:38:0;;:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;86117:40:0;;-1:-1:-1;86168:30:0;;:::i;:::-;86201;86222:8;86201:20;:30::i;:::-;86168:63;;86243:14;86263:66;86284:8;86294:7;86303:12;86317:11;86263:20;:66::i;:::-;-1:-1:-1;86242:87:0;85933:430;-1:-1:-1;;;;;;85933:430:0:o;42373:120::-;42458:27;;-1:-1:-1;;;42458:27:0;;;;;42373:120::o;95729:100::-;35111:12;:10;:12::i;:::-;95798:23:::1;:21;:23::i;:::-;95729:100::o:0;63324:82::-;63375:23;63396:1;63375:20;:23::i;56426:98::-;56515:1;56426:98;:::o;40429:935::-;40548:7;:5;:7::i;:::-;-1:-1:-1;;;;;40534:21:0;:10;-1:-1:-1;;;;;40534:21:0;;:53;;;-1:-1:-1;40560:27:0;;-1:-1:-1;;;40560:27:0;;;;40559:28;40534:53;40526:83;;;;;-1:-1:-1;;;40526:83:0;;;;;;;;;;;;-1:-1:-1;;;40526:83:0;;;;;;;;;;;;;;;40664:29;40714;-1:-1:-1;;;40714:10:0;:29::i;:::-;40856:9;;40664:80;;-1:-1:-1;;;;;;40841:24:0;;;40856:9;;40841:24;;;;:62;;-1:-1:-1;;;;;;40869:34:0;;;;40841:62;40833:95;;;;;-1:-1:-1;;;40833:95:0;;;;;;;;;;;;-1:-1:-1;;;40833:95:0;;;;;;;;;;;;;;;41095:1;-1:-1:-1;;;;;41043:54:0;:11;-1:-1:-1;;;;;41043:21:0;;-1:-1:-1;;;41043:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;41043:40:0;-1:-1:-1;;;;;41043:54:0;;;41035:87;;;;;-1:-1:-1;;;41035:87:0;;;;;;;;;;;;-1:-1:-1;;;41035:87:0;;;;;;;;;;;;;;;41230:9;;;41214:13;:25;;-1:-1:-1;;;;;41230:9:0;;;-1:-1:-1;;;;;;41214:25:0;;;;;;;41333:23;;;;;;;;;;;40429:935::o;61010:263::-;28058:1;28664:7;;:19;;28656:63;;;;;-1:-1:-1;;;28656:63:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;28656:63:0;;;;;;;;;;;;;;;28058:1;28797:7;:18;35111:12:::1;:10;:12::i;:::-;-1:-1:-1::0;;;39811:19:0::2;39817:12;39811:5;:19::i;:::-;61117:23:::3;61142::::0;61169:26:::3;61190:1;61193;61169:20;:26::i;:::-;61232:33;61206:23;:59:::0;-1:-1:-1;;28014:1:0;28976:7;:22;-1:-1:-1;61010:263:0:o;29280:35::-;29313:2;29280:35;:::o;57171:105::-;57254:14;;-1:-1:-1;;;57254:14:0;;;;;57171:105::o;63133:118::-;63181:7;63190;63217:26;63238:1;63241;63217:20;:26::i;:::-;63210:33;;;;63133:118;;:::o;42165:105::-;42249:13;;-1:-1:-1;;;;;42249:13:0;42165:105;:::o;58261:156::-;35111:12;:10;:12::i;:::-;-1:-1:-1;;;39811:19:0::1;39817:12;39811:5;:19::i;:::-;58374:7:::2;::::0;:35:::2;::::0;;-1:-1:-1;;;58374:35:0;;-1:-1:-1;;;;;58374:35:0;;::::2;;::::0;::::2;::::0;;;:7;;;::::2;::::0;:25:::2;::::0;:35;;;;;:7:::2;::::0;:35;;;;;;;:7;;:35;::::2;;::::0;::::2;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;35136:1:::1;58261:156:::0;:::o;61978:509::-;35111:12;:10;:12::i;:::-;55092:11:::1;:9;:11::i;:::-;62162:5:::2;37733:27;37755:4;37733:21;:27::i;:::-;62198:6:::3;56113:27;56133:6;56113:19;:27::i;:::-;62256:7:::4;::::0;-1:-1:-1;;;;;62230:34:0;;::::4;62256:7:::0;::::4;62230:34;::::0;::::4;::::0;:61:::4;;-1:-1:-1::0;;;;;;62268:18:0;::::4;;::::0;;;:11:::4;:18;::::0;;;;;:23;62230:61:::4;62222:93;;;::::0;;-1:-1:-1;;;62222:93:0;;::::4;;::::0;::::4;::::0;::::4;::::0;;;;-1:-1:-1;;;62222:93:0;;;;;;;;;;;;;::::4;;62356:1;62334:19;:17;:19::i;:::-;:23;;;62326:61;;;::::0;;-1:-1:-1;;;62326:61:0;;::::4;;::::0;::::4;::::0;::::4;::::0;;;;-1:-1:-1;;;62326:61:0;;;;;;;;;;;;;::::4;;-1:-1:-1::0;;62400:14:0::4;:26:::0;;::::4;::::0;::::4;::::0;;;::::4;::::0;;-1:-1:-1;;;;;62400:26:0;;::::4;-1:-1:-1::0;;;;;;62400:26:0;;::::4;::::0;::::4;::::0;;62458:21;-1:-1:-1;62437:18:0;;;:11:::4;62400:26;62437:18:::0;;;;;:42;;;;-1:-1:-1;61978:509:0:o;96658:116::-;96721:6;96747:19;:17;:19::i;:::-;96740:26;;96658:116;:::o;35808:227::-;35884:9;;-1:-1:-1;;;;;35884:9:0;35870:10;:23;35862:53;;;;;-1:-1:-1;;;35862:53:0;;;;;;;;;;;;-1:-1:-1;;;35862:53:0;;;;;;;;;;;;;;;35953:9;;;35945:6;;35933:30;;-1:-1:-1;;;;;35953:9:0;;;;35945:6;;;;35933:30;;;35985:9;;;;35976:18;;-1:-1:-1;;;;;;35976:18:0;;;-1:-1:-1;;;;;35985:9:0;;35976:18;;;;36005:22;;;35808:227::o;41977:95::-;42055:9;;-1:-1:-1;;;;;42055:9:0;41977:95;:::o;77109:3912::-;77296:7;28058:1;28664:7;;:19;;28656:63;;;;;-1:-1:-1;;;28656:63:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;28656:63:0;;;;;;;;;;;;;;;28058:1;28797:7;:18;54832:9:::1;:7;:9::i;:::-;77316:58:::2;77338:8;77348:14;77364:9;77316:21;:58::i;:::-;;77530:27;:8;77539:1;77530:11;;;;;;;;;;;;;;-1:-1:-1::0;;;;;77530:25:0::2;;:27::i;:::-;77529:28;:62;;;;77582:9;77561:14;77576:1;77561:17;;;;;;;;;;;;;;:30;77529:62;77528:149;;;;;77615:27;:8;77624:1;77615:11;;;;;;;:27;77614:28;:62;;;;77667:9;77646:14;77661:1;77646:17;;;;;;;;;;;;;;:30;77614:62;77506:222;;;::::0;;-1:-1:-1;;;77506:222:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;77506:222:0;;;;;;;;;;;;;::::2;;77848:9;:13:::0;77844:128:::2;;31913:42;77886:46;::::0;:11:::2;:46;::::0;;;77878:82:::2;;;::::0;;-1:-1:-1;;;77878:82:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;77878:82:0;;;;;;;;;;;;;::::2;;78070:7;::::0;78147:23:::2;::::0;;-1:-1:-1;;;78147:23:0;;;;-1:-1:-1;;;;;78070:7:0;;::::2;::::0;78032:18:::2;::::0;78070:7;;78147:21:::2;::::0;:23:::2;::::0;;::::2;::::0;::::2;::::0;;;;;;;;;78070:7;78147:23;::::2;;::::0;::::2;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;::::0;::::2;;-1:-1:-1::0;78147:23:0;;-1:-1:-1;78183:37:0::2;;:::i;:::-;78231:36;;:::i;:::-;78397:30;78417:9;78397:19;:30::i;:::-;78347:22;78371::::0;::::2;78346:81:::0;;;78367:1:::2;78465:35;;:::i;:::-;78661:16:::0;78657:430:::2;;78703:36;78724:14;78703:20;:36::i;:::-;78694:45;;78777:14;78792:1;78777:17;;;;;;;;;;;;;;78754;78772:1;78754:20;;;;;;;;;;:40:::0;78832:17;;:14;;78847:1:::2;::::0;78832:17;::::2;;;;;;;;;;;78809;78827:1;78809:20;;;;;;;;;;:40:::0;78657:430:::2;;;78912:163;78951:8;78978:14;79011:19;79049:11;78912:20;:163::i;:::-;78882:193:::0;;-1:-1:-1;78882:193:0;-1:-1:-1;78657:430:0::2;79099:26;79128:23;:11:::0;79144:6;79128:15:::2;:23::i;:::-;79099:52;;79167:9;79162:1266;79186:1;79182;:5;79162:1266;;;79209:26;79238:8;79247:1;79238:11;;;;;;;;;;;;;;79209:40;;79264:21;79288:17;79306:1;79288:20;;;;;;;;;;;79264:44;;79347:1;79331:13;:17;79323:52;;;::::0;;-1:-1:-1;;;79323:52:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;79323:52:0;;;;;;;;;;;;;::::2;;79414:14;79429:1;79414:17;;;;;;;;;;;;;;79397:13;:34;;79390:42;;;;79537:28;:12;-1:-1:-1::0;;;;;79537:26:0::2;;:28::i;:::-;79532:443;;79666:71;-1:-1:-1::0;;;;;79666:29:0;::::2;79696:10;79716:4;79723:13:::0;79666:29:::2;:71::i;:::-;79532:443;;;79783:13;79763:14;79778:1;79763:17;;;;;;;;;;;;;;:33;79759:216;;;79887:72;79913:10;79945:13;79925:14;79940:1;79925:17;;;;;;;;;;;;;;:33;79887:12;-1:-1:-1::0;;;;;79887:25:0::2;;;:72;;;;;:::i;:::-;80060:41;80087:13;80060:19;80080:1;80060:22;;;;;;;;;;::::0;;:26:::2;:41::i;:::-;80036:18;80055:1;80036:21;;;;;;;;;;:65:::0;-1:-1:-1;;;;;80123:98:0;::::2;80138:10;80123:98;80164:13:::0;80179:18;80198:1;80179:21:::2;::::0;::::2;;;;;;::::0;;::::2;::::0;;;::::2;::::0;80123:98:::2;::::0;;;;;;;::::2;::::0;;;;;;;;;;;;;;;::::2;80359:12;-1:-1:-1::0;;;;;80315:101:0::2;80339:9;-1:-1:-1::0;;;;;80315:101:0::2;-1:-1:-1::0;;;;;;;;;;;80374:18:0::2;80393:1;80374:21;;;;;;;;;;;80397:18;80315:101;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;79189:3:0::2;;79162:1266;;;-1:-1:-1::0;80503:21:0;;80477:71:::2;::::0;80497:1:::2;::::0;80500::::2;::::0;80503:18;80497:1;80526:21:::2;;;;;80477:19;:71::i;:::-;80656:21;::::0;::::2;::::0;80632;;:45:::2;80606:23;:71:::0;80804:19;;::::2;;80796:50;;;::::0;;-1:-1:-1;;;80796:50:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;80796:50:0;;;;;;;;;;;;;::::2;;80900:35;::::0;;-1:-1:-1;;;80900:35:0;;80916:10:::2;80900:35;::::0;::::2;::::0;;;;;;;;;-1:-1:-1;;;;;80900:15:0;::::2;::::0;::::2;::::0;:35;;;;;-1:-1:-1;;80900:35:0;;;;;;;-1:-1:-1;80900:15:0;:35;::::2;;::::0;::::2;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;-1:-1:-1::0;;28014:1:0;28976:7;:22;-1:-1:-1;81007:6:0;;77109:3912;-1:-1:-1;;;;;;;;;;;77109:3912:0:o;84931:678::-;85078:16;85107:19;85146:7;;;;;;;;;-1:-1:-1;;;;;85146:7:0;-1:-1:-1;;;;;85129:38:0;;:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;85129:40:0;;-1:-1:-1;85180:30:0;;:::i;:::-;85213;85234:8;85213:20;:30::i;:::-;85180:63;;85254:20;85277:59;85295:11;85308:12;85321:5;85308:19;;;;;;;;;;;85329:6;85277:17;:59::i;:::-;85383:16;;;85397:1;85383:16;;;85349:31;85383:16;;;;;85254:82;;-1:-1:-1;85383:16:0;;;;;;;;;;;;-1:-1:-1;;85349:50:0;-1:-1:-1;85430:53:0;85440:11;85453:12;85466:1;85453:15;;;;;85470:12;85430:9;:53::i;:::-;85410:14;85425:1;85410:17;;;;;;;;;;;;;;;;;:73;85514:53;85524:11;85537:12;85550:1;85537:15;;85514:53;85494:14;85509:1;85494:17;;;;;;;;;;;;;;;;;:73;85587:14;-1:-1:-1;;;;84931:678:0;;;;;;:::o;36115:88::-;36162:7;36189:6;-1:-1:-1;;;;;36189:6:0;36115:88;:::o;56968:111::-;57054:17;;-1:-1:-1;;;57054:17:0;;;;;56968:111::o;61441:122::-;61533:14;:21;61441:122;:::o;69869:528::-;70052:7;70061;54832:9;:7;:9::i;:::-;-1:-1:-1;;;;;70100:24:0;;::::1;70081:16;70100:24:::0;;;:11:::1;:24;::::0;;;;;;70154;;::::1;::::0;;;;;;70081:16;70240:40:::1;70100:24:::0;70154;70240:20:::1;:40::i;:::-;70191:89;;;;70300;70320:11;70333;70346:13;70361;70376:12;70300:19;:89::i;:::-;70293:96;;;;;;;;69869:528:::0;;;;;;:::o;82030:2522::-;82211:16;28058:1;28664:7;;:19;;28656:63;;;;;-1:-1:-1;;;28656:63:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;28656:63:0;;;;;;;;;;;;;;;28058:1;28797:7;:18;54832:9:::1;:7;:9::i;:::-;82274:20:::2;82297:57;82319:8;82329:16;82347:6;82297:21;:57::i;:::-;82274:80;;82415:18;82453:7;;;;;;;;;-1:-1:-1::0;;;;;82453:7:0::2;82415:47;;82542:19;82564:9;-1:-1:-1::0;;;;;82564:21:0::2;;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;::::0;::::2;;-1:-1:-1::0;82564:23:0;82636:37:::2;::::0;;-1:-1:-1;;;82636:37:0;;82654:10:::2;82636:37;::::0;::::2;::::0;;;;;;;;;82564:23;;-1:-1:-1;;;;;;82636:17:0;::::2;::::0;::::2;::::0;:37;;;;;-1:-1:-1;;82636:37:0;;;;;;;;-1:-1:-1;82636:17:0;:37;::::2;;::::0;::::2;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;82686:26;82715:23;82731:6;82715:11;:15;;:23;;;;:::i;:::-;82686:52;;82751:37;;:::i;:::-;82799:36;;:::i;:::-;82965:22;82985:1;82965:19;:22::i;:::-;82915;82939::::0;::::2;82914:73:::0;;;83000:31:::2;83034:72;83065:6:::0;83073:11;82915:19;83034:30:::2;:72::i;:::-;83000:106;;83124:9;83119:837;83143:1;83139;:5;83119:837;;;83166:26;83195:8;83204:1;83195:11;;;;;;;;;;;;;;83166:40;;83221:21;83245:14;83260:1;83245:17;;;;;;;;;;;;;;83221:41;;83302:16;83319:1;83302:19;;;;;;;;;;;;;;83285:13;:36;;83277:71;;;::::0;;-1:-1:-1;;;83277:71:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;83277:71:0;;;;;;;;;;;;;::::2;;83434:41;83461:13;83434:19;83454:1;83434:22;;;;;;;;;;::::0;;:26:::2;:41::i;:::-;83410:18;83429:1;83410:21;;;;;;;;;;:65:::0;83575:52:::2;-1:-1:-1::0;;;;;83575:25:0;::::2;83601:10;83613:13:::0;83575:25:::2;:52::i;:::-;-1:-1:-1::0;;;;;83649:100:0;::::2;83666:10;83649:100;83692:13:::0;83707:18;83726:1;83707:21:::2;::::0;::::2;;;;;;::::0;;::::2;::::0;;;::::2;::::0;83649:100:::2;::::0;;;;;;;::::2;::::0;;;;;;;;;;;;;;;::::2;83887:12;-1:-1:-1::0;;;;;83843:101:0::2;83867:9;-1:-1:-1::0;;;;;83843:101:0::2;-1:-1:-1::0;;;;;;;;;;;83902:18:0::2;83921:1;83902:21;;;;;;;;;;;83925:18;83843:101;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;83146:3:0::2;;83119:837;;;-1:-1:-1::0;84031:21:0;;84005:71:::2;::::0;84025:1:::2;::::0;84028::::2;::::0;84031:18;84025:1;84054:21:::2;::::0;84005:71:::2;84184:21;::::0;::::2;::::0;84160;;:45:::2;84134:23;:71:::0;84218:197;::::2;;;84254:25;84282:14;84297:1;84282:17;;;;;;;;;;;;;;84254:45;;84334:14;84349:1;84334:17;;;;;;;;;;;;;;84314:14;84329:1;84314:17;;;;;;;;;;;;;:37;;;::::0;::::2;84386:17;84366:14;84381:1;84366:17;;;;;;;;;;;;;:37;;;::::0;::::2;84218:197;;28014:1:::0;28976:7;:22;84530:14;82030:2522;-1:-1:-1;;;;;;;;;;82030:2522:0:o;41443:141::-;35111:12;:10;:12::i;:::-;41563:13:::1;::::0;41551:9:::1;:25:::0;;-1:-1:-1;;;;;;41551:25:0::1;-1:-1:-1::0;;;;;41563:13:0;;::::1;41551:25:::0;;;::::1;::::0;;41443:141::o;71106:620::-;71280:7;71289;54832:9;:7;:9::i;:::-;-1:-1:-1;;;;;71328:24:0;;::::1;71309:16;71328:24:::0;;;:11:::1;:24;::::0;;;;;;71382;;::::1;::::0;;;;;;71309:16;71468:40:::1;71328:24:::0;71382;71468:20:::1;:40::i;:::-;71419:89;;;;71521:11;71535:30;71552:12;71535:16;:30::i;:::-;71521:44:::0;-1:-1:-1;71578:20:0::1;71601:78;71627:13:::0;71642;71657:21:::1;:12:::0;71521:44;71657:16:::1;:21::i;:::-;71601:25;:78::i;:::-;71578:101:::0;71714:3;;-1:-1:-1;71106:620:0;;-1:-1:-1;;;;;;;;;71106:620:0:o;58791:284::-;35111:12;:10;:12::i;:::-;58877:14:::1;:21:::0;58902:1:::1;58877:26;58869:64;;;::::0;;-1:-1:-1;;;58869:64:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;58869:64:0;;;;;;;;;;;;;::::1;;58946:7;;;;;;;;;-1:-1:-1::0;;;;;58946:7:0::1;-1:-1:-1::0;;;;;58946:23:0::1;;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;58984:23;59005:1;58984:20;:23::i;:::-;59053:7;::::0;59062:4:::1;::::0;-1:-1:-1;;;;;59053:7:0::1;59036:15;:13;:15::i;:::-;59025:42;;;;;;;;;;;;58791:284::o:0;56623:84::-;56695:4;56623:84;:::o;56775:101::-;56861:7;;-1:-1:-1;;;;;56861:7:0;56775:101;:::o;36289:87::-;36359:9;;-1:-1:-1;;;;;36359:9:0;36289:87;:::o;60506:378::-;35111:12;:10;:12::i;:::-;60555:36:::1;60613:30;-1:-1:-1::0;;;60613:10:0::1;:30::i;:::-;60730:7;::::0;60555:89;;-1:-1:-1;60739:5:0::1;::::0;-1:-1:-1;;;;;60730:7:0::1;60713:15;:13;:15::i;:::-;60702:43;;;;;;;;;;;;60758:45;60784:17;60758;:45::i;:::-;60814:34;::::0;;-1:-1:-1;;;60814:34:0;;29313:2:::1;60814:34;::::0;::::1;::::0;;;-1:-1:-1;;;;;60814:25:0;::::1;::::0;::::1;::::0;:34;;;;;-1:-1:-1;;60814:34:0;;;;;;;-1:-1:-1;60814:25:0;:34;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;60859:17;:15;:17::i;96848:152::-:0;96937:7;96964:28;96979:12;62792:258;-1:-1:-1;;;;;62914:25:0;;62874:7;62914:25;;;:11;:25;;;;;;62958:14;62950:46;;;;;-1:-1:-1;;;62950:46:0;;;;;;;;;;;;-1:-1:-1;;;62950:46:0;;;;;;;;;;;;;;;63016:26;63032:9;63016:15;:26::i;65882:439::-;66141:7;28058:1;28664:7;;:19;;28656:63;;;;;-1:-1:-1;;;28656:63:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;28656:63:0;;;;;;;;;;;;;;;28058:1;28797:7;:18;-1:-1:-1;;;39811:19:0::1;66116:14:::0;39811:5:::1;:19::i;:::-;66184:11:::2;-1:-1:-1::0;;;;;66169:26:0::2;:11;-1:-1:-1::0;;;;;66169:26:0::2;;;66161:61;;;::::0;;-1:-1:-1;;;66161:61:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;66161:61:0;;;;;;;;;;;;;::::2;;66242:71;66253:11;66266;66279:12;66293:6;66301:11;66242:10;:71::i;:::-;28014:1:::0;28976:7;:22;66235:78;65882:439;-1:-1:-1;;;;;;;65882:439:0:o;59242:239::-;35111:12;:10;:12::i;:::-;59334:17:::1;::::0;::::1;-1:-1:-1::0;;;59334:17:0;;::::1;::::0;::::1;59327:24:::0;;::::1;;;59319:63;;;::::0;;-1:-1:-1;;;59319:63:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;59420:14;::::0;59400:40:::1;::::0;;59420:14:::1;-1:-1:-1::0;;;59420:14:0;;::::1;::::0;::::1;59400:40:::0;;;;::::1;;::::0;::::1;::::0;;;::::1;::::0;;;;;;;;::::1;59453:14;:20:::0;;::::1;::::0;;::::1;-1:-1:-1::0;;;59453:20:0::1;-1:-1:-1::0;;;;59453:20:0;;::::1;::::0;;;::::1;::::0;;59242:239::o;57345:101::-;57422:16;;57345:101;:::o;35549:168::-;35111:12;:10;:12::i;:::-;35651:6:::1;::::0;-1:-1:-1;;;;;35639:18:0;;::::1;35651:6:::0;::::1;35639:18;;35631:45;;;::::0;;-1:-1:-1;;;35631:45:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;35631:45:0;;;;;;;;;;;;;::::1;;35689:9;:20:::0;;-1:-1:-1;;;;;;35689:20:0::1;-1:-1:-1::0;;;;;35689:20:0;;;::::1;::::0;;;::::1;::::0;;35549:168::o;35200:104::-;35268:6;;-1:-1:-1;;;;;35268:6:0;35254:10;:20;35246:50;;;;;-1:-1:-1;;;35246:50:0;;;;;;;;;;;;-1:-1:-1;;;35246:50:0;;;;;;;;;;;;;;39905:138;39989:24;40000:12;39989:10;:24::i;:::-;-1:-1:-1;;;;;39975:38:0;:10;-1:-1:-1;;;;;39975:38:0;;39967:68;;;;;-1:-1:-1;;;39967:68:0;;;;;;;;;;;;-1:-1:-1;;;39967:68:0;;;;;;;;;;;;;;32288:257;32375:7;32399:27;32413:12;32399:13;:27::i;:::-;32395:82;;;-1:-1:-1;;;;;;32450:15:0;;;32443:22;;32395:82;32496:22;32505:12;32496:8;:22::i;:::-;-1:-1:-1;;;;;32496:32:0;;32529:7;32496:41;;;;;;;;;;;;;-1:-1:-1;;;;;32496:41:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;32496:41:0;;32288:257;-1:-1:-1;;;32288:257:0:o;32633:369::-;32769:11;32765:50;;32797:7;;32765:50;32831:27;32845:12;32831:13;:27::i;:::-;32827:168;;;32875:28;;-1:-1:-1;;;;;32875:20:0;;;:28;;;;;32896:6;;32875:28;;;;32896:6;32875:20;:28;;;;;;;;;;;;;;;;;;;;;32827:168;;;32936:47;32972:2;32976:6;32936:22;32945:12;32936:8;:22::i;:::-;-1:-1:-1;;;;;32936:35:0;;:47;:35;:47::i;:::-;32633:369;;;:::o;68485:210::-;-1:-1:-1;;;;;68581:25:0;;68561:17;68581:25;;;:11;:25;;;;;;;68619:68;;68581:25;;68649:37;;68680:4;68649:22;:37::i;:::-;68619:18;:68::i;:::-;68485:210;;:::o;66932:151::-;66998:7;67025:50;67047:16;;67065:9;67025:21;:50::i;63864:1170::-;63925:7;63934;63954:27;63975:5;63954:20;:27::i;:::-;63993:23;64018;64045:26;64066:1;64069;64045:20;:26::i;:::-;63992:79;;;;64083:19;64104:12;64118;64134:55;64156:15;64173;64134:21;:55::i;:::-;64082:107;;;;;;64219:4;64200:23;;;;64253:4;64234:23;;;;64270:59;64290:1;64293;64296:15;64313;64270:19;:59::i;:::-;64581:33;:14;64596:1;64581:17;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;64581:17:0;:31;:33::i;:::-;64577:192;;;64631:40;-1:-1:-1;;;;;64631:34:0;;64666:4;64631:34;:40::i;:::-;64577:192;;;64704:53;64743:6;64752:4;64704:14;64719:1;64704:17;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;64704:17:0;;:53;:30;:53::i;:::-;64785:33;:14;64800:1;64785:17;;;;;;;:33;64781:192;;;64835:40;-1:-1:-1;;;;;64835:34:0;;64870:4;64835:34;:40::i;:::-;64781:192;;;64908:53;64947:6;64956:4;64908:14;64923:1;64908:17;;;;;;;:53;-1:-1:-1;64993:15:0;;-1:-1:-1;65010:15:0;;-1:-1:-1;;;63864:1170:0;;;:::o;65161:526::-;65255:17;;:::i;:::-;65285:18;65306:11;:33;65318:17;65336:1;65318:20;;;;;;;;;;;;;;-1:-1:-1;;;;;65306:33:0;-1:-1:-1;;;;;65306:33:0;;;;;;;;;;;;;65285:54;;65350:18;65371:11;:33;65383:17;65401:1;65383:20;;;;;;;;;;;;;;-1:-1:-1;;;;;65371:33:0;-1:-1:-1;;;;;65371:33:0;;;;;;;;;;;;;65350:54;;65416:23;65441;65468:44;65489:10;65501;65468:20;:44::i;:::-;65415:97;;;;65526:12;65540;65556:55;65578:15;65595;65556:21;:55::i;:::-;65624;;;;;;;;;65632:22;;;;65624:55;;65656:22;;;;65624:55;;;;-1:-1:-1;65624:55:0;;65161:526;-1:-1:-1;;;;;;65161:526:0:o;88455:458::-;88679:16;;;88693:1;88679:16;;;88616;88679;;;;;88616;;;88679;88693:1;88679:16;;;;;;;;;;-1:-1:-1;;88645:50:0;-1:-1:-1;88726:57:0;88750:11;88763:8;88772:1;88763:11;;;;;88776:6;88726:23;:57::i;:::-;88706:14;88721:1;88706:17;;;;;;;;;;;;;;;;;:77;88814:57;88838:11;88851:8;88860:1;88851:11;;88814:57;88794:14;88809:1;88794:17;;;;;;;;;;;;;;;;;:77;88891:14;88455:458;-1:-1:-1;;;;88455:458:0:o;75061:1878::-;75144:7;75226:24;75253:40;75273:19;75253;:40::i;:::-;75226:67;;75304:24;75331:40;75351:19;75331;:40::i;:::-;75304:67;;75382:24;75409:40;75429:19;75409;:40::i;:::-;75382:67;;75542:19;75564:7;:5;:7::i;:::-;75542:29;-1:-1:-1;75582:19:0;75604:33;75542:29;75620:16;75604:15;:33::i;:::-;75582:55;-1:-1:-1;75767:16:0;75763:75;;75807:19;75800:26;;;;;;;;;75763:75;75905:20;75927;75951:17;:15;:17::i;:::-;75904:64;;;;52853:10;76109:11;:34;;:59;;;-1:-1:-1;76147:21:0;;76109:59;76105:268;;;76216:60;76236:12;76250;-1:-1:-1;;;;;76216:19:0;:60::i;:::-;76185:91;-1:-1:-1;76185:91:0;-1:-1:-1;76298:63:0;76321:11;76185:91;;76298:22;:63::i;:::-;76291:70;;;;;;;;;;;76105:268;76385:9;76397:34;:16;76418:12;76397:20;:34::i;:::-;76385:46;-1:-1:-1;76442:9:0;76454:34;:16;76475:12;76454:20;:34::i;:::-;76442:46;-1:-1:-1;76596:16:0;76615:64;76660:18;:1;76666:11;76660:5;:18::i;:::-;76615:40;:1;52853:10;76621:33;;;76615:5;:40::i;:::-;:44;;:64::i;:::-;76596:83;-1:-1:-1;76690:16:0;76709:59;52853:10;76709:34;:16;76730:12;76709:20;:34::i;:::-;:38;;:59::i;:::-;76690:78;;76804:52;76824:8;76834;-1:-1:-1;;;;;76804:19:0;:52::i;:::-;76781:75;;-1:-1:-1;76781:75:0;-1:-1:-1;76876:55:0;76899:11;76781:75;;76876:22;:55::i;:::-;76869:62;75061:1878;-1:-1:-1;;;;;;;;;;;;;75061:1878:0:o;91379:157::-;91510:3;91487:26;-1:-1:-1;;;;;91486:42:0;;91379:157::o;91544:148::-;-1:-1:-1;;;;;91651:33:0;;91544:148::o;81182:639::-;81391:7;81400:17;;:::i;:::-;81430:13;81476:27;81491:8;81430:13;81491:11;;;;81476:7;81484:1;81476:10;;;;;;;;;;;;;;:14;;:27;;;;:::i;:::-;81446;81461:8;81470:1;81461:11;;;;81446:7;81454:1;81446:10;;;;;;;:27;:57;:65;;81510:1;81446:65;;;81506:1;81446:65;81430:81;;;;81522:14;81539:63;81557:11;81570:8;81579:5;81570:15;;;;;;;;;;;81587:7;81595:5;81587:14;;;;;;;;;;;;;;81539:17;:63::i;:::-;81522:80;;81615:28;;:::i;:::-;:158;;;;;;;;;;81661:43;81671:11;81684:8;-1:-1:-1;81684:11:0;;;;;81697:6;81661:9;:43::i;:::-;81615:158;;;;81719:43;81729:11;81742:8;81751:1;81742:11;;81719:43;81615:158;;81794:6;;;;-1:-1:-1;81182:639:0;;-1:-1:-1;;;;;;;81182:639:0:o;68848:469::-;68912:28;68943:14;68958:1;68943:17;;;;;;;;;;;;;;;;;69002:14;:17;;-1:-1:-1;;;;;68943:17:0;;;;-1:-1:-1;69002:14:0;68943:17;;69002;;;;;;;;;;;;;;;-1:-1:-1;;;;;69002:17:0;;;;-1:-1:-1;69092:30:0;;:28;;;:30::i;:::-;:42;;69133:1;69092:42;;;69125:5;69092:42;69049:39;-1:-1:-1;;;;;69049:24:0;;69082:4;69049:24;:39::i;:::-;:86;69030:105;;69146:16;69208:30;:14;-1:-1:-1;;;;;69208:28:0;;:30::i;:::-;:42;;69249:1;69208:42;;;69241:5;69208:42;69165:39;-1:-1:-1;;;;;69165:24:0;;69198:4;69165:24;:39::i;:::-;:86;69146:105;;69264:45;69284:1;69287;69290:8;69300;69264:19;:45::i;:::-;68848:469;;;;;:::o;42592:133::-;42684:9;;:33;;;-1:-1:-1;;;42684:33:0;;;;;;;;;;42657:7;;-1:-1:-1;;;;;42684:9:0;;:19;;:33;;;;;;;;;;;;;;:9;:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;42684:33:0;;42592:133;-1:-1:-1;;42592:133:0:o;67156:306::-;67244:7;67253;67282:8;67294:1;67282:13;:30;;;;;67299:8;67311:1;67299:13;67282:30;67281:68;;;;67318:8;67330:1;67318:13;:30;;;;;67335:8;67347:1;67335:13;67318:30;67273:101;;;;;-1:-1:-1;;;67273:101:0;;;;;;;;;;;;-1:-1:-1;;;67273:101:0;;;;;;;;;;;;;;;67394:60;67417:16;;67435:8;67445;67394:22;:60::i;:::-;67387:67;;;;67156:306;;;;;:::o;55180:87::-;55234:10;:8;:10::i;:::-;55233:11;55225:34;;;;;-1:-1:-1;;;55225:34:0;;;;;;;;;;;;-1:-1:-1;;;55225:34:0;;;;;;;;;;;;;;37837:162;-1:-1:-1;;;;;37915:18:0;;;;;;:43;;-1:-1:-1;;;;;;37937:21:0;;37953:4;37937:21;;37915:43;37907:84;;;;;-1:-1:-1;;;37907:84:0;;;;;;;;;;;;;;;;;;;;;;;;;;;56217:143;56293:28;;;56303:18;56293:28;56285:67;;;;;-1:-1:-1;;;56285:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;54918:86;54969:10;:8;:10::i;:::-;54961:35;;;;;-1:-1:-1;;;54961:35:0;;;;;;;;;;;;-1:-1:-1;;;54961:35:0;;;;;;;;;;;;;;87237:850;87399:4;87424:29;87445:7;87424:20;:29::i;:::-;:43;;;;;87466:1;87457:6;:10;87424:43;87416:71;;;;;-1:-1:-1;;;87416:71:0;;;;;;;;;;;;-1:-1:-1;;;87416:71:0;;;;;;;;;;;;;;;87500:18;87521:11;:24;87533:8;87542:1;87533:11;;;;;;;;;;;;;;-1:-1:-1;;;;;87521:24:0;-1:-1:-1;;;;;87521:24:0;;;;;;;;;;;;;87500:45;;87556:18;87577:11;:24;87589:8;87598:1;87589:11;;;;;;;;;;;;;;-1:-1:-1;;;;;87577:24:0;-1:-1:-1;;;;;87577:24:0;;;;;;;;;;;;;87556:45;;87618:10;87632:1;87618:15;:34;;;;;87637:10;87651:1;87637:15;87618:34;87614:362;;;87669:30;87702:8;87711:1;87702:11;;;;;;;;;;;;;;87669:44;;87742:8;87751:1;87742:11;;;;;;;;;;;;;;87728:8;87737:1;87728:11;;;;;;;;;;;;;:25;-1:-1:-1;;;;;87728:25:0;;;-1:-1:-1;;;;;87728:25:0;;;;;87782:16;87768:8;87777:1;87768:11;;;;;;;;;;;;;:30;-1:-1:-1;;;;;87768:30:0;;;-1:-1:-1;;;;;87768:30:0;;;;;87815:25;87843:7;87851:1;87843:10;;;;;;;;;;;;;;87815:38;;87881:7;87889:1;87881:10;;;;;;;;;;;;;;87868:7;87876:1;87868:10;;;;;;;;;;;;;:23;;;;;87919:17;87906:7;87914:1;87906:10;;;;;;;;;;;;;:30;;;;;87960:4;87953:11;;;;;;;;87614:362;87996:10;88010:1;87996:15;:34;;;;;88015:10;88029:1;88015:15;87996:34;87988:66;;;;;-1:-1:-1;;;87988:66:0;;;;;;;;;;;;-1:-1:-1;;;87988:66:0;;;;;;;;;;;;;;;-1:-1:-1;88074:5:0;;87237:850;-1:-1:-1;;;;;87237:850:0:o;32066:142::-;-1:-1:-1;;;;;32164:36:0;;31913:42;32164:36;32066:142;;;:::o;46690:348::-;46832:13;;46761:7;;;;;46856:103;46880:6;46876:1;:10;46856:103;;;46923:24;46937:6;46944:1;46937:9;;;;;;;;;;;;;;46923:13;:24::i;:::-;46908:39;;;;46888:3;;46856:103;;;;47028:1;46990:35;47005:11;47018:6;46990:14;:35::i;:::-;:39;46984:2;46976:54;;46690:348;-1:-1:-1;;;;46690:348:0:o;2834:179::-;2892:7;2924:5;;;2948:6;;;;2940:46;;;;;-1:-1:-1;;;2940:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;33238:317;33401:11;;;:42;;;33416:27;33430:12;33416:13;:27::i;:::-;33397:81;;;33460:7;;33397:81;33490:57;33530:4;33536:2;33540:6;33490:22;33499:12;33490:8;:22::i;:::-;-1:-1:-1;;;;;33490:39:0;;:57;;:39;:57::i;:::-;33238:317;;;;:::o;67977:386::-;-1:-1:-1;;;;;68158:13:0;:28;;:60;;;;;-1:-1:-1;;;;;68190:13:0;:28;;68158:60;68150:101;;;;;-1:-1:-1;;;68150:101:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;68283:72;68306:13;68321:8;68331:13;68346:8;68283:22;:72::i;:::-;68264:16;:91;-1:-1:-1;;;;67977:386:0:o;93295:413::-;93427:7;93464:1;93455:6;:10;93447:41;;;;;-1:-1:-1;;;93447:41:0;;;;;;;;;;;;-1:-1:-1;;;93447:41:0;;;;;;;;;;;;;;;93517:1;93507:7;:11;93499:51;;;;;-1:-1:-1;;;93499:51:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;93499:51:0;;;;;;;;;;;;;;;93605:11;93601:52;;-1:-1:-1;93640:1:0;93633:8;;93601:52;93693:7;93672:18;:6;93683;93672:10;:18::i;:::-;:28;;;;;;;93295:413;-1:-1:-1;;;;93295:413:0:o;92872:415::-;92996:7;93033:1;93024:6;:10;93016:41;;;;;-1:-1:-1;;;93016:41:0;;;;;;;;;;;;-1:-1:-1;;;93016:41:0;;;;;;;;;;;;;;;93086:1;93076:7;:11;93068:51;;;;;-1:-1:-1;;;93068:51:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;93068:51:0;;;;;;;;;;;;;;;93174:11;93170:52;;-1:-1:-1;93209:1:0;93202:8;;93170:52;93269:6;93264:1;93242:19;:6;93253:7;93242:10;:19::i;:::-;:23;93241:34;;;;;;93278:1;93241:38;93234:45;;92872:415;;;;;:::o;70519:465::-;70756:7;70765;70785:20;70808:69;70834:13;70849;70864:12;70808:25;:69::i;:::-;70785:92;;70890:11;70904:27;70918:12;70904:13;:27::i;:::-;70952:18;;;;;;;-1:-1:-1;70519:465:0;;-1:-1:-1;;;;;;;70519:465:0:o;3296:158::-;3354:7;3387:1;3382;:6;;3374:49;;;;;-1:-1:-1;;;3374:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;3441:5:0;;;3296:158::o;66663:174::-;66814:14;;66733:7;;66760:69;;66814:14;-1:-1:-1;;;66814:14:0;;;;;36563:7;66797:31;;;66760:69;;;:32;;:12;;:16;:32;:::i;:::-;:36;;:69::i;92344:520::-;92517:7;92568:1;92545:20;:24;92537:64;;;;;-1:-1:-1;;;92537:64:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;92537:64:0;;;;;;;;;;;;;;;92635:20;92620:12;:35;92612:66;;;;;-1:-1:-1;;;92612:66:0;;;;;;;;;;;;-1:-1:-1;;;92612:66:0;;;;;;;;;;;;;;;92695:17;92691:58;;-1:-1:-1;92736:1:0;92729:8;;92691:58;92816:35;;;92810:1;92769:38;:20;92839:12;92769:24;:38::i;71907:2075::-;72117:7;72180:26;:24;:26::i;:::-;-1:-1:-1;;;;;72238:24:0;;;72219:16;72238:24;;;:11;:24;;;;;;;72292;;;;;;;;;72219:16;72378:40;72238:24;72292;72378:20;:40::i;:::-;72329:89;;;;72514:20;72536:11;72551:165;72585:11;72611;72637:13;72665;72693:12;72551:19;:165::i;:::-;72513:203;;;;72797:12;72813:1;72797:17;;72789:52;;;;;-1:-1:-1;;;72789:52:0;;;;;;;;;;;;-1:-1:-1;;;72789:52:0;;;;;;;;;;;;;;;72944:13;72929:12;:28;72922:36;;;;73034:27;73064:36;-1:-1:-1;;;;;73064:21:0;;73094:4;73064:21;:36::i;:::-;73034:66;;73115:27;:11;-1:-1:-1;;;;;73115:25:0;;:27::i;:::-;73111:257;;;73180:12;73167:9;:25;73159:61;;;;;-1:-1:-1;;;73159:61:0;;;;;;;;;;;;-1:-1:-1;;;73159:61:0;;;;;;;;;;;;;;;73111:257;;;73261:9;:14;:72;;;;-1:-1:-1;73321:12:0;73279:38;:19;73303:13;73279:23;:38::i;:::-;:54;;73261:72;73253:103;;;;;-1:-1:-1;;;73253:103:0;;;;;;;;;;;;-1:-1:-1;;;73253:103:0;;;;;;;;;;;;;;;73418:90;73438:8;73448;73458:19;73495:12;73479:13;:28;73418:19;:90::i;:::-;73591:51;-1:-1:-1;;;;;73591:24:0;;73616:11;73629:12;73591:24;:51::i;:::-;73697:91;73722:11;73735;73748:6;73756:12;73770;73784:3;73697:24;:91::i;:::-;73835:107;73866:11;73879;73892:19;73929:12;73913:13;:28;73835:30;:107::i;:::-;-1:-1:-1;73962:12:0;;71907:2075;-1:-1:-1;;;;;;;;;;;71907:2075:0:o;34117:131::-;34226:12;34117:131::o;19021:177::-;19131:58;;;-1:-1:-1;;;;;19131:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;19131:58:0;-1:-1:-1;;;19131:58:0;;;19104:86;;19124:5;;19104:19;:86::i;67558:345::-;-1:-1:-1;;;;;67649:7:0;:22;;67641:63;;;;;-1:-1:-1;;;67641:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;67717:20;67740:54;67762:16;;67784:9;67780:1;:13;67740:21;:54::i;:::-;67717:77;;67824:71;67847:7;67856:9;67867:12;67885:9;67881:1;:13;67824:22;:71::i;:::-;67805:16;:90;-1:-1:-1;;;67558:345:0:o;90122:199::-;90205:7;90232:2;90238:1;90232:7;:18;;;;90243:2;90249:1;90243:7;90232:18;90225:26;;;;-1:-1:-1;90294:3:0;-1:-1:-1;;90284:6:0;;90283:14;90270:28;;;-1:-1:-1;;;;;90269:44:0;90122:199;;;;:::o;94402:826::-;94546:12;94573:7;94595;94630:17;94650:35;94661:23;;94650:10;:35::i;:::-;94630:55;;94696:17;94716:45;94745:15;94727;:33;94716:10;:45::i;:::-;94696:65;;94791:9;94778;:22;94774:94;;94846:1;94851;94854;94817:39;;;;;;;;;;94774:94;94881:29;94912:17;94950:28;-1:-1:-1;;;94950:10:0;:28::i;:::-;-1:-1:-1;;;;;94933:77:0;;:79;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;94933:79:0;;;;;;;;;-1:-1:-1;94933:79:0;-1:-1:-1;95035:36:0;;;;95036:21;;;95035:36;;36563:7;95094:26;;;94933:79;;95159:29;;95094:26;;95159:22;;:15;;95035:36;;95159:19;:22;:::i;:29::-;95190;95217:1;95190:22;:15;95210:1;95190:19;:22::i;:29::-;95133:87;;;;;;;;;;;;94402:826;;;;;;:::o;12451:397::-;12566:6;12541:21;:31;;12533:73;;;;;-1:-1:-1;;;12533:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;12716:35;;12698:12;;-1:-1:-1;;;;;12716:14:0;;;12739:6;;12698:12;12716:35;12698:12;12716:35;12739:6;12716:14;:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12697:54;;;12770:7;12762:78;;;;-1:-1:-1;;;12762:78:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;93716:611;93854:7;93891:1;93882:6;:10;93874:41;;;;;-1:-1:-1;;;93874:41:0;;;;;;;;;;;;-1:-1:-1;;;93874:41:0;;;;;;;;;;;;;;;93944:1;93934:7;:11;93926:51;;;;;-1:-1:-1;;;93926:51:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;93926:51:0;;;;;;;;;;;;;;;94006:6;93996;:16;;93988:47;;;;;-1:-1:-1;;;93988:47:0;;;;;;;;;;;;-1:-1:-1;;;93988:47:0;;;;;;;;;;;;;;;94090:11;94086:52;;-1:-1:-1;94125:1:0;94118:8;;94086:52;94223:6;94213;:16;94209:63;;;-1:-1:-1;94253:7:0;94246:14;;94209:63;94313:6;94291:19;:6;94302:7;94291:10;:19::i;91230:141::-;91360:3;91337:26;;91230:141::o;51959:98::-;52034:15;51959:98;:::o;44315:400::-;44429:7;;44490:1;44493;44510:10;;;;:24;;;44531:3;44524:4;:10;44510:24;44506:104;;;44566:32;44582:4;44588;44594:3;44566:15;:32::i;:::-;44551:47;;-1:-1:-1;44551:47:0;-1:-1:-1;44506:104:0;44632:4;44624;:12;44620:64;;44661:4;;-1:-1:-1;44667:4:0;-1:-1:-1;44653:19:0;;44620:64;-1:-1:-1;44702:1:0;;;;-1:-1:-1;44315:400:0;-1:-1:-1;;;;;44315:400:0:o;90866:356::-;91020:7;52790:9;91047:12;:26;;:57;;;;;-1:-1:-1;;;;;91077:12:0;:27;;91047:57;:88;;;;;-1:-1:-1;;;;;91108:12:0;:27;;91047:88;91040:96;;;;-1:-1:-1;91171:3:0;91155:19;;;91195:3;91179:19;;;91154:45;:60;;90866:356;;;;;:::o;3713:220::-;3771:7;3795:6;3791:20;;-1:-1:-1;3810:1:0;3803:8;;3791:20;3834:5;;;3838:1;3834;:5;:1;3858:5;;;;;:10;3850:56;;;;-1:-1:-1;;;3850:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;90606:252;90738:7;90747;90775:36;90797:8;90807:3;90775:21;:36::i;:::-;90813;90835:8;90845:3;90813:21;:36::i;88190:142::-;88268:4;88305:1;88292:7;88300:1;88292:10;;;;;;;;;;;;;;:14;:32;;;;;88323:1;88310:7;88318:1;88310:10;;;;;;;;;;;;;;:14;88285:39;;88190:142;;;:::o;47142:202::-;47199:7;;47263:1;47243:75;47266:8;;47243:75;;47303:3;;;;;;47284:2;47276:10;;47243:75;;;-1:-1:-1;47335:1:0;47142:202;-1:-1:-1;;47142:202:0:o;47531:119::-;47600:7;47641:1;47636;47641;47632:5;47628:1;:9;47627:15;;;;;;;47531:119;-1:-1:-1;;;47531:119:0:o;19206:205::-;19334:68;;;-1:-1:-1;;;;;19334:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;19334:68:0;-1:-1:-1;;;19334:68:0;;;19307:96;;19327:5;;19307:19;:96::i;90329:269::-;90488:7;90554:36;90576:8;90586:3;90554:21;:36::i;:::-;90515;90537:8;90547:3;90515:21;:36::i;:::-;:75;;90329:269;-1:-1:-1;;;;;90329:269:0:o;91944:392::-;92117:7;92168:1;92145:20;:24;:52;;;;;92196:1;92173:20;:24;92145:52;92137:92;;;;;-1:-1:-1;;;92137:92:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;92137:92:0;;;;;;;;;;;;;;;92290:38;:20;92315:12;92290:24;:38::i;:::-;92249;:20;92274:12;92249:24;:38::i;66413:151::-;66524:14;;66480:7;;36563;;66507:32;;:12;;-1:-1:-1;;;66524:14:0;;66507:49;66524:14;;;;66507:16;:32;:::i;:::-;:49;;;;;;;66413:151;-1:-1:-1;;66413:151:0:o;4411:153::-;4469:7;4501:1;4497;:5;4489:44;;;;;-1:-1:-1;;;4489:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;4555:1;4551;:5;;;;74646:298;74728:16;;74701:24;74782:40;74728:16;74782:22;:40::i;:::-;74755:67;;74857:16;74837;:36;74833:104;;74890:16;:35;-1:-1:-1;74646:298:0:o;69396:351::-;69648:91;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;69648:91:0;;;;;;;;;;;;;;;;;;;;;69396:351;;;;;;:::o;89030:867::-;89318:7;;89414:23;;;-1:-1:-1;;;89414:23:0;;;;-1:-1:-1;;;;;89318:7:0;;;;89280:18;;89318:7;;89414:21;;:23;;;;;;;;;;;;;;;89318:7;89414:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;89414:23:0;89523:89;;;;;;89414:23;89523:89;;;;;;;89414:23;;-1:-1:-1;;;;;;89523:89:0;;;;;;;;-1:-1:-1;;;;;;;;;;;89523:89:0;;;;;;;89739:11;-1:-1:-1;;;;;89695:89:0;89719:9;-1:-1:-1;;;;;89695:89:0;-1:-1:-1;;;;;;;;;;;89753:13:0;89768:15;89695:89;;;;;;;;;;;;;;;;;;;;;;;;89844:11;-1:-1:-1;;;;;89800:89:0;89824:9;-1:-1:-1;;;;;89800:89:0;-1:-1:-1;;;;;;;;;;;89858:13:0;89873:15;89800:89;;;;;;;;;;;;;;;;;;;;;;;;89030:867;;;;;;:::o;21326:761::-;21750:23;21776:69;21804:4;21776:69;;;;;;;;;;;;;;;;;21784:5;-1:-1:-1;;;;;21776:27:0;;;:69;;;;;:::i;:::-;21860:17;;21750:95;;-1:-1:-1;21860:21:0;21856:224;;22002:10;21991:30;;;;;;;;;;;;;;;-1:-1:-1;21991:30:0;21983:85;;;;-1:-1:-1;;;21983:85:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;91817:119;91870:7;91901:1;91897;:5;:31;;91927:1;91897:31;;;91905:19;91922:1;91905:16;:19::i;44812:313::-;44931:7;44940;44969:1;44964;:6;44960:72;;44994:26;45008:1;45011;45014:5;44994:13;:26::i;:::-;44987:33;;;;;;44960:72;45043:9;45054;45067:26;45081:1;45084;45087:5;45067:13;:26::i;:::-;45042:51;;;-1:-1:-1;44812:313:0;-1:-1:-1;;;;;;44812:313:0:o;89905:209::-;89987:7;-1:-1:-1;;;;;90014:7:0;:22;;:46;;;;;90041:2;90047:1;90041:7;:18;;;;90052:2;90058:1;90052:7;90041:18;90007:54;;;;-1:-1:-1;;;90092:6:0;90102:3;90091:14;90079:27;;89905:209::o;14012:195::-;14115:12;14147:52;14169:6;14177:4;14183:1;14186:12;14147:21;:52::i;:::-;14140:59;14012:195;-1:-1:-1;;;;14012:195:0:o;43194:257::-;43249:7;;43287:1;43281:3;:7;43291:1;43281:11;43269:23;;43303:9;43331:1;43326;43320:3;:7;;;;;;43316:1;:11;43315:17;;;;;;43303:29;;43343:82;43354:1;43350;:5;43343:82;;;43376:1;43372:5;;43412:1;43407;43401:3;:7;;;;;;43397:1;:11;43396:17;;;;;;43392:21;;43343:82;;45246:1071;45363:7;45372;45392:14;45423:5;-1:-1:-1;;45409:19:0;;;;;;45392:36;;45447:6;45443:1;:10;45439:158;;;45470:9;45487:6;45496:1;45487:10;45482:1;:16;;;;;;45501:1;45482:20;45470:32;;45522:1;45517:6;;;;;;;;;45584:1;45579:6;;;;;;;;;45439:158;;45616:1;45611;:6;45607:608;;45649:9;;;45634:12;45688:15;45649:1;45701;45688:9;:15::i;:::-;45673:30;;45746:1;45738:4;:9;45734:238;;45811:9;45823:20;45832:4;45838;45823:8;:20::i;:::-;45811:32;-1:-1:-1;;;45915:9:0;;;;-1:-1:-1;45943:13:0;;-1:-1:-1;;45943:13:0;45734:238;46011:1;46002:5;;;46001:11;45997:1;:15;45990:4;:22;45986:131;;;46041:1;46044:5;46033:17;;;;;;;;;45986:131;46139:1;46150;46142:5;:9;46131:21;;;;;;;;;45607:608;-1:-1:-1;;46241:1:0;46233:9;;;;;;-1:-1:-1;45246:1071:0;-1:-1:-1;;45246:1071:0:o;15064:530::-;15191:12;15249:5;15224:21;:30;;15216:81;;;;-1:-1:-1;;;15216:81:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15316:18;15327:6;15316:10;:18::i;:::-;15308:60;;;;;-1:-1:-1;;;15308:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;15442:12;15456:23;15483:6;-1:-1:-1;;;;;15483:11:0;15503:5;15511:4;15483:33;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;15483:33:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15441:75;;;;15534:52;15552:7;15561:10;15573:12;15534:17;:52::i;:::-;15527:59;15064:530;-1:-1:-1;;;;;;;15064:530:0:o;50917:103::-;51007:5;;50917:103::o;46442:127::-;46505:7;46559:1;46555;:5;46551:1;:9;46545:1;46541;:5;;;;;;46540:21;;;;;;46536:1;46532;:5;;;;;;:29;;46442:127;-1:-1:-1;;;46442:127:0:o;11094:422::-;11461:20;11500:8;;;11094:422::o;17604:742::-;17719:12;17748:7;17744:595;;;-1:-1:-1;17779:10:0;17772:17;;17744:595;17893:17;;:21;17889:439;;18156:10;18150:17;18217:15;18204:10;18200:2;18196:19;18189:44;18104:148;18299:12;18292:20;;-1:-1:-1;;;18292:20:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;:::o
Swarm Source
ipfs://842dacb7e388376021cadeda051cec41f1b8c334339cbba7a1be95a5308eee91
Loading...
Loading
Loading...
Loading
OVERVIEW
Bancor converter address.Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.