Contract Overview
Balance:
0 AVAX
AVAX Value:
$0.00
My Name Tag:
Not Available, login to update
Txn Hash | Method |
Block
|
From
|
To
|
Value | [Txn Fee] | |||
---|---|---|---|---|---|---|---|---|---|
0xb94cb02d46e1b48109af8f2b18ea550783c1a8ab47e4da15da30ca28b82754b9 | 0x60806040 | 14692574 | 7 days 14 hrs ago | 0xc783ea213810f1d3429bd9c1bfd2ab20f0e1ead1 | IN | Create: JoeLiquidator | 0 AVAX | 0.103421559051 |
[ Download CSV Export ]
Contract Name:
JoeLiquidator
Compiler Version
v0.8.9+commit.e5eed63a
Contract Source Code (Solidity)
/** *Submitted for verification at snowtrace.io on 2022-05-14 */ // File: github/0xnivek/joe-liquidator/liquidator/contracts/libraries/SafeMath.sol pragma solidity ^0.8.3; // From https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeMath.sol /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler * now has built in overflow checking. */ 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) { unchecked { 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) { unchecked { 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) { unchecked { // 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) { unchecked { 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) { unchecked { 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) { return a + b; } /** * @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) { 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) { return a * b; } /** * @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. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { 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) { 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) { unchecked { 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. * * 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) { unchecked { 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) { unchecked { require(b > 0, errorMessage); return a % b; } } } // File: github/0xnivek/joe-liquidator/liquidator/contracts/lending/Exponential.sol pragma solidity ^0.8.3; /** * @title Exponential module for storing fixed-precision decimals * @author Compound * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places. * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is: * `Exp({mantissa: 5100000000000000000})`. */ contract Exponential { uint256 constant expScale = 1e18; uint256 constant doubleScale = 1e36; uint256 constant halfExpScale = expScale / 2; uint256 constant mantissaOne = expScale; struct Exp { uint256 mantissa; } /** * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer. */ function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) { Exp memory product = mul_(a, scalar); return truncate(product); } function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) { return Exp({mantissa: mul_(a.mantissa, b)}); } function mul_(uint256 a, uint256 b) internal pure returns (uint256) { return mul_(a, b, "multiplication overflow"); } function mul_( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { if (a == 0 || b == 0) { return 0; } uint256 c = a * b; require(c / a == b, errorMessage); return c; } /** * @dev Truncates the given exp to a whole number value. * For example, truncate(Exp{mantissa: 15 * expScale}) = 15 */ function truncate(Exp memory exp) internal pure returns (uint256) { // Note: We are not using careful math here as we're performing a division that cannot fail return exp.mantissa / expScale; } } // File: github/0xnivek/joe-liquidator/liquidator/contracts/lending/JoeRouter02.sol pragma solidity ^0.8.3; interface JoeRouter02 { function getAmountsIn(uint256 amountOut, address[] memory path) external view returns (uint256[] memory amounts); function getAmountsOut(uint256 amountIn, address[] memory path) external view returns (uint256[] memory amounts); function swapExactTokensForTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function swapExactTokensForAVAX( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function swapExactAVAXForTokens( uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external payable returns (uint256[] memory amounts); } // File: github/0xnivek/joe-liquidator/liquidator/contracts/interfaces/WAVAXInterface.sol pragma solidity ^0.8.3; interface WAVAXInterface { function deposit() external payable; function transfer(address to, uint256 value) external returns (bool); function withdraw(uint256) external; function balanceOf(address account) external view returns (uint256); function approve(address guy, uint256 wad) external returns (bool); } // File: github/0xnivek/joe-liquidator/liquidator/contracts/interfaces/ERC3156FlashBorrowerInterface.sol pragma solidity ^0.8.3; interface ERC3156FlashBorrowerInterface { /** * @dev Receive a flash loan. * @param initiator The initiator of the loan. * @param token The loan currency. * @param amount The amount of tokens lent. * @param fee The additional amount of tokens to repay. * @param data Arbitrary data structure, intended to contain user-defined parameters. * @return The keccak256 hash of "ERC3156FlashBorrower.onFlashLoan" */ function onFlashLoan( address initiator, address token, uint256 amount, uint256 fee, bytes calldata data ) external returns (bytes32); } // File: github/0xnivek/joe-liquidator/liquidator/contracts/lending/JTokenInterfaces.sol pragma solidity ^0.8.3; interface JTokenStorage { function totalBorrows() external view returns (uint256); /** * @notice Block timestamp that interest was last accrued at */ function accrualBlockTimestamp() external view returns (uint256); } interface JTokenInterface is JTokenStorage { function balanceOf(address owner) external view returns (uint256); function balanceOfUnderlying(address owner) external view returns (uint256); function borrowRatePerSecond() external view returns (uint256); function supplyRatePerSecond() external view returns (uint256); function borrowBalanceCurrent(address account) external view returns (uint256); function borrowBalanceStored(address account) external view returns (uint256); function accrueInterest() external returns (uint256); function exchangeRateStored() external view returns (uint256); } interface JToken is JTokenInterface {} interface JErc20Storage { function underlying() external returns (address); } interface JErc20Interface is JErc20Storage { function liquidateBorrow( address borrower, uint256 repayAmount, JTokenInterface jTokenCollateral ) external returns (uint256); function redeem(uint256 redeemTokens) external returns (uint256); function mint(uint256 mintAmount) external returns (uint256); function borrow(uint256 borrowAmount) external returns (uint256); } interface JWrappedNativeInterface is JErc20Interface { function flashLoan( ERC3156FlashBorrowerInterface receiver, address initiator, uint256 amount, bytes calldata data ) external returns (bool); function liquidateBorrowNative( address borrower, JTokenInterface jTokenCollateral ) external payable returns (uint256); function redeemNative(uint256 redeemTokens) external returns (uint256); function mintNative() external payable returns (uint256); function borrowNative(uint256 borrowAmount) external returns (uint256); } interface JWrappedNativeDelegator is JTokenInterface, JWrappedNativeInterface {} interface JCollateralCapErc20Interface is JErc20Interface { function flashLoan( ERC3156FlashBorrowerInterface receiver, address initiator, uint256 amount, bytes calldata data ) external returns (bool); } interface JCollateralCapErc20Delegator is JTokenInterface, JCollateralCapErc20Interface {} // File: github/0xnivek/joe-liquidator/liquidator/contracts/lending/PriceOracle.sol pragma solidity ^0.8.3; interface PriceOracle { /** * @notice Get the underlying price of a jToken asset * @param jToken The jToken to get the underlying price of * @return The underlying asset price mantissa (scaled by 1e18). * Zero means the price is unavailable. */ function getUnderlyingPrice(JToken jToken) external view returns (uint256); } // File: github/0xnivek/joe-liquidator/liquidator/contracts/lending/JoetrollerInterface.sol pragma solidity ^0.8.3; interface JoetrollerV1Storage { /** * @notice Oracle which gives the price of any given asset */ function oracle() external view returns (PriceOracle); /** * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow */ function closeFactorMantissa() external view returns (uint256); /** * @notice Multiplier representing the discount on collateral that a liquidator receives */ function liquidationIncentiveMantissa() external view returns (uint256); } interface Joetroller is JoetrollerV1Storage { function enterMarkets(address[] calldata jTokens) external returns (uint256[] memory); function isMarketListed(address jTokenAddress) external view returns (bool); function checkMembership(address account, JToken jToken) external view returns (bool); function getAccountLiquidity(address account) external view returns ( uint256, uint256, uint256 ); function liquidateBorrowAllowed( address jTokenBorrowed, address jTokenCollateral, address liquidator, address borrower, uint256 repayAmount ) external returns (uint256); function repayBorrowAllowed( address jToken, address payer, address borrower, uint256 repayAmount ) external returns (uint256); } // File: github/0xnivek/joe-liquidator/liquidator/contracts/interfaces/ERC3156FlashLenderInterface.sol pragma solidity ^0.8.3; interface ERC3156FlashLenderInterface { /** * @dev The amount of currency available to be lent. * @param token The loan currency. * @return The amount of `token` that can be borrowed. */ function maxFlashLoan(address token) external view returns (uint256); /** * @dev The fee to be charged for a given loan. * @param token The loan currency. * @param amount The amount of tokens lent. * @return The amount of `token` to be charged for the loan, on top of the returned principal. */ function flashFee(address token, uint256 amount) external view returns (uint256); /** * @dev Initiate a flash loan. * @param receiver The receiver of the tokens in the loan, and the receiver of the callback. * @param token The loan currency. * @param amount The amount of tokens lent. * @param data Arbitrary data structure, intended to contain user-defined parameters. */ function flashLoan( ERC3156FlashBorrowerInterface receiver, address token, uint256 amount, bytes calldata data ) external returns (bool); } // File: github/0xnivek/joe-liquidator/liquidator/contracts/interfaces/ERC20Interface.sol pragma solidity ^0.8.3; interface ERC20 { function approve(address spender, uint256 amount) external; function balanceOf(address account) external view returns (uint256); } // File: github/0xnivek/joe-liquidator/liquidator/contracts/JoeLiquidator.sol pragma solidity ^0.8.3; // import "hardhat/console.sol"; /** * @notice Contract that performs liquidation of underwater accounts in the jToken markets */ contract JoeLiquidator is ERC3156FlashBorrowerInterface, Exponential { using SafeMath for uint256; /// @notice Addresses of Banker Joe contracts address public joetrollerAddress; address public joeRouter02Address; address public jUSDCAddress; address public jWETHAddress; /// @notice Addresses of ERC20 contracts address public constant WAVAX = 0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7; address public constant WETH = 0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB; address public constant USDC = 0xA7D7079b0FEaD91F3e65f86E8915Cb59c1a4C664; struct LiquidationLocalVars { address jRepayTokenAddress; address jSeizeTokenAddress; address borrowerToLiquidate; uint256 repayAmount; } /// @notice Emitted upon successful liquidation event LiquidationEvent( address indexed _borrowerLiquidated, address _jRepayToken, address _jSeizeToken, uint256 _repayAmount, uint256 _profitedAVAX ); constructor( address _joetrollerAddress, address _joeRouter02Address, address _jUSDCAddress, address _jWETHAddress ) { joetrollerAddress = _joetrollerAddress; joeRouter02Address = _joeRouter02Address; jUSDCAddress = _jUSDCAddress; jWETHAddress = _jWETHAddress; } /// @dev Need to implement receive function in order for this contract to receive AVAX. /// We need to receive AVAX when we liquidating a native borrow position. receive() external payable {} /** * @notice Ensure that we can liquidate the borrower * @dev A borrower is liquidatable if: * 1. Their `liquidity` is zero * 2. Their `shortfall` is non-zero */ modifier isLiquidatable(address _borrowerToLiquidate) { (, uint256 liquidity, uint256 shortfall) = Joetroller(joetrollerAddress) .getAccountLiquidity(_borrowerToLiquidate); require( liquidity == 0, "JoeLiquidator: Cannot liquidate account with non-zero liquidity" ); require( shortfall != 0, "JoeLiquidator: Cannot liquidate account with zero shortfall" ); _; } /** * @notice Liquidates a borrower with a given jToken to repay and * jToken to seize. * @param _borrowerToLiquidate: Address of the borrower to liquidate * @param _jRepayTokenAddress: Address of the jToken to repay * @param _jSeizeTokenAddress: Address of the jToken to seize */ function liquidate( address _borrowerToLiquidate, address _jRepayTokenAddress, address _jSeizeTokenAddress ) external isLiquidatable(_borrowerToLiquidate) { uint256 amountToRepay = getAmountToRepay( _borrowerToLiquidate, _jRepayTokenAddress, _jSeizeTokenAddress ); doFlashloan( _borrowerToLiquidate, _jRepayTokenAddress, _jSeizeTokenAddress, amountToRepay ); } /** * @dev Calculates amount of the borrow position to repay * @param _borrowerToLiquidate: Address of the borrower to liquidate * @param _jRepayTokenAddress: Address of the jToken to repay * @param _jSeizeTokenAddress: Address of the jToken to seize * @return the amount of jRepayToken to repay */ function getAmountToRepay( address _borrowerToLiquidate, address _jRepayTokenAddress, address _jSeizeTokenAddress ) internal view returns (uint256) { // Inspired from https://github.com/haydenshively/Nantucket/blob/538bd999c9cc285efb403c876e5f4c3d467a2d68/contracts/FlashLiquidator.sol#L121-L144 Joetroller joetroller = Joetroller(joetrollerAddress); PriceOracle priceOracle = joetroller.oracle(); uint256 closeFactor = joetroller.closeFactorMantissa(); uint256 liquidationIncentive = joetroller .liquidationIncentiveMantissa(); uint256 repayTokenUnderlyingPrice = priceOracle.getUnderlyingPrice( JToken(_jRepayTokenAddress) ); uint256 seizeTokenUnderlyingPrice = priceOracle.getUnderlyingPrice( JToken(_jSeizeTokenAddress) ); uint256 maxRepayAmount = (JTokenInterface(_jRepayTokenAddress) .borrowBalanceStored(_borrowerToLiquidate) * closeFactor) / uint256(10**18); uint256 maxSeizeAmount = (_getBalanceOfUnderlying( _jSeizeTokenAddress, _borrowerToLiquidate ) * uint256(10**18)) / liquidationIncentive; uint256 maxRepayAmountInUSD = maxRepayAmount * repayTokenUnderlyingPrice; uint256 maxSeizeAmountInUSD = maxSeizeAmount * seizeTokenUnderlyingPrice; uint256 maxAmountInUSD = (maxRepayAmountInUSD < maxSeizeAmountInUSD) ? maxRepayAmountInUSD : maxSeizeAmountInUSD; return maxAmountInUSD / repayTokenUnderlyingPrice; } /** * @dev Gets an account's balanceOfUnderlying (i.e. supply balance) for a given jToken * @param _jTokenAddress The address of a jToken contract * @param _account The address the account to lookup * @return the account's balanceOfUnderlying in jToken */ function _getBalanceOfUnderlying(address _jTokenAddress, address _account) internal view returns (uint256) { // From https://github.com/traderjoe-xyz/joe-lending/blob/main/contracts/JToken.sol#L128 JTokenInterface jToken = JTokenInterface(_jTokenAddress); Exp memory exchangeRate = Exp({mantissa: jToken.exchangeRateStored()}); return mul_ScalarTruncate(exchangeRate, jToken.balanceOf(_account)); } /** * @notice Performs flash loan from: * - jWETH if _jRepayTokenAddress == jUSDC * - jUSDC otherwise * Upon receiving the flash loan, the tokens are swapped to the tokens needed * to repay the borrow position and perform liquidation. * @param _borrowerToLiquidate The address of the borrower to liquidate * @param _jRepayTokenAddress The address of the jToken contract to borrow from * @param _jSeizeTokenAddress The address of the jToken contract to seize collateral from * @param _repayAmount The amount of the tokens to repay */ function doFlashloan( address _borrowerToLiquidate, address _jRepayTokenAddress, address _jSeizeTokenAddress, uint256 _repayAmount ) internal { // See if the underlying repay token is USDC address underlyingRepayToken = JErc20Storage(_jRepayTokenAddress) .underlying(); bool isRepayTokenUSDC = underlyingRepayToken == USDC; // Calculate the amount we need to flash loan uint256 flashLoanAmount = _getFlashLoanAmount( underlyingRepayToken, _repayAmount, isRepayTokenUSDC ); // Calculate which jToken to flash loan from. // We will only ever flash loan from jUSDC or jWETH. JCollateralCapErc20Delegator jTokenToFlashLoan = _getJTokenToFlashLoan( isRepayTokenUSDC ); bytes memory data = abi.encode( msg.sender, // initiator _borrowerToLiquidate, // borrowerToLiquidate _jRepayTokenAddress, // jRepayTokenAddress _jSeizeTokenAddress, // jSeizeTokenAddress jTokenToFlashLoan.underlying(), // flashLoanedTokenAddress flashLoanAmount, // flashLoanAmount _repayAmount // repayAmount ); // Perform flash loan jTokenToFlashLoan.flashLoan(this, msg.sender, flashLoanAmount, data); } /** * @dev Calculates the amount needed to flash loan in order to repay * `_repayAmount` of the borrow position. * @param _underlyingRepayToken The token of the borrow position to repay * @param _repayAmount The amount of the borrow position to repay * @param _isRepayTokenUSDC Whether the token of the borrow position to repay is USDC * @return The flash loan amount required to repay the borrow position for liquidation. */ function _getFlashLoanAmount( address _underlyingRepayToken, uint256 _repayAmount, bool _isRepayTokenUSDC ) internal view returns (uint256) { address[] memory path = new address[](2); // If the underlying repay token is USDC, we will flash loan from jWETH, // else we will flash loan jUSDC. if (_isRepayTokenUSDC) { path[0] = WETH; } else { path[0] = USDC; } path[1] = _underlyingRepayToken; return JoeRouter02(joeRouter02Address).getAmountsIn(_repayAmount, path)[0]; } /** * @dev Gets the jToken to flash loan. * We always flash loan from jUSDC unless the repay token is USDC in which case we * flash loan from jWETH. * @param _isRepayTokenUSDC Whether the token of the borrow position to repay is USDC * @return The jToken to flash loan */ function _getJTokenToFlashLoan(bool _isRepayTokenUSDC) internal view returns (JCollateralCapErc20Delegator) { if (_isRepayTokenUSDC) { return JCollateralCapErc20Delegator(jWETHAddress); } else { return JCollateralCapErc20Delegator(jUSDCAddress); } } /** * @dev Called by a jToken upon request of a flash loan * @param _initiator The address that initiated this flash loan * @param _flashLoanTokenAddress The address of the flash loan jToken's underlying asset * @param _flashLoanAmount The flash loan amount granted * @param _flashLoanFee The fee for this flash loan * @param _data The encoded data sent for this flash loan */ function onFlashLoan( address _initiator, address _flashLoanTokenAddress, uint256 _flashLoanAmount, uint256 _flashLoanFee, bytes calldata _data ) external override returns (bytes32) { require( Joetroller(joetrollerAddress).isMarketListed(msg.sender), "JoeLiquidator: Untrusted message sender calling onFlashLoan" ); LiquidationLocalVars memory liquidationLocalVars = _getLiquidationLocalVars( _initiator, _flashLoanTokenAddress, _flashLoanAmount, _data ); uint256 flashLoanAmountToRepay = _flashLoanAmount.add(_flashLoanFee); // ******************************************************************** // Our custom logic begins here... // ******************************************************************** JErc20Interface jRepayToken = JErc20Interface( liquidationLocalVars.jRepayTokenAddress ); // Swap token that we flash loaned to the token we need to repay the borrow // position _swapFlashLoanTokenToRepayToken( _flashLoanTokenAddress, _flashLoanAmount, jRepayToken.underlying(), liquidationLocalVars.repayAmount ); // Perform liquidation using the underlying repay token we swapped for and // receive jSeizeTokens in return. _liquidateBorrow( jRepayToken, liquidationLocalVars.borrowerToLiquidate, liquidationLocalVars.repayAmount, JTokenInterface(liquidationLocalVars.jSeizeTokenAddress) ); // Redeem jSeizeTokens for underlying seize tokens _redeemSeizeToken(liquidationLocalVars.jSeizeTokenAddress); // Swap enough seize tokens to flash loan tokens so we can repay flash loan // amount + flash loan fee _swapSeizeTokenToFlashLoanToken( liquidationLocalVars.jSeizeTokenAddress, _flashLoanTokenAddress, flashLoanAmountToRepay ); // Convert any remaining seized token to native AVAX, unless it already is // AVAX, and send to liquidator uint256 profitedAVAX = _swapRemainingSeizedTokenToAVAX( _initiator, liquidationLocalVars.jSeizeTokenAddress ); require( profitedAVAX > 0, "JoeLiquidator: Expected to have profited from liquidation" ); // ******************************************************************** // Our custom logic ends here... // ******************************************************************** // Approve flash loan lender to retrieve loan amount + fee from us _approveFlashLoanToken(_flashLoanTokenAddress, flashLoanAmountToRepay); // Emit event to indicate successful liquidation emit LiquidationEvent( liquidationLocalVars.borrowerToLiquidate, liquidationLocalVars.jRepayTokenAddress, liquidationLocalVars.jSeizeTokenAddress, liquidationLocalVars.repayAmount, profitedAVAX ); return keccak256("ERC3156FlashBorrowerInterface.onFlashLoan"); } /** * @dev Decodes the encoded `_data` and packs relevant data needed to perform * liquidation into a `LiquidationLocalVars` struct. * @param _initiator The address that initiated this flash loan * @param _flashLoanTokenAddress The address of the flash loan jToken's underlying asset * @param _flashLoanAmount The amount flash loaned * @param _data The encoded data sent for this flash loan * @return relevant decoded data needed to perform liquidation */ function _getLiquidationLocalVars( address _initiator, address _flashLoanTokenAddress, uint256 _flashLoanAmount, bytes calldata _data ) internal pure returns (LiquidationLocalVars memory) { ( address initiator, address borrowerToLiquidate, address jRepayTokenAddress, address jSeizeTokenAddress, address flashLoanedTokenAddress, uint256 flashLoanAmount, uint256 repayAmount ) = abi.decode( _data, (address, address, address, address, address, uint256, uint256) ); // Validate encoded data require( _initiator == initiator, "JoeLiquidator: Untrusted loan initiator" ); require( _flashLoanTokenAddress == flashLoanedTokenAddress, "JoeLiquidator: Encoded data (flashLoanedTokenAddress) does not match" ); require( _flashLoanAmount == flashLoanAmount, "JoeLiquidator: Encoded data (flashLoanAmount) does not match" ); LiquidationLocalVars memory liquidationLocalVars = LiquidationLocalVars({ borrowerToLiquidate: borrowerToLiquidate, jRepayTokenAddress: jRepayTokenAddress, jSeizeTokenAddress: jSeizeTokenAddress, repayAmount: repayAmount }); return liquidationLocalVars; } /** * @dev Swaps the flash loan token to the token needed to repay the borrow position * @param _flashLoanedTokenAddress The address of the flash loan jToken's underlying asset * @param _flashLoanAmount The amount flash loaned * @param _jRepayTokenUnderlyingAddress The address of the jToken to repay's underlying asset * @param _repayAmount The amount of the borrow position to repay */ function _swapFlashLoanTokenToRepayToken( address _flashLoanedTokenAddress, uint256 _flashLoanAmount, address _jRepayTokenUnderlyingAddress, uint256 _repayAmount ) internal { // Approve JoeRouter to transfer our flash loaned token so that we can swap for // the underlying repay token ERC20(_flashLoanedTokenAddress).approve( joeRouter02Address, _flashLoanAmount ); address[] memory swapPath = new address[](2); swapPath[0] = _flashLoanedTokenAddress; swapPath[1] = _jRepayTokenUnderlyingAddress; bool isRepayNative = _jRepayTokenUnderlyingAddress == WAVAX; // Swap flashLoanedToken to jRepayTokenUnderlying if (isRepayNative) { JoeRouter02(joeRouter02Address).swapExactTokensForAVAX( _flashLoanAmount, // amountIn _repayAmount, // amountOutMin swapPath, // path address(this), // to block.timestamp // deadline ); } else { JoeRouter02(joeRouter02Address).swapExactTokensForTokens( _flashLoanAmount, // amountIn _repayAmount, // amountOutMin swapPath, // path address(this), // to block.timestamp // deadline ); } } /** * @dev Performs liquidation given: * - a borrower * - a borrow position to repay * - a supply position to seize * @param _jRepayToken The jToken to repay for liquidation * @param _borrowerToLiquidate The borrower to liquidate * @param _repayAmount The amount of _jRepayToken's underlying assset to repay * @param _jSeizeToken The jToken to seize collateral from */ function _liquidateBorrow( JErc20Interface _jRepayToken, address _borrowerToLiquidate, uint256 _repayAmount, JTokenInterface _jSeizeToken ) internal { bool isRepayNative = _jRepayToken.underlying() == WAVAX; // We should have at least `_repayAmount` of underlying repay tokens from // swapping the flash loan tokens. uint256 repayTokenBalance = isRepayNative ? address(this).balance : ERC20(_jRepayToken.underlying()).balanceOf(address(this)); require( repayTokenBalance >= _repayAmount, "JoeLiquidator: Expected to have enough underlying repay token to liquidate borrow position." ); uint256 err; if (isRepayNative) { // Perform liquidation and receive jAVAX in return err = JWrappedNativeInterface(address(_jRepayToken)) .liquidateBorrowNative{value: _repayAmount}( _borrowerToLiquidate, _jSeizeToken ); } else { // Approve repay jToken to take our underlying repay tokens so that we // can perform liquidation ERC20(_jRepayToken.underlying()).approve( address(_jRepayToken), _repayAmount ); // Perform liquidation and receive jSeizeTokens in return err = _jRepayToken.liquidateBorrow( _borrowerToLiquidate, _repayAmount, _jSeizeToken ); } require( err == 0, "JoeLiquidator: Error occurred trying to liquidateBorrow" ); } /** * @dev Seizes collateral from a jToken market after having successfully performed * liquidation * @param _jSeizeTokenAddress The address of the jToken to seize collateral from */ function _redeemSeizeToken(address _jSeizeTokenAddress) internal { // Get amount of jSeizeToken's we have uint256 amountOfJSeizeTokensToRedeem = JTokenInterface( _jSeizeTokenAddress ).balanceOf(address(this)); JErc20Interface jSeizeToken = JErc20Interface(_jSeizeTokenAddress); bool isSeizeNative = jSeizeToken.underlying() == WAVAX; // Redeem `amountOfJSeizeTokensToRedeem` jSeizeTokens for underlying seize tokens uint256 err; if (isSeizeNative) { err = JWrappedNativeInterface(_jSeizeTokenAddress).redeemNative( amountOfJSeizeTokensToRedeem ); } else { err = jSeizeToken.redeem(amountOfJSeizeTokensToRedeem); } require( err == 0, "JoeLiquidator: Error occurred trying to redeem underlying seize tokens" ); } /** * @dev Swaps enough of the seized collateral to flash loan tokens in order * to repay the flash loan amount + flash loan fee * @param _jSeizeTokenAddress The address of the jToken to seize collateral from * @param _flashLoanTokenAddress The address of the flash loan jToken's underlying asset * @param _flashLoanAmountToRepay The flash loan amount + flash loan fee to repay */ function _swapSeizeTokenToFlashLoanToken( address _jSeizeTokenAddress, address _flashLoanTokenAddress, uint256 _flashLoanAmountToRepay ) internal { JErc20Storage jSeizeToken = JErc20Storage(_jSeizeTokenAddress); address jSeizeTokenUnderlyingAddress = jSeizeToken.underlying(); // Calculate amount of underlying seize token we need // to swap in order to pay back the flash loan amount + fee address[] memory swapPath = new address[](2); swapPath[0] = jSeizeTokenUnderlyingAddress; swapPath[1] = _flashLoanTokenAddress; uint256 amountOfSeizeTokenToSwap = JoeRouter02(joeRouter02Address) .getAmountsIn(_flashLoanAmountToRepay, swapPath)[0]; bool isSeizeNative = jSeizeTokenUnderlyingAddress == WAVAX; // Perform the swap to flash loan tokens! if (isSeizeNative) { JoeRouter02(joeRouter02Address).swapExactAVAXForTokens{ value: amountOfSeizeTokenToSwap }( _flashLoanAmountToRepay, // amountOutMin swapPath, // path address(this), // to block.timestamp // deadline ); } else { // Approve router to transfer `amountOfSeizeTokenToSwap` underlying // seize tokens ERC20 seizeToken = ERC20(jSeizeTokenUnderlyingAddress); seizeToken.approve(joeRouter02Address, amountOfSeizeTokenToSwap); // Swap seized token to flash loan token JoeRouter02(joeRouter02Address).swapExactTokensForTokens( amountOfSeizeTokenToSwap, // amountIn _flashLoanAmountToRepay, // amountOutMin swapPath, // path address(this), // to block.timestamp // deadline ); } // Check we received enough flash loan tokens from the swap to repay the flash loan ERC20 flashLoanToken = ERC20(_flashLoanTokenAddress); require( flashLoanToken.balanceOf(address(this)) >= _flashLoanAmountToRepay, "JoeLiquidator: Expected to have enough tokens to repay flash loan after swapping seized tokens." ); } /** * @dev Swaps all remaining of the seized collateral to AVAX, unless * the seized collateral is already AVAX, and sends it to the initiator. * @param _initiator The initiator of the flash loan, aka the liquidator * @param _jSeizeTokenAddress The address of jToken collateral was seized from * @return The AVAX received as profit from performing the liquidation. */ function _swapRemainingSeizedTokenToAVAX( address _initiator, address _jSeizeTokenAddress ) internal returns (uint256) { JErc20Storage jSeizeToken = JErc20Storage(_jSeizeTokenAddress); address jSeizeTokenUnderlyingAddress = jSeizeToken.underlying(); bool isSeizeNative = jSeizeTokenUnderlyingAddress == WAVAX; if (isSeizeNative) { // The seized collateral was AVAX so we can do a simple transfer to the liquidator uint256 profitedAVAX = address(this).balance; (bool success, ) = _initiator.call{value: profitedAVAX}(""); require( success, "JoeLiquidator: Failed to transfer native AVAX to liquidator" ); return profitedAVAX; } else { // Swap seized token to AVAX ERC20 seizeToken = ERC20(jSeizeTokenUnderlyingAddress); uint256 remainingSeizeAmount = seizeToken.balanceOf(address(this)); require( remainingSeizeAmount > 0, "JoeLiquidator: Expected to have remaining seize amount in order to have profited from liquidation" ); seizeToken.approve(joeRouter02Address, remainingSeizeAmount); address[] memory swapPath = new address[](2); swapPath[0] = jSeizeTokenUnderlyingAddress; swapPath[1] = WAVAX; uint256[] memory amounts = JoeRouter02(joeRouter02Address) .swapExactTokensForAVAX( remainingSeizeAmount, // amountIn 0, // amountOutMin swapPath, // path _initiator, // to block.timestamp // deadline ); // Return profitted AVAX return amounts[1]; } } /** * @notice Approves the flash loan jToken to retrieve the flash loan amount + fee. * @param _flashLoanTokenAddress The address of the flash loan jToken's underlying asset * @param _flashLoanAmountToRepay The flash loan amount to repay */ function _approveFlashLoanToken( address _flashLoanTokenAddress, uint256 _flashLoanAmountToRepay ) internal { ERC20 flashLoanToken = ERC20(_flashLoanTokenAddress); // Ensure we have enough to repay flash loan require( flashLoanToken.balanceOf(address(this)) >= _flashLoanAmountToRepay, "JoeLiquidator: Expected to have enough tokens to repay flash loan after swapping seized tokens." ); // Approve flash loan lender to retrieve loan amount + fee from us flashLoanToken.approve(msg.sender, _flashLoanAmountToRepay); } }
[{"inputs":[{"internalType":"address","name":"_joetrollerAddress","type":"address"},{"internalType":"address","name":"_joeRouter02Address","type":"address"},{"internalType":"address","name":"_jUSDCAddress","type":"address"},{"internalType":"address","name":"_jWETHAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_borrowerLiquidated","type":"address"},{"indexed":false,"internalType":"address","name":"_jRepayToken","type":"address"},{"indexed":false,"internalType":"address","name":"_jSeizeToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"_repayAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_profitedAVAX","type":"uint256"}],"name":"LiquidationEvent","type":"event"},{"inputs":[],"name":"USDC","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WAVAX","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"jUSDCAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"jWETHAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"joeRouter02Address","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"joetrollerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_borrowerToLiquidate","type":"address"},{"internalType":"address","name":"_jRepayTokenAddress","type":"address"},{"internalType":"address","name":"_jSeizeTokenAddress","type":"address"}],"name":"liquidate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_initiator","type":"address"},{"internalType":"address","name":"_flashLoanTokenAddress","type":"address"},{"internalType":"uint256","name":"_flashLoanAmount","type":"uint256"},{"internalType":"uint256","name":"_flashLoanFee","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"onFlashLoan","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60806040523480156200001157600080fd5b5060405162004387380380620043878339818101604052810190620000379190620001ae565b836000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050505062000220565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620001768262000149565b9050919050565b620001888162000169565b81146200019457600080fd5b50565b600081519050620001a8816200017d565b92915050565b60008060008060808587031215620001cb57620001ca62000144565b5b6000620001db8782880162000197565b9450506020620001ee8782880162000197565b9350506040620002018782880162000197565b9250506060620002148782880162000197565b91505092959194509250565b61415780620002306000396000f3fe60806040526004361061008a5760003560e01c806389a302711161005957806389a3027114610154578063ad5c46481461017f578063c62d2751146101aa578063ca5ce2ec146101d5578063e62fbf6a146101fe57610091565b8063218377a01461009657806323e30c8b146100c157806373b295c2146100fe578063897857b81461012957610091565b3661009157005b600080fd5b3480156100a257600080fd5b506100ab610229565b6040516100b89190612b52565b60405180910390f35b3480156100cd57600080fd5b506100e860048036038101906100e39190612c48565b61024f565b6040516100f59190612cfb565b60405180910390f35b34801561010a57600080fd5b50610113610522565b6040516101209190612b52565b60405180910390f35b34801561013557600080fd5b5061013e61053a565b60405161014b9190612b52565b60405180910390f35b34801561016057600080fd5b5061016961055e565b6040516101769190612b52565b60405180910390f35b34801561018b57600080fd5b50610194610576565b6040516101a19190612b52565b60405180910390f35b3480156101b657600080fd5b506101bf61058e565b6040516101cc9190612b52565b60405180910390f35b3480156101e157600080fd5b506101fc60048036038101906101f79190612d16565b6105b4565b005b34801561020a57600080fd5b50610213610711565b6040516102209190612b52565b60405180910390f35b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16633d98a1e5336040518263ffffffff1660e01b81526004016102ab9190612b52565b60206040518083038186803b1580156102c357600080fd5b505afa1580156102d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102fb9190612da1565b61033a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161033190612e51565b60405180910390fd5b60006103498888888787610737565b90506000610360868861090090919063ffffffff16565b90506000826000015190506103fa89898373ffffffffffffffffffffffffffffffffffffffff16636f307dc36040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156103b857600080fd5b505af11580156103cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103f09190612e86565b8660600151610916565b61041281846040015185606001518660200151610c62565b61041f83602001516110ea565b61042e83602001518a846113b4565b600061043e8b8560200151611932565b905060008111610483576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161047a90612f25565b60405180910390fd5b61048d8a84611e16565b836040015173ffffffffffffffffffffffffffffffffffffffff167f1683d07b2bca5806ccc25a2d5ecdad3343784e4ed273236e2a53890b4f1d95a6856000015186602001518760600151856040516104e99493929190612f54565b60405180910390a27f7968ba28153757de2da7bce4c2ba9ebaf94445061f3050de1b0de5c34bb7d5d89450505050509695505050505050565b73b31f66aa3c1e785363f0875a1b74e27b85fd66c781565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b73a7d7079b0fead91f3e65f86e8915cb59c1a4c66481565b7349d5c2bdffac6ce2bfdb6640f4f80f226bc10bab81565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b8260008060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635ec88c79846040518263ffffffff1660e01b81526004016106119190612b52565b60606040518083038186803b15801561062957600080fd5b505afa15801561063d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106619190612fae565b9250925050600082146106a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106a090613073565b60405180910390fd5b60008114156106ed576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106e490613105565b60405180910390fd5b60006106fa878787611f58565b905061070887878784612348565b50505050505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61073f612a94565b600080600080600080600089898101906107599190613163565b96509650965096509650965096508673ffffffffffffffffffffffffffffffffffffffff168d73ffffffffffffffffffffffffffffffffffffffff16146107d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107cc90613277565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168c73ffffffffffffffffffffffffffffffffffffffff1614610843576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161083a9061332f565b60405180910390fd5b818b14610885576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161087c906133c1565b60405180910390fd5b600060405180608001604052808773ffffffffffffffffffffffffffffffffffffffff1681526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff168152602001838152509050809850505050505050505095945050505050565b6000818361090e9190613410565b905092915050565b8373ffffffffffffffffffffffffffffffffffffffff1663095ea7b3600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856040518363ffffffff1660e01b8152600401610973929190613466565b600060405180830381600087803b15801561098d57600080fd5b505af11580156109a1573d6000803e3d6000fd5b505050506000600267ffffffffffffffff8111156109c2576109c161348f565b5b6040519080825280602002602001820160405280156109f05781602001602082028036833780820191505090505b5090508481600081518110610a0857610a076134be565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508281600181518110610a5757610a566134be565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600073b31f66aa3c1e785363f0875a1b74e27b85fd66c773ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161490508015610b9e57600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663676528d186858530426040518663ffffffff1660e01b8152600401610b419594939291906135ab565b600060405180830381600087803b158015610b5b57600080fd5b505af1158015610b6f573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610b989190613725565b50610c5a565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166338ed173986858530426040518663ffffffff1660e01b8152600401610c019594939291906135ab565b600060405180830381600087803b158015610c1b57600080fd5b505af1158015610c2f573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610c589190613725565b505b505050505050565b600073b31f66aa3c1e785363f0875a1b74e27b85fd66c773ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16636f307dc36040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610cd757600080fd5b505af1158015610ceb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d0f9190612e86565b73ffffffffffffffffffffffffffffffffffffffff16149050600081610e3c578573ffffffffffffffffffffffffffffffffffffffff16636f307dc36040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610d7757600080fd5b505af1158015610d8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610daf9190612e86565b73ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610de79190612b52565b60206040518083038186803b158015610dff57600080fd5b505afa158015610e13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e37919061376e565b610e3e565b475b905083811015610e83576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e7a90613833565b60405180910390fd5b60008215610f20578673ffffffffffffffffffffffffffffffffffffffff1663291727a48688876040518463ffffffff1660e01b8152600401610ec79291906138b2565b6020604051808303818588803b158015610ee057600080fd5b505af1158015610ef4573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610f19919061376e565b905061109e565b8673ffffffffffffffffffffffffffffffffffffffff16636f307dc36040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610f6857600080fd5b505af1158015610f7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa09190612e86565b73ffffffffffffffffffffffffffffffffffffffff1663095ea7b388876040518363ffffffff1660e01b8152600401610fda929190613466565b600060405180830381600087803b158015610ff457600080fd5b505af1158015611008573d6000803e3d6000fd5b505050508673ffffffffffffffffffffffffffffffffffffffff1663f5e3c4628787876040518463ffffffff1660e01b8152600401611049939291906138db565b602060405180830381600087803b15801561106357600080fd5b505af1158015611077573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061109b919061376e565b90505b600081146110e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110d890613984565b60405180910390fd5b50505050505050565b60008173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016111259190612b52565b60206040518083038186803b15801561113d57600080fd5b505afa158015611151573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611175919061376e565b90506000829050600073b31f66aa3c1e785363f0875a1b74e27b85fd66c773ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16636f307dc36040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156111f157600080fd5b505af1158015611205573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112299190612e86565b73ffffffffffffffffffffffffffffffffffffffff16149050600081156112dc578473ffffffffffffffffffffffffffffffffffffffff16634bf03edf856040518263ffffffff1660e01b815260040161128391906139a4565b602060405180830381600087803b15801561129d57600080fd5b505af11580156112b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112d5919061376e565b905061136a565b8273ffffffffffffffffffffffffffffffffffffffff1663db006a75856040518263ffffffff1660e01b815260040161131591906139a4565b602060405180830381600087803b15801561132f57600080fd5b505af1158015611343573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611367919061376e565b90505b600081146113ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113a490613a57565b60405180910390fd5b5050505050565b600083905060008173ffffffffffffffffffffffffffffffffffffffff16636f307dc36040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561140357600080fd5b505af1158015611417573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061143b9190612e86565b90506000600267ffffffffffffffff81111561145a5761145961348f565b5b6040519080825280602002602001820160405280156114885781602001602082028036833780820191505090505b50905081816000815181106114a05761149f6134be565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505084816001815181106114ef576114ee6134be565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631f00ca7486846040518363ffffffff1660e01b8152600401611588929190613a77565b60006040518083038186803b1580156115a057600080fd5b505afa1580156115b4573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906115dd9190613725565b6000815181106115f0576115ef6134be565b5b60200260200101519050600073b31f66aa3c1e785363f0875a1b74e27b85fd66c773ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16149050801561170657600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a2a1623d83888630426040518663ffffffff1660e01b81526004016116a99493929190613aa7565b6000604051808303818588803b1580156116c257600080fd5b505af11580156116d6573d6000803e3d6000fd5b50505050506040513d6000823e3d601f19601f820116820180604052508101906117009190613725565b50611857565b60008490508073ffffffffffffffffffffffffffffffffffffffff1663095ea7b3600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856040518363ffffffff1660e01b8152600401611768929190613466565b600060405180830381600087803b15801561178257600080fd5b505af1158015611796573d6000803e3d6000fd5b50505050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166338ed173984898730426040518663ffffffff1660e01b81526004016117fd9594939291906135ab565b600060405180830381600087803b15801561181757600080fd5b505af115801561182b573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906118549190613725565b50505b6000879050868173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016118969190612b52565b60206040518083038186803b1580156118ae57600080fd5b505afa1580156118c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118e6919061376e565b1015611927576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161191e90613b8b565b60405180910390fd5b505050505050505050565b60008082905060008173ffffffffffffffffffffffffffffffffffffffff16636f307dc36040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561198257600080fd5b505af1158015611996573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ba9190612e86565b9050600073b31f66aa3c1e785363f0875a1b74e27b85fd66c773ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161490508015611ac757600047905060008773ffffffffffffffffffffffffffffffffffffffff1682604051611a3490613bdc565b60006040518083038185875af1925050503d8060008114611a71576040519150601f19603f3d011682016040523d82523d6000602084013e611a76565b606091505b5050905080611aba576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ab190613c63565b60405180910390fd5b8195505050505050611e10565b600082905060008173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401611b079190612b52565b60206040518083038186803b158015611b1f57600080fd5b505afa158015611b33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b57919061376e565b905060008111611b9c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b9390613d41565b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff1663095ea7b3600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040518363ffffffff1660e01b8152600401611bf9929190613466565b600060405180830381600087803b158015611c1357600080fd5b505af1158015611c27573d6000803e3d6000fd5b505050506000600267ffffffffffffffff811115611c4857611c4761348f565b5b604051908082528060200260200182016040528015611c765781602001602082028036833780820191505090505b5090508481600081518110611c8e57611c8d6134be565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505073b31f66aa3c1e785363f0875a1b74e27b85fd66c781600181518110611cf157611cf06134be565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663676528d1846000858e426040518663ffffffff1660e01b8152600401611d91959493929190613d9c565b600060405180830381600087803b158015611dab57600080fd5b505af1158015611dbf573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611de89190613725565b905080600181518110611dfe57611dfd6134be565b5b60200260200101519750505050505050505b92915050565b6000829050818173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401611e559190612b52565b60206040518083038186803b158015611e6d57600080fd5b505afa158015611e81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ea5919061376e565b1015611ee6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611edd90613b8b565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1663095ea7b333846040518363ffffffff1660e01b8152600401611f21929190613466565b600060405180830381600087803b158015611f3b57600080fd5b505af1158015611f4f573d6000803e3d6000fd5b50505050505050565b60008060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008173ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b815260040160206040518083038186803b158015611fc657600080fd5b505afa158015611fda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ffe9190613e34565b905060008273ffffffffffffffffffffffffffffffffffffffff1663e87554466040518163ffffffff1660e01b815260040160206040518083038186803b15801561204857600080fd5b505afa15801561205c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612080919061376e565b905060008373ffffffffffffffffffffffffffffffffffffffff16634ada90af6040518163ffffffff1660e01b815260040160206040518083038186803b1580156120ca57600080fd5b505afa1580156120de573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612102919061376e565b905060008373ffffffffffffffffffffffffffffffffffffffff1663fc57d4df896040518263ffffffff1660e01b815260040161213f9190613e82565b60206040518083038186803b15801561215757600080fd5b505afa15801561216b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218f919061376e565b905060008473ffffffffffffffffffffffffffffffffffffffff1663fc57d4df896040518263ffffffff1660e01b81526004016121cc9190613e82565b60206040518083038186803b1580156121e457600080fd5b505afa1580156121f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061221c919061376e565b90506000670de0b6b3a7640000858b73ffffffffffffffffffffffffffffffffffffffff166395dd91938e6040518263ffffffff1660e01b81526004016122639190612b52565b60206040518083038186803b15801561227b57600080fd5b505afa15801561228f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122b3919061376e565b6122bd9190613e9d565b6122c79190613f26565b9050600084670de0b6b3a76400006122df8c8f61257b565b6122e99190613e9d565b6122f39190613f26565b9050600084836123039190613e9d565b9050600084836123139190613e9d565b905060008183106123245781612326565b825b905086816123349190613f26565b9b5050505050505050505050509392505050565b60008373ffffffffffffffffffffffffffffffffffffffff16636f307dc36040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561239257600080fd5b505af11580156123a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123ca9190612e86565b9050600073a7d7079b0fead91f3e65f86e8915cb59c1a4c66473ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614905060006124208385846126ad565b9050600061242d836128f4565b90506000338989898573ffffffffffffffffffffffffffffffffffffffff16636f307dc36040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561247d57600080fd5b505af1158015612491573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124b59190612e86565b878b6040516020016124cd9796959493929190613f57565b60405160208183030381529060405290508173ffffffffffffffffffffffffffffffffffffffff16635cffe9de303386856040518563ffffffff1660e01b815260040161251d949392919061406f565b602060405180830381600087803b15801561253757600080fd5b505af115801561254b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061256f9190612da1565b50505050505050505050565b600080839050600060405180602001604052808373ffffffffffffffffffffffffffffffffffffffff1663182df0f56040518163ffffffff1660e01b815260040160206040518083038186803b1580156125d457600080fd5b505afa1580156125e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061260c919061376e565b81525090506126a3818373ffffffffffffffffffffffffffffffffffffffff166370a08231876040518263ffffffff1660e01b815260040161264e9190612b52565b60206040518083038186803b15801561266657600080fd5b505afa15801561267a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061269e919061376e565b612951565b9250505092915050565b600080600267ffffffffffffffff8111156126cb576126ca61348f565b5b6040519080825280602002602001820160405280156126f95781602001602082028036833780820191505090505b509050821561276a577349d5c2bdffac6ce2bfdb6640f4f80f226bc10bab8160008151811061272b5761272a6134be565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506127ce565b73a7d7079b0fead91f3e65f86e8915cb59c1a4c66481600081518110612793576127926134be565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250505b84816001815181106127e3576127e26134be565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631f00ca7485836040518363ffffffff1660e01b815260040161287a929190613a77565b60006040518083038186803b15801561289257600080fd5b505afa1580156128a6573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906128cf9190613725565b6000815181106128e2576128e16134be565b5b60200260200101519150509392505050565b6000811561292657600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905061294c565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505b919050565b60008061295e8484612972565b90506129698161299e565b91505092915050565b61297a612afe565b60405180602001604052806129938560000151856129bf565b815250905092915050565b6000670de0b6b3a764000082600001516129b89190613f26565b9050919050565b6000612a0183836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250612a09565b905092915050565b600080841480612a195750600083145b15612a275760009050612a8d565b60008385612a359190613e9d565b9050838582612a449190613f26565b148390612a87576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a7e91906140ff565b60405180910390fd5b50809150505b9392505050565b6040518060800160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600081525090565b6040518060200160405280600081525090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612b3c82612b11565b9050919050565b612b4c81612b31565b82525050565b6000602082019050612b676000830184612b43565b92915050565b6000604051905090565b600080fd5b600080fd5b612b8a81612b31565b8114612b9557600080fd5b50565b600081359050612ba781612b81565b92915050565b6000819050919050565b612bc081612bad565b8114612bcb57600080fd5b50565b600081359050612bdd81612bb7565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f840112612c0857612c07612be3565b5b8235905067ffffffffffffffff811115612c2557612c24612be8565b5b602083019150836001820283011115612c4157612c40612bed565b5b9250929050565b60008060008060008060a08789031215612c6557612c64612b77565b5b6000612c7389828a01612b98565b9650506020612c8489828a01612b98565b9550506040612c9589828a01612bce565b9450506060612ca689828a01612bce565b935050608087013567ffffffffffffffff811115612cc757612cc6612b7c565b5b612cd389828a01612bf2565b92509250509295509295509295565b6000819050919050565b612cf581612ce2565b82525050565b6000602082019050612d106000830184612cec565b92915050565b600080600060608486031215612d2f57612d2e612b77565b5b6000612d3d86828701612b98565b9350506020612d4e86828701612b98565b9250506040612d5f86828701612b98565b9150509250925092565b60008115159050919050565b612d7e81612d69565b8114612d8957600080fd5b50565b600081519050612d9b81612d75565b92915050565b600060208284031215612db757612db6612b77565b5b6000612dc584828501612d8c565b91505092915050565b600082825260208201905092915050565b7f4a6f654c697175696461746f723a20556e74727573746564206d65737361676560008201527f2073656e6465722063616c6c696e67206f6e466c6173684c6f616e0000000000602082015250565b6000612e3b603b83612dce565b9150612e4682612ddf565b604082019050919050565b60006020820190508181036000830152612e6a81612e2e565b9050919050565b600081519050612e8081612b81565b92915050565b600060208284031215612e9c57612e9b612b77565b5b6000612eaa84828501612e71565b91505092915050565b7f4a6f654c697175696461746f723a20457870656374656420746f20686176652060008201527f70726f66697465642066726f6d206c69717569646174696f6e00000000000000602082015250565b6000612f0f603983612dce565b9150612f1a82612eb3565b604082019050919050565b60006020820190508181036000830152612f3e81612f02565b9050919050565b612f4e81612bad565b82525050565b6000608082019050612f696000830187612b43565b612f766020830186612b43565b612f836040830185612f45565b612f906060830184612f45565b95945050505050565b600081519050612fa881612bb7565b92915050565b600080600060608486031215612fc757612fc6612b77565b5b6000612fd586828701612f99565b9350506020612fe686828701612f99565b9250506040612ff786828701612f99565b9150509250925092565b7f4a6f654c697175696461746f723a2043616e6e6f74206c69717569646174652060008201527f6163636f756e742077697468206e6f6e2d7a65726f206c697175696469747900602082015250565b600061305d603f83612dce565b915061306882613001565b604082019050919050565b6000602082019050818103600083015261308c81613050565b9050919050565b7f4a6f654c697175696461746f723a2043616e6e6f74206c69717569646174652060008201527f6163636f756e742077697468207a65726f2073686f727466616c6c0000000000602082015250565b60006130ef603b83612dce565b91506130fa82613093565b604082019050919050565b6000602082019050818103600083015261311e816130e2565b9050919050565b600061313082612b11565b9050919050565b61314081613125565b811461314b57600080fd5b50565b60008135905061315d81613137565b92915050565b600080600080600080600060e0888a03121561318257613181612b77565b5b60006131908a828b0161314e565b97505060206131a18a828b0161314e565b96505060406131b28a828b0161314e565b95505060606131c38a828b0161314e565b94505060806131d48a828b0161314e565b93505060a06131e58a828b01612bce565b92505060c06131f68a828b01612bce565b91505092959891949750929550565b7f4a6f654c697175696461746f723a20556e74727573746564206c6f616e20696e60008201527f69746961746f7200000000000000000000000000000000000000000000000000602082015250565b6000613261602783612dce565b915061326c82613205565b604082019050919050565b6000602082019050818103600083015261329081613254565b9050919050565b7f4a6f654c697175696461746f723a20456e636f64656420646174612028666c6160008201527f73684c6f616e6564546f6b656e416464726573732920646f6573206e6f74206d60208201527f6174636800000000000000000000000000000000000000000000000000000000604082015250565b6000613319604483612dce565b915061332482613297565b606082019050919050565b600060208201905081810360008301526133488161330c565b9050919050565b7f4a6f654c697175696461746f723a20456e636f64656420646174612028666c6160008201527f73684c6f616e416d6f756e742920646f6573206e6f74206d6174636800000000602082015250565b60006133ab603c83612dce565b91506133b68261334f565b604082019050919050565b600060208201905081810360008301526133da8161339e565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061341b82612bad565b915061342683612bad565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561345b5761345a6133e1565b5b828201905092915050565b600060408201905061347b6000830185612b43565b6134886020830184612f45565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61352281612b31565b82525050565b60006135348383613519565b60208301905092915050565b6000602082019050919050565b6000613558826134ed565b61356281856134f8565b935061356d83613509565b8060005b8381101561359e5781516135858882613528565b975061359083613540565b925050600181019050613571565b5085935050505092915050565b600060a0820190506135c06000830188612f45565b6135cd6020830187612f45565b81810360408301526135df818661354d565b90506135ee6060830185612b43565b6135fb6080830184612f45565b9695505050505050565b6000601f19601f8301169050919050565b61361f82613605565b810181811067ffffffffffffffff8211171561363e5761363d61348f565b5b80604052505050565b6000613651612b6d565b905061365d8282613616565b919050565b600067ffffffffffffffff82111561367d5761367c61348f565b5b602082029050602081019050919050565b60006136a161369c84613662565b613647565b905080838252602082019050602084028301858111156136c4576136c3612bed565b5b835b818110156136ed57806136d98882612f99565b8452602084019350506020810190506136c6565b5050509392505050565b600082601f83011261370c5761370b612be3565b5b815161371c84826020860161368e565b91505092915050565b60006020828403121561373b5761373a612b77565b5b600082015167ffffffffffffffff81111561375957613758612b7c565b5b613765848285016136f7565b91505092915050565b60006020828403121561378457613783612b77565b5b600061379284828501612f99565b91505092915050565b7f4a6f654c697175696461746f723a20457870656374656420746f20686176652060008201527f656e6f75676820756e6465726c79696e6720726570617920746f6b656e20746f60208201527f206c697175696461746520626f72726f7720706f736974696f6e2e0000000000604082015250565b600061381d605b83612dce565b91506138288261379b565b606082019050919050565b6000602082019050818103600083015261384c81613810565b9050919050565b6000819050919050565b600061387861387361386e84612b11565b613853565b612b11565b9050919050565b600061388a8261385d565b9050919050565b600061389c8261387f565b9050919050565b6138ac81613891565b82525050565b60006040820190506138c76000830185612b43565b6138d460208301846138a3565b9392505050565b60006060820190506138f06000830186612b43565b6138fd6020830185612f45565b61390a60408301846138a3565b949350505050565b7f4a6f654c697175696461746f723a204572726f72206f6363757272656420747260008201527f79696e6720746f206c6971756964617465426f72726f77000000000000000000602082015250565b600061396e603783612dce565b915061397982613912565b604082019050919050565b6000602082019050818103600083015261399d81613961565b9050919050565b60006020820190506139b96000830184612f45565b92915050565b7f4a6f654c697175696461746f723a204572726f72206f6363757272656420747260008201527f79696e6720746f2072656465656d20756e6465726c79696e67207365697a652060208201527f746f6b656e730000000000000000000000000000000000000000000000000000604082015250565b6000613a41604683612dce565b9150613a4c826139bf565b606082019050919050565b60006020820190508181036000830152613a7081613a34565b9050919050565b6000604082019050613a8c6000830185612f45565b8181036020830152613a9e818461354d565b90509392505050565b6000608082019050613abc6000830187612f45565b8181036020830152613ace818661354d565b9050613add6040830185612b43565b613aea6060830184612f45565b95945050505050565b7f4a6f654c697175696461746f723a20457870656374656420746f20686176652060008201527f656e6f75676820746f6b656e7320746f20726570617920666c617368206c6f6160208201527f6e206166746572207377617070696e67207365697a656420746f6b656e732e00604082015250565b6000613b75605f83612dce565b9150613b8082613af3565b606082019050919050565b60006020820190508181036000830152613ba481613b68565b9050919050565b600081905092915050565b50565b6000613bc6600083613bab565b9150613bd182613bb6565b600082019050919050565b6000613be782613bb9565b9150819050919050565b7f4a6f654c697175696461746f723a204661696c656420746f207472616e73666560008201527f72206e6174697665204156415820746f206c697175696461746f720000000000602082015250565b6000613c4d603b83612dce565b9150613c5882613bf1565b604082019050919050565b60006020820190508181036000830152613c7c81613c40565b9050919050565b7f4a6f654c697175696461746f723a20457870656374656420746f20686176652060008201527f72656d61696e696e67207365697a6520616d6f756e7420696e206f726465722060208201527f746f20686176652070726f66697465642066726f6d206c69717569646174696f60408201527f6e00000000000000000000000000000000000000000000000000000000000000606082015250565b6000613d2b606183612dce565b9150613d3682613c83565b608082019050919050565b60006020820190508181036000830152613d5a81613d1e565b9050919050565b6000819050919050565b6000613d86613d81613d7c84613d61565b613853565b612bad565b9050919050565b613d9681613d6b565b82525050565b600060a082019050613db16000830188612f45565b613dbe6020830187613d8d565b8181036040830152613dd0818661354d565b9050613ddf6060830185612b43565b613dec6080830184612f45565b9695505050505050565b6000613e0182612b31565b9050919050565b613e1181613df6565b8114613e1c57600080fd5b50565b600081519050613e2e81613e08565b92915050565b600060208284031215613e4a57613e49612b77565b5b6000613e5884828501613e1f565b91505092915050565b6000613e6c8261387f565b9050919050565b613e7c81613e61565b82525050565b6000602082019050613e976000830184613e73565b92915050565b6000613ea882612bad565b9150613eb383612bad565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613eec57613eeb6133e1565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000613f3182612bad565b9150613f3c83612bad565b925082613f4c57613f4b613ef7565b5b828204905092915050565b600060e082019050613f6c600083018a612b43565b613f796020830189612b43565b613f866040830188612b43565b613f936060830187612b43565b613fa06080830186612b43565b613fad60a0830185612f45565b613fba60c0830184612f45565b98975050505050505050565b6000613fd18261387f565b9050919050565b613fe181613fc6565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b83811015614021578082015181840152602081019050614006565b83811115614030576000848401525b50505050565b600061404182613fe7565b61404b8185613ff2565b935061405b818560208601614003565b61406481613605565b840191505092915050565b60006080820190506140846000830187613fd8565b6140916020830186612b43565b61409e6040830185612f45565b81810360608301526140b08184614036565b905095945050505050565b600081519050919050565b60006140d1826140bb565b6140db8185612dce565b93506140eb818560208601614003565b6140f481613605565b840191505092915050565b6000602082019050818103600083015261411981846140c6565b90509291505056fea264697066735822122030f82ddb7939846bbf3111eb31139576c8a2ba5ac7c4a223a48dead1d332665964736f6c63430008090033000000000000000000000000dc13687554205e5b89ac783db14bb5bba4a1edac00000000000000000000000060ae616a2155ee3d9a68541ba4544862310933d4000000000000000000000000ed6aaf91a2b084bd594dbd1245be3691f9f637ac000000000000000000000000929f5cab61dfec79a5431a7734a68d714c4633fa
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000dc13687554205e5b89ac783db14bb5bba4a1edac00000000000000000000000060ae616a2155ee3d9a68541ba4544862310933d4000000000000000000000000ed6aaf91a2b084bd594dbd1245be3691f9f637ac000000000000000000000000929f5cab61dfec79a5431a7734a68d714c4633fa
-----Decoded View---------------
Arg [0] : _joetrollerAddress (address): 0xdc13687554205e5b89ac783db14bb5bba4a1edac
Arg [1] : _joeRouter02Address (address): 0x60ae616a2155ee3d9a68541ba4544862310933d4
Arg [2] : _jUSDCAddress (address): 0xed6aaf91a2b084bd594dbd1245be3691f9f637ac
Arg [3] : _jWETHAddress (address): 0x929f5cab61dfec79a5431a7734a68d714c4633fa
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000dc13687554205e5b89ac783db14bb5bba4a1edac
Arg [1] : 00000000000000000000000060ae616a2155ee3d9a68541ba4544862310933d4
Arg [2] : 000000000000000000000000ed6aaf91a2b084bd594dbd1245be3691f9f637ac
Arg [3] : 000000000000000000000000929f5cab61dfec79a5431a7734a68d714c4633fa
Deployed ByteCode Sourcemap
18192:26664:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;18467:27;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;28326:3385;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;18549:74;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;18354:32;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;18710:73;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;18630;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;18433:27;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;20824:524;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;18393:33;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;18467:27;;;;;;;;;;;;;:::o;28326:3385::-;28549:7;28602:17;;;;;;;;;;;28591:44;;;28636:10;28591:56;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;28569:165;;;;;;;;;;;;:::i;:::-;;;;;;;;;28747:61;28811:168;28854:10;28883:22;28924:16;28959:5;;28811:24;:168::i;:::-;28747:232;;28992:30;29025:35;29046:13;29025:16;:20;;:35;;;;:::i;:::-;28992:68;;29279:27;29339:20;:39;;;29279:110;;29508:196;29554:22;29591:16;29622:11;:22;;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;29661:20;:32;;;29508:31;:196::i;:::-;29845:226;29876:11;29902:20;:40;;;29957:20;:32;;;30020:20;:39;;;29845:16;:226::i;:::-;30144:58;30162:20;:39;;;30144:17;:58::i;:::-;30336:170;30382:20;:39;;;30436:22;30473;30336:31;:170::i;:::-;30644:20;30667:121;30713:10;30738:20;:39;;;30667:31;:121::i;:::-;30644:144;;30838:1;30823:12;:16;30801:123;;;;;;;;;;;;:::i;:::-;;;;;;;;;31219:70;31242:22;31266;31219;:70::i;:::-;31396:20;:40;;;31365:264;;;31451:20;:39;;;31505:20;:39;;;31559:20;:32;;;31606:12;31365:264;;;;;;;;;:::i;:::-;;;;;;;;31649:54;31642:61;;;;;;28326:3385;;;;;;;;:::o;18549:74::-;18581:42;18549:74;:::o;18354:32::-;;;;;;;;;;;;:::o;18710:73::-;18741:42;18710:73;:::o;18630:::-;18661:42;18630:73;:::o;18433:27::-;;;;;;;;;;;;;:::o;20824:524::-;20989:20;20077:17;20096;20128;;;;;;;;;;20117:63;;;20181:20;20117:85;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;20074:128;;;;;20248:1;20235:9;:14;20213:127;;;;;;;;;;;;:::i;:::-;;;;;;;;;20386:1;20373:9;:14;;20351:123;;;;;;;;;;;;:::i;:::-;;;;;;;;;21022:21:::1;21046:130;21077:20;21112:19;21146;21046:16;:130::i;:::-;21022:154;;21187:153;21213:20;21248:19;21282;21316:13;21187:11;:153::i;:::-;21011:337;20063:431:::0;;20824:524;;;;:::o;18393:33::-;;;;;;;;;;;;;:::o;32228:1528::-;32428:27;;:::i;:::-;32483:17;32515:27;32557:26;32598;32639:31;32685:23;32723:19;32785:5;;32756:131;;;;;;;:::i;:::-;32468:419;;;;;;;;;;;;;;32970:9;32956:23;;:10;:23;;;32934:112;;;;;;;;;;;;:::i;:::-;;;;;;;;;33105:23;33079:49;;:22;:49;;;33057:167;;;;;;;;;;;;:::i;:::-;;;;;;;;;33277:15;33257:16;:35;33235:145;;;;;;;;;;;;:::i;:::-;;;;;;;;;33393:61;33457:253;;;;;;;;33576:18;33457:253;;;;;;33633:18;33457:253;;;;;;33518:19;33457:253;;;;;;33683:11;33457:253;;;33393:317;;33728:20;33721:27;;;;;;;;;;32228:1528;;;;;;;:::o;2941:98::-;2999:7;3030:1;3026;:5;;;;:::i;:::-;3019:12;;2941:98;;;;:::o;34193:1423::-;34552:24;34546:39;;;34600:18;;;;;;;;;;;34633:16;34546:114;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34673:25;34715:1;34701:16;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34673:44;;34742:24;34728:8;34737:1;34728:11;;;;;;;;:::i;:::-;;;;;;;:38;;;;;;;;;;;34791:29;34777:8;34786:1;34777:11;;;;;;;;:::i;:::-;;;;;;;:43;;;;;;;;;;;34833:18;18581:42;34854:38;;:29;:38;;;34833:59;;34968:13;34964:645;;;35010:18;;;;;;;;;;;34998:54;;;35071:16;35118:12;35165:8;35208:4;35238:15;34998:282;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;34964:645;;;35325:18;;;;;;;;;;;35313:56;;;35388:16;35435:12;35482:8;35525:4;35555:15;35313:284;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;34964:645;34407:1209;;34193:1423;;;;:::o;36052:1727::-;36253:18;18581:42;36274:34;;:12;:23;;;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:34;;;36253:55;;36448:25;36476:13;:123;;36548:12;:23;;;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;36542:42;;;36593:4;36542:57;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;36476:123;;;36505:21;36476:123;36448:151;;36653:12;36632:17;:33;;36610:174;;;;;;;;;;;;:::i;:::-;;;;;;;;;36797:11;36823:13;36819:829;;;36955:12;36923:86;;;37017:12;37049:20;37088:12;36923:192;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;36917:198;;36819:829;;;37278:12;:23;;;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;37272:40;;;37339:12;37371;37272:126;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;37492:12;:28;;;37539:20;37578:12;37609;37492:144;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;37486:150;;36819:829;37687:1;37680:3;:8;37658:113;;;;;;;;;;;;:::i;:::-;;;;;;;;;36242:1537;;;36052:1727;;;;:::o;37999:926::-;38123:36;38192:19;38162:70;;;38241:4;38162:85;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;38123:124;;38260:27;38306:19;38260:66;;38339:18;18581:42;38360:33;;:11;:22;;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:33;;;38339:54;;38497:11;38523:13;38519:258;;;38583:19;38559:57;;;38635:28;38559:119;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;38553:125;;38519:258;;;38717:11;:18;;;38736:28;38717:48;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;38711:54;;38519:258;38818:1;38811:3;:8;38789:128;;;;;;;;;;;;:::i;:::-;;;;;;;;;38064:861;;;;37999:926;:::o;39355:2287::-;39544:25;39586:19;39544:62;;39617:36;39656:11;:22;;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;39617:63;;39825:25;39867:1;39853:16;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39825:44;;39894:28;39880:8;39889:1;39880:11;;;;;;;;:::i;:::-;;;;;;;:42;;;;;;;;;;;39947:22;39933:8;39942:1;39933:11;;;;;;;;:::i;:::-;;;;;;;:36;;;;;;;;;;;39982:32;40029:18;;;;;;;;;;;40017:58;;;40076:23;40101:8;40017:93;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;40111:1;40017:96;;;;;;;;:::i;:::-;;;;;;;;39982:131;;40126:18;18581:42;40147:37;;:28;:37;;;40126:58;;40252:13;40248:1007;;;40294:18;;;;;;;;;;;40282:54;;;40362:24;40420:23;40478:8;40521:4;40551:15;40282:311;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;40248:1007;;;40736:16;40761:28;40736:54;;40805:10;:18;;;40824;;;;;;;;;;;40844:24;40805:64;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40952:18;;;;;;;;;;;40940:56;;;41015:24;41070:23;41128:8;41171:4;41201:15;40940:303;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;40611:644;40248:1007;41360:20;41389:22;41360:52;;41488:23;41445:14;:24;;;41478:4;41445:39;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:66;;41423:211;;;;;;;;;;;;:::i;:::-;;;;;;;;;39533:2109;;;;;;39355:2287;;;:::o;42059:1888::-;42192:7;42212:25;42254:19;42212:62;;42285:36;42324:11;:22;;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;42285:63;;42361:18;18581:42;42382:37;;:28;:37;;;42361:58;;42434:13;42430:1510;;;42560:20;42583:21;42560:44;;42622:12;42640:10;:15;;42663:12;42640:40;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;42621:59;;;42721:7;42695:128;;;;;;;;;;;;:::i;:::-;;;;;;;;;42847:12;42840:19;;;;;;;;;42430:1510;42934:16;42959:28;42934:54;;43003:28;43034:10;:20;;;43063:4;43034:35;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;43003:66;;43135:1;43112:20;:24;43086:183;;;;;;;;;;;;:::i;:::-;;;;;;;;;43286:10;:18;;;43305;;;;;;;;;;;43325:20;43286:60;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;43363:25;43405:1;43391:16;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;43363:44;;43436:28;43422:8;43431:1;43422:11;;;;;;;;:::i;:::-;;;;;;;:42;;;;;;;;;;;18581;43479:8;43488:1;43479:11;;;;;;;;:::i;:::-;;;;;;;:19;;;;;;;;;;;43515:24;43554:18;;;;;;;;;;;43542:72;;;43637:20;43692:1;43732:8;43771:10;43810:15;43542:314;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;43515:341;;43918:7;43926:1;43918:10;;;;;;;;:::i;:::-;;;;;;;;43911:17;;;;;;;;;42059:1888;;;;;:::o;44225:628::-;44367:20;44396:22;44367:52;;44551:23;44508:14;:24;;;44541:4;44508:39;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:66;;44486:211;;;;;;;;;;;;:::i;:::-;;;;;;;;;44786:14;:22;;;44809:10;44821:23;44786:59;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;44356:497;44225:628;;:::o;21696:1655::-;21867:7;22042:21;22077:17;;;;;;;;;;22042:53;;22106:23;22132:10;:17;;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;22106:45;;22164:19;22186:10;:30;;;:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;22164:54;;22229:28;22260:10;:53;;;:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;22229:86;;22328:33;22364:11;:30;;;22416:19;22364:83;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;22328:119;;22458:33;22494:11;:30;;;22546:19;22494:83;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;22458:119;;22590:22;22747:6;22711:11;22632:19;22616:70;;;22687:20;22616:92;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:106;;;;:::i;:::-;22615:139;;;;:::i;:::-;22590:164;;22765:22;22916:20;22905:6;22791:103;22829:19;22863:20;22791:23;:103::i;:::-;:121;;;;:::i;:::-;22790:146;;;;:::i;:::-;22765:171;;22949:27;23009:25;22979:14;:55;;;;:::i;:::-;22949:85;;23045:27;23105:25;23075:14;:55;;;;:::i;:::-;23045:85;;23143:22;23191:19;23169;:41;23168:113;;23262:19;23168:113;;;23227:19;23168:113;23143:138;;23318:25;23301:14;:42;;;;:::i;:::-;23294:49;;;;;;;;;;;;;21696:1655;;;;;:::o;24727:1407::-;24975:28;25020:19;25006:59;;;:61;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;24975:92;;25078:21;18741:42;25102:28;;:20;:28;;;25078:52;;25198:23;25224:123;25258:20;25293:12;25320:16;25224:19;:123::i;:::-;25198:149;;25477:46;25526:63;25562:16;25526:21;:63::i;:::-;25477:112;;25602:17;25647:10;25685:20;25743:19;25799;25855:17;:28;;;:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;25927:15;25976:12;25622:392;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;25602:412;;26058:17;:27;;;26086:4;26092:10;26104:15;26121:4;26058:68;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;24910:1224;;;;;24727:1407;;;;:::o;23650:471::-;23775:7;23898:22;23939:14;23898:56;;23965:23;23991:44;;;;;;;;24006:6;:25;;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;23991:44;;;23965:70;;24053:60;24072:12;24086:6;:16;;;24103:8;24086:26;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;24053:18;:60::i;:::-;24046:67;;;;23650:471;;;;:::o;26615:619::-;26778:7;26798:21;26836:1;26822:16;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26798:40;;26980:17;26976:111;;;18661:42;27014:4;27019:1;27014:7;;;;;;;;:::i;:::-;;;;;;;:14;;;;;;;;;;;26976:111;;;18741:42;27061:4;27066:1;27061:7;;;;;;;;:::i;:::-;;;;;;;:14;;;;;;;;;;;26976:111;27107:21;27097:4;27102:1;27097:7;;;;;;;;:::i;:::-;;;;;;;:31;;;;;;;;;;;27171:18;;;;;;;;;;;27159:44;;;27204:12;27218:4;27159:64;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;27224:1;27159:67;;;;;;;;:::i;:::-;;;;;;;;27139:87;;;26615:619;;;;;:::o;27555:339::-;27660:28;27710:17;27706:181;;;27780:12;;;;;;;;;;;27744:49;;;;27706:181;27862:12;;;;;;;;;;;27826:49;;27555:339;;;;:::o;7921:212::-;8029:7;8054:18;8075:15;8080:1;8083:6;8075:4;:15::i;:::-;8054:36;;8108:17;8117:7;8108:8;:17::i;:::-;8101:24;;;7921:212;;;;:::o;8141:136::-;8203:10;;:::i;:::-;8233:36;;;;;;;;8248:19;8253:1;:10;;;8265:1;8248:4;:19::i;:::-;8233:36;;;8226:43;;8141:136;;;;:::o;8878:216::-;8935:7;7610:4;9063:3;:12;;;:23;;;;:::i;:::-;9056:30;;8878:216;;;:::o;8285:131::-;8344:7;8371:37;8376:1;8379;8371:37;;;;;;;;;;;;;;;;;:4;:37::i;:::-;8364:44;;8285:131;;;;:::o;8424:296::-;8545:7;8574:1;8569;:6;:16;;;;8584:1;8579;:6;8569:16;8565:57;;;8609:1;8602:8;;;;8565:57;8632:9;8648:1;8644;:5;;;;:::i;:::-;8632:17;;8677:1;8672;8668;:5;;;;:::i;:::-;:10;8680:12;8660:33;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;8711:1;8704:8;;;8424:296;;;;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;:::o;7:126:1:-;44:7;84:42;77:5;73:54;62:65;;7:126;;;:::o;139:96::-;176:7;205:24;223:5;205:24;:::i;:::-;194:35;;139:96;;;:::o;241:118::-;328:24;346:5;328:24;:::i;:::-;323:3;316:37;241:118;;:::o;365:222::-;458:4;496:2;485:9;481:18;473:26;;509:71;577:1;566:9;562:17;553:6;509:71;:::i;:::-;365:222;;;;:::o;593:75::-;626:6;659:2;653:9;643:19;;593:75;:::o;674:117::-;783:1;780;773:12;797:117;906:1;903;896:12;920:122;993:24;1011:5;993:24;:::i;:::-;986:5;983:35;973:63;;1032:1;1029;1022:12;973:63;920:122;:::o;1048:139::-;1094:5;1132:6;1119:20;1110:29;;1148:33;1175:5;1148:33;:::i;:::-;1048:139;;;;:::o;1193:77::-;1230:7;1259:5;1248:16;;1193:77;;;:::o;1276:122::-;1349:24;1367:5;1349:24;:::i;:::-;1342:5;1339:35;1329:63;;1388:1;1385;1378:12;1329:63;1276:122;:::o;1404:139::-;1450:5;1488:6;1475:20;1466:29;;1504:33;1531:5;1504:33;:::i;:::-;1404:139;;;;:::o;1549:117::-;1658:1;1655;1648:12;1672:117;1781:1;1778;1771:12;1795:117;1904:1;1901;1894:12;1931:552;1988:8;1998:6;2048:3;2041:4;2033:6;2029:17;2025:27;2015:122;;2056:79;;:::i;:::-;2015:122;2169:6;2156:20;2146:30;;2199:18;2191:6;2188:30;2185:117;;;2221:79;;:::i;:::-;2185:117;2335:4;2327:6;2323:17;2311:29;;2389:3;2381:4;2373:6;2369:17;2359:8;2355:32;2352:41;2349:128;;;2396:79;;:::i;:::-;2349:128;1931:552;;;;;:::o;2489:1109::-;2595:6;2603;2611;2619;2627;2635;2684:3;2672:9;2663:7;2659:23;2655:33;2652:120;;;2691:79;;:::i;:::-;2652:120;2811:1;2836:53;2881:7;2872:6;2861:9;2857:22;2836:53;:::i;:::-;2826:63;;2782:117;2938:2;2964:53;3009:7;3000:6;2989:9;2985:22;2964:53;:::i;:::-;2954:63;;2909:118;3066:2;3092:53;3137:7;3128:6;3117:9;3113:22;3092:53;:::i;:::-;3082:63;;3037:118;3194:2;3220:53;3265:7;3256:6;3245:9;3241:22;3220:53;:::i;:::-;3210:63;;3165:118;3350:3;3339:9;3335:19;3322:33;3382:18;3374:6;3371:30;3368:117;;;3404:79;;:::i;:::-;3368:117;3517:64;3573:7;3564:6;3553:9;3549:22;3517:64;:::i;:::-;3499:82;;;;3293:298;2489:1109;;;;;;;;:::o;3604:77::-;3641:7;3670:5;3659:16;;3604:77;;;:::o;3687:118::-;3774:24;3792:5;3774:24;:::i;:::-;3769:3;3762:37;3687:118;;:::o;3811:222::-;3904:4;3942:2;3931:9;3927:18;3919:26;;3955:71;4023:1;4012:9;4008:17;3999:6;3955:71;:::i;:::-;3811:222;;;;:::o;4039:619::-;4116:6;4124;4132;4181:2;4169:9;4160:7;4156:23;4152:32;4149:119;;;4187:79;;:::i;:::-;4149:119;4307:1;4332:53;4377:7;4368:6;4357:9;4353:22;4332:53;:::i;:::-;4322:63;;4278:117;4434:2;4460:53;4505:7;4496:6;4485:9;4481:22;4460:53;:::i;:::-;4450:63;;4405:118;4562:2;4588:53;4633:7;4624:6;4613:9;4609:22;4588:53;:::i;:::-;4578:63;;4533:118;4039:619;;;;;:::o;4664:90::-;4698:7;4741:5;4734:13;4727:21;4716:32;;4664:90;;;:::o;4760:116::-;4830:21;4845:5;4830:21;:::i;:::-;4823:5;4820:32;4810:60;;4866:1;4863;4856:12;4810:60;4760:116;:::o;4882:137::-;4936:5;4967:6;4961:13;4952:22;;4983:30;5007:5;4983:30;:::i;:::-;4882:137;;;;:::o;5025:345::-;5092:6;5141:2;5129:9;5120:7;5116:23;5112:32;5109:119;;;5147:79;;:::i;:::-;5109:119;5267:1;5292:61;5345:7;5336:6;5325:9;5321:22;5292:61;:::i;:::-;5282:71;;5238:125;5025:345;;;;:::o;5376:169::-;5460:11;5494:6;5489:3;5482:19;5534:4;5529:3;5525:14;5510:29;;5376:169;;;;:::o;5551:246::-;5691:34;5687:1;5679:6;5675:14;5668:58;5760:29;5755:2;5747:6;5743:15;5736:54;5551:246;:::o;5803:366::-;5945:3;5966:67;6030:2;6025:3;5966:67;:::i;:::-;5959:74;;6042:93;6131:3;6042:93;:::i;:::-;6160:2;6155:3;6151:12;6144:19;;5803:366;;;:::o;6175:419::-;6341:4;6379:2;6368:9;6364:18;6356:26;;6428:9;6422:4;6418:20;6414:1;6403:9;6399:17;6392:47;6456:131;6582:4;6456:131;:::i;:::-;6448:139;;6175:419;;;:::o;6600:143::-;6657:5;6688:6;6682:13;6673:22;;6704:33;6731:5;6704:33;:::i;:::-;6600:143;;;;:::o;6749:351::-;6819:6;6868:2;6856:9;6847:7;6843:23;6839:32;6836:119;;;6874:79;;:::i;:::-;6836:119;6994:1;7019:64;7075:7;7066:6;7055:9;7051:22;7019:64;:::i;:::-;7009:74;;6965:128;6749:351;;;;:::o;7106:244::-;7246:34;7242:1;7234:6;7230:14;7223:58;7315:27;7310:2;7302:6;7298:15;7291:52;7106:244;:::o;7356:366::-;7498:3;7519:67;7583:2;7578:3;7519:67;:::i;:::-;7512:74;;7595:93;7684:3;7595:93;:::i;:::-;7713:2;7708:3;7704:12;7697:19;;7356:366;;;:::o;7728:419::-;7894:4;7932:2;7921:9;7917:18;7909:26;;7981:9;7975:4;7971:20;7967:1;7956:9;7952:17;7945:47;8009:131;8135:4;8009:131;:::i;:::-;8001:139;;7728:419;;;:::o;8153:118::-;8240:24;8258:5;8240:24;:::i;:::-;8235:3;8228:37;8153:118;;:::o;8277:553::-;8454:4;8492:3;8481:9;8477:19;8469:27;;8506:71;8574:1;8563:9;8559:17;8550:6;8506:71;:::i;:::-;8587:72;8655:2;8644:9;8640:18;8631:6;8587:72;:::i;:::-;8669;8737:2;8726:9;8722:18;8713:6;8669:72;:::i;:::-;8751;8819:2;8808:9;8804:18;8795:6;8751:72;:::i;:::-;8277:553;;;;;;;:::o;8836:143::-;8893:5;8924:6;8918:13;8909:22;;8940:33;8967:5;8940:33;:::i;:::-;8836:143;;;;:::o;8985:663::-;9073:6;9081;9089;9138:2;9126:9;9117:7;9113:23;9109:32;9106:119;;;9144:79;;:::i;:::-;9106:119;9264:1;9289:64;9345:7;9336:6;9325:9;9321:22;9289:64;:::i;:::-;9279:74;;9235:128;9402:2;9428:64;9484:7;9475:6;9464:9;9460:22;9428:64;:::i;:::-;9418:74;;9373:129;9541:2;9567:64;9623:7;9614:6;9603:9;9599:22;9567:64;:::i;:::-;9557:74;;9512:129;8985:663;;;;;:::o;9654:250::-;9794:34;9790:1;9782:6;9778:14;9771:58;9863:33;9858:2;9850:6;9846:15;9839:58;9654:250;:::o;9910:366::-;10052:3;10073:67;10137:2;10132:3;10073:67;:::i;:::-;10066:74;;10149:93;10238:3;10149:93;:::i;:::-;10267:2;10262:3;10258:12;10251:19;;9910:366;;;:::o;10282:419::-;10448:4;10486:2;10475:9;10471:18;10463:26;;10535:9;10529:4;10525:20;10521:1;10510:9;10506:17;10499:47;10563:131;10689:4;10563:131;:::i;:::-;10555:139;;10282:419;;;:::o;10707:246::-;10847:34;10843:1;10835:6;10831:14;10824:58;10916:29;10911:2;10903:6;10899:15;10892:54;10707:246;:::o;10959:366::-;11101:3;11122:67;11186:2;11181:3;11122:67;:::i;:::-;11115:74;;11198:93;11287:3;11198:93;:::i;:::-;11316:2;11311:3;11307:12;11300:19;;10959:366;;;:::o;11331:419::-;11497:4;11535:2;11524:9;11520:18;11512:26;;11584:9;11578:4;11574:20;11570:1;11559:9;11555:17;11548:47;11612:131;11738:4;11612:131;:::i;:::-;11604:139;;11331:419;;;:::o;11756:104::-;11801:7;11830:24;11848:5;11830:24;:::i;:::-;11819:35;;11756:104;;;:::o;11866:138::-;11947:32;11973:5;11947:32;:::i;:::-;11940:5;11937:43;11927:71;;11994:1;11991;11984:12;11927:71;11866:138;:::o;12010:155::-;12064:5;12102:6;12089:20;12080:29;;12118:41;12153:5;12118:41;:::i;:::-;12010:155;;;;:::o;12171:1283::-;12324:6;12332;12340;12348;12356;12364;12372;12421:3;12409:9;12400:7;12396:23;12392:33;12389:120;;;12428:79;;:::i;:::-;12389:120;12548:1;12573:61;12626:7;12617:6;12606:9;12602:22;12573:61;:::i;:::-;12563:71;;12519:125;12683:2;12709:61;12762:7;12753:6;12742:9;12738:22;12709:61;:::i;:::-;12699:71;;12654:126;12819:2;12845:61;12898:7;12889:6;12878:9;12874:22;12845:61;:::i;:::-;12835:71;;12790:126;12955:2;12981:61;13034:7;13025:6;13014:9;13010:22;12981:61;:::i;:::-;12971:71;;12926:126;13091:3;13118:61;13171:7;13162:6;13151:9;13147:22;13118:61;:::i;:::-;13108:71;;13062:127;13228:3;13255:53;13300:7;13291:6;13280:9;13276:22;13255:53;:::i;:::-;13245:63;;13199:119;13357:3;13384:53;13429:7;13420:6;13409:9;13405:22;13384:53;:::i;:::-;13374:63;;13328:119;12171:1283;;;;;;;;;;:::o;13460:226::-;13600:34;13596:1;13588:6;13584:14;13577:58;13669:9;13664:2;13656:6;13652:15;13645:34;13460:226;:::o;13692:366::-;13834:3;13855:67;13919:2;13914:3;13855:67;:::i;:::-;13848:74;;13931:93;14020:3;13931:93;:::i;:::-;14049:2;14044:3;14040:12;14033:19;;13692:366;;;:::o;14064:419::-;14230:4;14268:2;14257:9;14253:18;14245:26;;14317:9;14311:4;14307:20;14303:1;14292:9;14288:17;14281:47;14345:131;14471:4;14345:131;:::i;:::-;14337:139;;14064:419;;;:::o;14489:292::-;14629:34;14625:1;14617:6;14613:14;14606:58;14698:34;14693:2;14685:6;14681:15;14674:59;14767:6;14762:2;14754:6;14750:15;14743:31;14489:292;:::o;14787:366::-;14929:3;14950:67;15014:2;15009:3;14950:67;:::i;:::-;14943:74;;15026:93;15115:3;15026:93;:::i;:::-;15144:2;15139:3;15135:12;15128:19;;14787:366;;;:::o;15159:419::-;15325:4;15363:2;15352:9;15348:18;15340:26;;15412:9;15406:4;15402:20;15398:1;15387:9;15383:17;15376:47;15440:131;15566:4;15440:131;:::i;:::-;15432:139;;15159:419;;;:::o;15584:247::-;15724:34;15720:1;15712:6;15708:14;15701:58;15793:30;15788:2;15780:6;15776:15;15769:55;15584:247;:::o;15837:366::-;15979:3;16000:67;16064:2;16059:3;16000:67;:::i;:::-;15993:74;;16076:93;16165:3;16076:93;:::i;:::-;16194:2;16189:3;16185:12;16178:19;;15837:366;;;:::o;16209:419::-;16375:4;16413:2;16402:9;16398:18;16390:26;;16462:9;16456:4;16452:20;16448:1;16437:9;16433:17;16426:47;16490:131;16616:4;16490:131;:::i;:::-;16482:139;;16209:419;;;:::o;16634:180::-;16682:77;16679:1;16672:88;16779:4;16776:1;16769:15;16803:4;16800:1;16793:15;16820:305;16860:3;16879:20;16897:1;16879:20;:::i;:::-;16874:25;;16913:20;16931:1;16913:20;:::i;:::-;16908:25;;17067:1;16999:66;16995:74;16992:1;16989:81;16986:107;;;17073:18;;:::i;:::-;16986:107;17117:1;17114;17110:9;17103:16;;16820:305;;;;:::o;17131:332::-;17252:4;17290:2;17279:9;17275:18;17267:26;;17303:71;17371:1;17360:9;17356:17;17347:6;17303:71;:::i;:::-;17384:72;17452:2;17441:9;17437:18;17428:6;17384:72;:::i;:::-;17131:332;;;;;:::o;17469:180::-;17517:77;17514:1;17507:88;17614:4;17611:1;17604:15;17638:4;17635:1;17628:15;17655:180;17703:77;17700:1;17693:88;17800:4;17797:1;17790:15;17824:4;17821:1;17814:15;17841:114;17908:6;17942:5;17936:12;17926:22;;17841:114;;;:::o;17961:184::-;18060:11;18094:6;18089:3;18082:19;18134:4;18129:3;18125:14;18110:29;;17961:184;;;;:::o;18151:132::-;18218:4;18241:3;18233:11;;18271:4;18266:3;18262:14;18254:22;;18151:132;;;:::o;18289:108::-;18366:24;18384:5;18366:24;:::i;:::-;18361:3;18354:37;18289:108;;:::o;18403:179::-;18472:10;18493:46;18535:3;18527:6;18493:46;:::i;:::-;18571:4;18566:3;18562:14;18548:28;;18403:179;;;;:::o;18588:113::-;18658:4;18690;18685:3;18681:14;18673:22;;18588:113;;;:::o;18737:732::-;18856:3;18885:54;18933:5;18885:54;:::i;:::-;18955:86;19034:6;19029:3;18955:86;:::i;:::-;18948:93;;19065:56;19115:5;19065:56;:::i;:::-;19144:7;19175:1;19160:284;19185:6;19182:1;19179:13;19160:284;;;19261:6;19255:13;19288:63;19347:3;19332:13;19288:63;:::i;:::-;19281:70;;19374:60;19427:6;19374:60;:::i;:::-;19364:70;;19220:224;19207:1;19204;19200:9;19195:14;;19160:284;;;19164:14;19460:3;19453:10;;18861:608;;;18737:732;;;;:::o;19475:815::-;19730:4;19768:3;19757:9;19753:19;19745:27;;19782:71;19850:1;19839:9;19835:17;19826:6;19782:71;:::i;:::-;19863:72;19931:2;19920:9;19916:18;19907:6;19863:72;:::i;:::-;19982:9;19976:4;19972:20;19967:2;19956:9;19952:18;19945:48;20010:108;20113:4;20104:6;20010:108;:::i;:::-;20002:116;;20128:72;20196:2;20185:9;20181:18;20172:6;20128:72;:::i;:::-;20210:73;20278:3;20267:9;20263:19;20254:6;20210:73;:::i;:::-;19475:815;;;;;;;;:::o;20296:102::-;20337:6;20388:2;20384:7;20379:2;20372:5;20368:14;20364:28;20354:38;;20296:102;;;:::o;20404:281::-;20487:27;20509:4;20487:27;:::i;:::-;20479:6;20475:40;20617:6;20605:10;20602:22;20581:18;20569:10;20566:34;20563:62;20560:88;;;20628:18;;:::i;:::-;20560:88;20668:10;20664:2;20657:22;20447:238;20404:281;;:::o;20691:129::-;20725:6;20752:20;;:::i;:::-;20742:30;;20781:33;20809:4;20801:6;20781:33;:::i;:::-;20691:129;;;:::o;20826:311::-;20903:4;20993:18;20985:6;20982:30;20979:56;;;21015:18;;:::i;:::-;20979:56;21065:4;21057:6;21053:17;21045:25;;21125:4;21119;21115:15;21107:23;;20826:311;;;:::o;21160:732::-;21267:5;21292:81;21308:64;21365:6;21308:64;:::i;:::-;21292:81;:::i;:::-;21283:90;;21393:5;21422:6;21415:5;21408:21;21456:4;21449:5;21445:16;21438:23;;21509:4;21501:6;21497:17;21489:6;21485:30;21538:3;21530:6;21527:15;21524:122;;;21557:79;;:::i;:::-;21524:122;21672:6;21655:231;21689:6;21684:3;21681:15;21655:231;;;21764:3;21793:48;21837:3;21825:10;21793:48;:::i;:::-;21788:3;21781:61;21871:4;21866:3;21862:14;21855:21;;21731:155;21715:4;21710:3;21706:14;21699:21;;21655:231;;;21659:21;21273:619;;21160:732;;;;;:::o;21915:385::-;21997:5;22046:3;22039:4;22031:6;22027:17;22023:27;22013:122;;22054:79;;:::i;:::-;22013:122;22164:6;22158:13;22189:105;22290:3;22282:6;22275:4;22267:6;22263:17;22189:105;:::i;:::-;22180:114;;22003:297;21915:385;;;;:::o;22306:554::-;22401:6;22450:2;22438:9;22429:7;22425:23;22421:32;22418:119;;;22456:79;;:::i;:::-;22418:119;22597:1;22586:9;22582:17;22576:24;22627:18;22619:6;22616:30;22613:117;;;22649:79;;:::i;:::-;22613:117;22754:89;22835:7;22826:6;22815:9;22811:22;22754:89;:::i;:::-;22744:99;;22547:306;22306:554;;;;:::o;22866:351::-;22936:6;22985:2;22973:9;22964:7;22960:23;22956:32;22953:119;;;22991:79;;:::i;:::-;22953:119;23111:1;23136:64;23192:7;23183:6;23172:9;23168:22;23136:64;:::i;:::-;23126:74;;23082:128;22866:351;;;;:::o;23223:315::-;23363:34;23359:1;23351:6;23347:14;23340:58;23432:34;23427:2;23419:6;23415:15;23408:59;23501:29;23496:2;23488:6;23484:15;23477:54;23223:315;:::o;23544:366::-;23686:3;23707:67;23771:2;23766:3;23707:67;:::i;:::-;23700:74;;23783:93;23872:3;23783:93;:::i;:::-;23901:2;23896:3;23892:12;23885:19;;23544:366;;;:::o;23916:419::-;24082:4;24120:2;24109:9;24105:18;24097:26;;24169:9;24163:4;24159:20;24155:1;24144:9;24140:17;24133:47;24197:131;24323:4;24197:131;:::i;:::-;24189:139;;23916:419;;;:::o;24341:60::-;24369:3;24390:5;24383:12;;24341:60;;;:::o;24407:142::-;24457:9;24490:53;24508:34;24517:24;24535:5;24517:24;:::i;:::-;24508:34;:::i;:::-;24490:53;:::i;:::-;24477:66;;24407:142;;;:::o;24555:126::-;24605:9;24638:37;24669:5;24638:37;:::i;:::-;24625:50;;24555:126;;;:::o;24687:149::-;24760:9;24793:37;24824:5;24793:37;:::i;:::-;24780:50;;24687:149;;;:::o;24842:177::-;24952:60;25006:5;24952:60;:::i;:::-;24947:3;24940:73;24842:177;;:::o;25025:378::-;25169:4;25207:2;25196:9;25192:18;25184:26;;25220:71;25288:1;25277:9;25273:17;25264:6;25220:71;:::i;:::-;25301:95;25392:2;25381:9;25377:18;25368:6;25301:95;:::i;:::-;25025:378;;;;;:::o;25409:488::-;25581:4;25619:2;25608:9;25604:18;25596:26;;25632:71;25700:1;25689:9;25685:17;25676:6;25632:71;:::i;:::-;25713:72;25781:2;25770:9;25766:18;25757:6;25713:72;:::i;:::-;25795:95;25886:2;25875:9;25871:18;25862:6;25795:95;:::i;:::-;25409:488;;;;;;:::o;25903:242::-;26043:34;26039:1;26031:6;26027:14;26020:58;26112:25;26107:2;26099:6;26095:15;26088:50;25903:242;:::o;26151:366::-;26293:3;26314:67;26378:2;26373:3;26314:67;:::i;:::-;26307:74;;26390:93;26479:3;26390:93;:::i;:::-;26508:2;26503:3;26499:12;26492:19;;26151:366;;;:::o;26523:419::-;26689:4;26727:2;26716:9;26712:18;26704:26;;26776:9;26770:4;26766:20;26762:1;26751:9;26747:17;26740:47;26804:131;26930:4;26804:131;:::i;:::-;26796:139;;26523:419;;;:::o;26948:222::-;27041:4;27079:2;27068:9;27064:18;27056:26;;27092:71;27160:1;27149:9;27145:17;27136:6;27092:71;:::i;:::-;26948:222;;;;:::o;27176:294::-;27316:34;27312:1;27304:6;27300:14;27293:58;27385:34;27380:2;27372:6;27368:15;27361:59;27454:8;27449:2;27441:6;27437:15;27430:33;27176:294;:::o;27476:366::-;27618:3;27639:67;27703:2;27698:3;27639:67;:::i;:::-;27632:74;;27715:93;27804:3;27715:93;:::i;:::-;27833:2;27828:3;27824:12;27817:19;;27476:366;;;:::o;27848:419::-;28014:4;28052:2;28041:9;28037:18;28029:26;;28101:9;28095:4;28091:20;28087:1;28076:9;28072:17;28065:47;28129:131;28255:4;28129:131;:::i;:::-;28121:139;;27848:419;;;:::o;28273:483::-;28444:4;28482:2;28471:9;28467:18;28459:26;;28495:71;28563:1;28552:9;28548:17;28539:6;28495:71;:::i;:::-;28613:9;28607:4;28603:20;28598:2;28587:9;28583:18;28576:48;28641:108;28744:4;28735:6;28641:108;:::i;:::-;28633:116;;28273:483;;;;;:::o;28762:704::-;28989:4;29027:3;29016:9;29012:19;29004:27;;29041:71;29109:1;29098:9;29094:17;29085:6;29041:71;:::i;:::-;29159:9;29153:4;29149:20;29144:2;29133:9;29129:18;29122:48;29187:108;29290:4;29281:6;29187:108;:::i;:::-;29179:116;;29305:72;29373:2;29362:9;29358:18;29349:6;29305:72;:::i;:::-;29387;29455:2;29444:9;29440:18;29431:6;29387:72;:::i;:::-;28762:704;;;;;;;:::o;29472:319::-;29612:34;29608:1;29600:6;29596:14;29589:58;29681:34;29676:2;29668:6;29664:15;29657:59;29750:33;29745:2;29737:6;29733:15;29726:58;29472:319;:::o;29797:366::-;29939:3;29960:67;30024:2;30019:3;29960:67;:::i;:::-;29953:74;;30036:93;30125:3;30036:93;:::i;:::-;30154:2;30149:3;30145:12;30138:19;;29797:366;;;:::o;30169:419::-;30335:4;30373:2;30362:9;30358:18;30350:26;;30422:9;30416:4;30412:20;30408:1;30397:9;30393:17;30386:47;30450:131;30576:4;30450:131;:::i;:::-;30442:139;;30169:419;;;:::o;30594:147::-;30695:11;30732:3;30717:18;;30594:147;;;;:::o;30747:114::-;;:::o;30867:398::-;31026:3;31047:83;31128:1;31123:3;31047:83;:::i;:::-;31040:90;;31139:93;31228:3;31139:93;:::i;:::-;31257:1;31252:3;31248:11;31241:18;;30867:398;;;:::o;31271:379::-;31455:3;31477:147;31620:3;31477:147;:::i;:::-;31470:154;;31641:3;31634:10;;31271:379;;;:::o;31656:246::-;31796:34;31792:1;31784:6;31780:14;31773:58;31865:29;31860:2;31852:6;31848:15;31841:54;31656:246;:::o;31908:366::-;32050:3;32071:67;32135:2;32130:3;32071:67;:::i;:::-;32064:74;;32147:93;32236:3;32147:93;:::i;:::-;32265:2;32260:3;32256:12;32249:19;;31908:366;;;:::o;32280:419::-;32446:4;32484:2;32473:9;32469:18;32461:26;;32533:9;32527:4;32523:20;32519:1;32508:9;32504:17;32497:47;32561:131;32687:4;32561:131;:::i;:::-;32553:139;;32280:419;;;:::o;32705:358::-;32845:34;32841:1;32833:6;32829:14;32822:58;32914:34;32909:2;32901:6;32897:15;32890:59;32983:34;32978:2;32970:6;32966:15;32959:59;33052:3;33047:2;33039:6;33035:15;33028:28;32705:358;:::o;33069:367::-;33211:3;33232:67;33296:2;33291:3;33232:67;:::i;:::-;33225:74;;33308:93;33397:3;33308:93;:::i;:::-;33426:3;33421;33417:13;33410:20;;33069:367;;;:::o;33442:419::-;33608:4;33646:2;33635:9;33631:18;33623:26;;33695:9;33689:4;33685:20;33681:1;33670:9;33666:17;33659:47;33723:131;33849:4;33723:131;:::i;:::-;33715:139;;33442:419;;;:::o;33867:85::-;33912:7;33941:5;33930:16;;33867:85;;;:::o;33958:158::-;34016:9;34049:61;34067:42;34076:32;34102:5;34076:32;:::i;:::-;34067:42;:::i;:::-;34049:61;:::i;:::-;34036:74;;33958:158;;;:::o;34122:147::-;34217:45;34256:5;34217:45;:::i;:::-;34212:3;34205:58;34122:147;;:::o;34275:831::-;34538:4;34576:3;34565:9;34561:19;34553:27;;34590:71;34658:1;34647:9;34643:17;34634:6;34590:71;:::i;:::-;34671:80;34747:2;34736:9;34732:18;34723:6;34671:80;:::i;:::-;34798:9;34792:4;34788:20;34783:2;34772:9;34768:18;34761:48;34826:108;34929:4;34920:6;34826:108;:::i;:::-;34818:116;;34944:72;35012:2;35001:9;34997:18;34988:6;34944:72;:::i;:::-;35026:73;35094:3;35083:9;35079:19;35070:6;35026:73;:::i;:::-;34275:831;;;;;;;;:::o;35112:115::-;35168:7;35197:24;35215:5;35197:24;:::i;:::-;35186:35;;35112:115;;;:::o;35233:160::-;35325:43;35362:5;35325:43;:::i;:::-;35318:5;35315:54;35305:82;;35383:1;35380;35373:12;35305:82;35233:160;:::o;35399:181::-;35475:5;35506:6;35500:13;35491:22;;35522:52;35568:5;35522:52;:::i;:::-;35399:181;;;;:::o;35586:389::-;35675:6;35724:2;35712:9;35703:7;35699:23;35695:32;35692:119;;;35730:79;;:::i;:::-;35692:119;35850:1;35875:83;35950:7;35941:6;35930:9;35926:22;35875:83;:::i;:::-;35865:93;;35821:147;35586:389;;;;:::o;35981:140::-;36045:9;36078:37;36109:5;36078:37;:::i;:::-;36065:50;;35981:140;;;:::o;36127:159::-;36228:51;36273:5;36228:51;:::i;:::-;36223:3;36216:64;36127:159;;:::o;36292:250::-;36399:4;36437:2;36426:9;36422:18;36414:26;;36450:85;36532:1;36521:9;36517:17;36508:6;36450:85;:::i;:::-;36292:250;;;;:::o;36548:348::-;36588:7;36611:20;36629:1;36611:20;:::i;:::-;36606:25;;36645:20;36663:1;36645:20;:::i;:::-;36640:25;;36833:1;36765:66;36761:74;36758:1;36755:81;36750:1;36743:9;36736:17;36732:105;36729:131;;;36840:18;;:::i;:::-;36729:131;36888:1;36885;36881:9;36870:20;;36548:348;;;;:::o;36902:180::-;36950:77;36947:1;36940:88;37047:4;37044:1;37037:15;37071:4;37068:1;37061:15;37088:185;37128:1;37145:20;37163:1;37145:20;:::i;:::-;37140:25;;37179:20;37197:1;37179:20;:::i;:::-;37174:25;;37218:1;37208:35;;37223:18;;:::i;:::-;37208:35;37265:1;37262;37258:9;37253:14;;37088:185;;;;:::o;37279:886::-;37540:4;37578:3;37567:9;37563:19;37555:27;;37592:71;37660:1;37649:9;37645:17;37636:6;37592:71;:::i;:::-;37673:72;37741:2;37730:9;37726:18;37717:6;37673:72;:::i;:::-;37755;37823:2;37812:9;37808:18;37799:6;37755:72;:::i;:::-;37837;37905:2;37894:9;37890:18;37881:6;37837:72;:::i;:::-;37919:73;37987:3;37976:9;37972:19;37963:6;37919:73;:::i;:::-;38002;38070:3;38059:9;38055:19;38046:6;38002:73;:::i;:::-;38085;38153:3;38142:9;38138:19;38129:6;38085:73;:::i;:::-;37279:886;;;;;;;;;;:::o;38171:148::-;38243:9;38276:37;38307:5;38276:37;:::i;:::-;38263:50;;38171:148;;;:::o;38325:175::-;38434:59;38487:5;38434:59;:::i;:::-;38429:3;38422:72;38325:175;;:::o;38506:98::-;38557:6;38591:5;38585:12;38575:22;;38506:98;;;:::o;38610:168::-;38693:11;38727:6;38722:3;38715:19;38767:4;38762:3;38758:14;38743:29;;38610:168;;;;:::o;38784:307::-;38852:1;38862:113;38876:6;38873:1;38870:13;38862:113;;;38961:1;38956:3;38952:11;38946:18;38942:1;38937:3;38933:11;38926:39;38898:2;38895:1;38891:10;38886:15;;38862:113;;;38993:6;38990:1;38987:13;38984:101;;;39073:1;39064:6;39059:3;39055:16;39048:27;38984:101;38833:258;38784:307;;;:::o;39097:360::-;39183:3;39211:38;39243:5;39211:38;:::i;:::-;39265:70;39328:6;39323:3;39265:70;:::i;:::-;39258:77;;39344:52;39389:6;39384:3;39377:4;39370:5;39366:16;39344:52;:::i;:::-;39421:29;39443:6;39421:29;:::i;:::-;39416:3;39412:39;39405:46;;39187:270;39097:360;;;;:::o;39463:684::-;39680:4;39718:3;39707:9;39703:19;39695:27;;39732:93;39822:1;39811:9;39807:17;39798:6;39732:93;:::i;:::-;39835:72;39903:2;39892:9;39888:18;39879:6;39835:72;:::i;:::-;39917;39985:2;39974:9;39970:18;39961:6;39917:72;:::i;:::-;40036:9;40030:4;40026:20;40021:2;40010:9;40006:18;39999:48;40064:76;40135:4;40126:6;40064:76;:::i;:::-;40056:84;;39463:684;;;;;;;:::o;40153:99::-;40205:6;40239:5;40233:12;40223:22;;40153:99;;;:::o;40258:364::-;40346:3;40374:39;40407:5;40374:39;:::i;:::-;40429:71;40493:6;40488:3;40429:71;:::i;:::-;40422:78;;40509:52;40554:6;40549:3;40542:4;40535:5;40531:16;40509:52;:::i;:::-;40586:29;40608:6;40586:29;:::i;:::-;40581:3;40577:39;40570:46;;40350:272;40258:364;;;;:::o;40628:313::-;40741:4;40779:2;40768:9;40764:18;40756:26;;40828:9;40822:4;40818:20;40814:1;40803:9;40799:17;40792:47;40856:78;40929:4;40920:6;40856:78;:::i;:::-;40848:86;;40628:313;;;;:::o
Swarm Source
ipfs://30f82ddb7939846bbf3111eb31139576c8a2ba5ac7c4a223a48dead1d3326659
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.