Contract 0x76e6d394e9481d50da2500d9f58e21d4956e1923

Txn Hash Method
Block
From
To
Value
0x509ae32774dcb8eb5556222b6a4656cc98e1ab3a8df3a851173a3de20340170bWithdraw Collate...248733072021-05-16 16:34:482 days 4 hrs ago0xe201fa932724229cb614ee1938e17c8cf189c33e IN  0x76e6d394e9481d50da2500d9f58e21d4956e19230 Ether0.0009701793
0x4e88b1273c74f31bd255d17f76d2540c4de0060969cfae06babc633ff7093197Collateralize248732912021-05-16 16:33:442 days 4 hrs ago0xe201fa932724229cb614ee1938e17c8cf189c33e IN  0x76e6d394e9481d50da2500d9f58e21d4956e19230.01 Ether0.0003281853
0x40da3991471cb7179e5a9419aa759e96236b614ccd451a3aefa7d813108d17a9Borrow248232572021-05-14 5:41:124 days 15 hrs ago0x66cd62c6f8a4bb0cd8720488bcbd1a6221b765f9 IN  0x76e6d394e9481d50da2500d9f58e21d4956e19230 Ether0.0006146331971.2075
0x3ad886675ed629c040c001c9f64430ce542263232b1630f7eb63293dedd9b0ecCollateralize248232512021-05-14 5:40:364 days 15 hrs ago0x66cd62c6f8a4bb0cd8720488bcbd1a6221b765f9 IN  0x76e6d394e9481d50da2500d9f58e21d4956e19230 Ether0.0001587150071.2075
0xef8df7351ed388566a74e687bfc573b48294dfa19018455fd3b60e08fc7fc517Withdraw Collate...247811802021-05-11 8:35:447 days 12 hrs ago0xde00d94f4d830364f72ba7105c048c39c1fa830a IN  0x76e6d394e9481d50da2500d9f58e21d4956e19230 Ether0.0011673843
0x62dbd129ee705f98531879b139475c1baa6aec0405da8b8d1928eb44c9b079a8Repay Borrow247811762021-05-11 8:35:207 days 12 hrs ago0xde00d94f4d830364f72ba7105c048c39c1fa830a IN  0x76e6d394e9481d50da2500d9f58e21d4956e19230 Ether0.0004151553
0xe9c5f1fd83ef7a118ece381071b0e884b528a9d9866d9573808d243a0b6cc88fBorrow247811722021-05-11 8:34:567 days 12 hrs ago0xde00d94f4d830364f72ba7105c048c39c1fa830a IN  0x76e6d394e9481d50da2500d9f58e21d4956e19230 Ether0.0014130393
0xa10ccb857dd3de106db03874d9895c506f154dcbc61f9a28e11fad2dcb6c5129Collateralize247811642021-05-11 8:34:087 days 12 hrs ago0xde00d94f4d830364f72ba7105c048c39c1fa830a IN  0x76e6d394e9481d50da2500d9f58e21d4956e19230 Ether0.0002916153
0xaa3be5f84d302c4b87c93df165f33b922954d2b7f67355749987556ee41cfe5eWithdraw Collate...247811602021-05-11 8:33:447 days 12 hrs ago0xde00d94f4d830364f72ba7105c048c39c1fa830a IN  0x76e6d394e9481d50da2500d9f58e21d4956e19230 Ether0.0011673843
0x2997469083f92d4f006fc8cbaf87132adf32043a2032e0070612527e0011b0efRepay Borrow247811572021-05-11 8:33:247 days 12 hrs ago0xde00d94f4d830364f72ba7105c048c39c1fa830a IN  0x76e6d394e9481d50da2500d9f58e21d4956e19230 Ether0.000513573
0x3d31517751d5907c38f0872792a7ff3dd5903eac50134e8fff52e72eab38cbf0Collateralize247811332021-05-11 8:31:087 days 12 hrs ago0xde00d94f4d830364f72ba7105c048c39c1fa830a IN  0x76e6d394e9481d50da2500d9f58e21d4956e19230 Ether0.0002916153
0xb7cbf0146d048a196737e8eed68d023442f76fd7a305ee03bc67e4c97eeff13aWithdraw Collate...247809912021-05-11 8:17:087 days 12 hrs ago0xde00d94f4d830364f72ba7105c048c39c1fa830a IN  0x76e6d394e9481d50da2500d9f58e21d4956e19230 Ether0.0012186843
0xca55be3bf0ea3a348d0b393d7b538b51c4d9225efd0877e6d4a03d35e559f88eRepay Borrow247809882021-05-11 8:16:487 days 12 hrs ago0xde00d94f4d830364f72ba7105c048c39c1fa830a IN  0x76e6d394e9481d50da2500d9f58e21d4956e19230 Ether0.0004517553
0x3cbf524053964594a1b27d2e200d959c5aa0265de95b708e4ee15fa6a3c87ef0Withdraw Collate...247809762021-05-11 8:15:367 days 12 hrs ago0xde00d94f4d830364f72ba7105c048c39c1fa830a IN  0x76e6d394e9481d50da2500d9f58e21d4956e19230 Ether0.0011615043
0x8f0c6a4a1b80a77a3e81e7a3ffb80dd36fe614f172b251ecff20535a36e1444dBorrow247809732021-05-11 8:15:207 days 12 hrs ago0xde00d94f4d830364f72ba7105c048c39c1fa830a IN  0x76e6d394e9481d50da2500d9f58e21d4956e19230 Ether0.0001908153
0x35363e8dc3e0bbdd2e243031887fe74382dffeb7c2ce029d389a016388f4e2f3Borrow247809722021-05-11 8:15:127 days 12 hrs ago0xde00d94f4d830364f72ba7105c048c39c1fa830a IN  0x76e6d394e9481d50da2500d9f58e21d4956e19230 Ether0.0015054663
0x5dff8823f1e31dfbe415786260d8b27f12eb66e1be81ed40e78c574995929ae4Collateralize247809332021-05-11 8:11:247 days 12 hrs ago0xde00d94f4d830364f72ba7105c048c39c1fa830a IN  0x76e6d394e9481d50da2500d9f58e21d4956e19230 Ether0.0003491793
0xbaee29ed264e3e6d5d59ae772e7f567d9936e1a0cc9ce55d3745ff899f1d8d1dCollateralize247809182021-05-11 8:09:567 days 12 hrs ago0xde00d94f4d830364f72ba7105c048c39c1fa830a IN  0x76e6d394e9481d50da2500d9f58e21d4956e19230 Ether0.0003493233
0xd44fb5e391d79f7bf7e6cf21c81c478b62b782773ce2a9338c6a4024ffed9a02Supply247808902021-05-11 8:07:127 days 12 hrs ago0xde00d94f4d830364f72ba7105c048c39c1fa830a IN  0x76e6d394e9481d50da2500d9f58e21d4956e19230 Ether0.000561123
0x2675a6241dd224c91b755608219c38df94e9a459e03114ecda094249693f756fSupply247808712021-05-11 8:05:207 days 12 hrs ago0xde00d94f4d830364f72ba7105c048c39c1fa830a IN  0x76e6d394e9481d50da2500d9f58e21d4956e19230 Ether0.000561123
0x9ff3511de6244b9ba8362dd45cb0c4baf735800435b1031172f3fa4917fc4da6Borrow243350302021-04-19 17:34:0429 days 3 hrs ago0xdde39a0150a5fb4a92cf2936d5c5428687335a15 IN  0x76e6d394e9481d50da2500d9f58e21d4956e19230 Ether0.0024084355
0x0032e9c0a83309f7e519b5bc989aa9c6ec4bf054896a8fef595ca32602366fe6Borrow243350252021-04-19 17:33:4429 days 3 hrs ago0xdde39a0150a5fb4a92cf2936d5c5428687335a15 IN  0x76e6d394e9481d50da2500d9f58e21d4956e19230 Ether0.002401545
0xe7323ea269a23d8011630d645609edbfa6c1e3a8597bfbab4374484713e8e62fBorrow243350092021-04-19 17:32:4029 days 3 hrs ago0xdde39a0150a5fb4a92cf2936d5c5428687335a15 IN  0x76e6d394e9481d50da2500d9f58e21d4956e19230 Ether0.002312035
0x39705987e12bb57f9a9ed68cd578ea4ccd57f4ad06c644ce0b78d5266745f16bCollateralize243350022021-04-19 17:32:1229 days 3 hrs ago0xdde39a0150a5fb4a92cf2936d5c5428687335a15 IN  0x76e6d394e9481d50da2500d9f58e21d4956e19230 Ether0.0004939655
0x7b6a94cfe72496e196af253bc3d32fe2fc548902d3453bb4ed24ed9dbb5ebaefCollateralize243349982021-04-19 17:31:5229 days 3 hrs ago0xdde39a0150a5fb4a92cf2936d5c5428687335a15 IN  0x76e6d394e9481d50da2500d9f58e21d4956e19230 Ether0.0004942055
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x509ae32774dcb8eb5556222b6a4656cc98e1ab3a8df3a851173a3de20340170b248733072021-05-16 16:34:482 days 4 hrs ago 0x76e6d394e9481d50da2500d9f58e21d4956e1923 0x1125382fd40a0bf48f7d2523a0818ca9d3fcfe390 Ether
0x509ae32774dcb8eb5556222b6a4656cc98e1ab3a8df3a851173a3de20340170b248733072021-05-16 16:34:482 days 4 hrs ago 0x76e6d394e9481d50da2500d9f58e21d4956e1923 0x2b27b93bcd2ed768b5f365f4577d6eeb27186f4f0 Ether
0x509ae32774dcb8eb5556222b6a4656cc98e1ab3a8df3a851173a3de20340170b248733072021-05-16 16:34:482 days 4 hrs ago 0x76e6d394e9481d50da2500d9f58e21d4956e1923 0xdb7908137be8a89a80c094ac93bee37693a1c9680 Ether
0x509ae32774dcb8eb5556222b6a4656cc98e1ab3a8df3a851173a3de20340170b248733072021-05-16 16:34:482 days 4 hrs ago 0x76e6d394e9481d50da2500d9f58e21d4956e1923 0x2b27b93bcd2ed768b5f365f4577d6eeb27186f4f0 Ether
0x509ae32774dcb8eb5556222b6a4656cc98e1ab3a8df3a851173a3de20340170b248733072021-05-16 16:34:482 days 4 hrs ago 0x76e6d394e9481d50da2500d9f58e21d4956e1923 0xdb7908137be8a89a80c094ac93bee37693a1c9680 Ether
0x509ae32774dcb8eb5556222b6a4656cc98e1ab3a8df3a851173a3de20340170b248733072021-05-16 16:34:482 days 4 hrs ago 0x76e6d394e9481d50da2500d9f58e21d4956e1923 0x2b27b93bcd2ed768b5f365f4577d6eeb27186f4f0 Ether
0x509ae32774dcb8eb5556222b6a4656cc98e1ab3a8df3a851173a3de20340170b248733072021-05-16 16:34:482 days 4 hrs ago 0x76e6d394e9481d50da2500d9f58e21d4956e1923 0xdb7908137be8a89a80c094ac93bee37693a1c9680 Ether
0x509ae32774dcb8eb5556222b6a4656cc98e1ab3a8df3a851173a3de20340170b248733072021-05-16 16:34:482 days 4 hrs ago 0x76e6d394e9481d50da2500d9f58e21d4956e1923 0x2b27b93bcd2ed768b5f365f4577d6eeb27186f4f0 Ether
0x509ae32774dcb8eb5556222b6a4656cc98e1ab3a8df3a851173a3de20340170b248733072021-05-16 16:34:482 days 4 hrs ago 0x76e6d394e9481d50da2500d9f58e21d4956e1923 0xdb7908137be8a89a80c094ac93bee37693a1c9680 Ether
0x509ae32774dcb8eb5556222b6a4656cc98e1ab3a8df3a851173a3de20340170b248733072021-05-16 16:34:482 days 4 hrs ago 0x76e6d394e9481d50da2500d9f58e21d4956e1923 0xdb7908137be8a89a80c094ac93bee37693a1c9680 Ether
0x509ae32774dcb8eb5556222b6a4656cc98e1ab3a8df3a851173a3de20340170b248733072021-05-16 16:34:482 days 4 hrs ago 0x76e6d394e9481d50da2500d9f58e21d4956e1923 0x2b27b93bcd2ed768b5f365f4577d6eeb27186f4f0 Ether
0x509ae32774dcb8eb5556222b6a4656cc98e1ab3a8df3a851173a3de20340170b248733072021-05-16 16:34:482 days 4 hrs ago 0x76e6d394e9481d50da2500d9f58e21d4956e1923 0xdb7908137be8a89a80c094ac93bee37693a1c9680 Ether
0x4e88b1273c74f31bd255d17f76d2540c4de0060969cfae06babc633ff7093197248732912021-05-16 16:33:442 days 4 hrs ago 0x76e6d394e9481d50da2500d9f58e21d4956e1923 0x1125382fd40a0bf48f7d2523a0818ca9d3fcfe390.01 Ether
0x4e88b1273c74f31bd255d17f76d2540c4de0060969cfae06babc633ff7093197248732912021-05-16 16:33:442 days 4 hrs ago 0x76e6d394e9481d50da2500d9f58e21d4956e1923 0xdb7908137be8a89a80c094ac93bee37693a1c9680 Ether
0x40da3991471cb7179e5a9419aa759e96236b614ccd451a3aefa7d813108d17a9248232572021-05-14 5:41:124 days 15 hrs ago 0x76e6d394e9481d50da2500d9f58e21d4956e1923 0xf38de8bd6184f51efba04d351eb090126eb7be2a0 Ether
0x40da3991471cb7179e5a9419aa759e96236b614ccd451a3aefa7d813108d17a9248232572021-05-14 5:41:124 days 15 hrs ago 0x76e6d394e9481d50da2500d9f58e21d4956e1923 0xdb7908137be8a89a80c094ac93bee37693a1c9680 Ether
0x40da3991471cb7179e5a9419aa759e96236b614ccd451a3aefa7d813108d17a9248232572021-05-14 5:41:124 days 15 hrs ago 0xdb7908137be8a89a80c094ac93bee37693a1c968 0x76e6d394e9481d50da2500d9f58e21d4956e19230 Ether
0x40da3991471cb7179e5a9419aa759e96236b614ccd451a3aefa7d813108d17a9248232572021-05-14 5:41:124 days 15 hrs ago 0xdb7908137be8a89a80c094ac93bee37693a1c968 0x76e6d394e9481d50da2500d9f58e21d4956e19230 Ether
0x40da3991471cb7179e5a9419aa759e96236b614ccd451a3aefa7d813108d17a9248232572021-05-14 5:41:124 days 15 hrs ago 0x76e6d394e9481d50da2500d9f58e21d4956e1923 0xdb7908137be8a89a80c094ac93bee37693a1c9680 Ether
0x40da3991471cb7179e5a9419aa759e96236b614ccd451a3aefa7d813108d17a9248232572021-05-14 5:41:124 days 15 hrs ago 0xdb7908137be8a89a80c094ac93bee37693a1c968 0x76e6d394e9481d50da2500d9f58e21d4956e19230 Ether
0x40da3991471cb7179e5a9419aa759e96236b614ccd451a3aefa7d813108d17a9248232572021-05-14 5:41:124 days 15 hrs ago 0xdb7908137be8a89a80c094ac93bee37693a1c968 0x76e6d394e9481d50da2500d9f58e21d4956e19230 Ether
0x40da3991471cb7179e5a9419aa759e96236b614ccd451a3aefa7d813108d17a9248232572021-05-14 5:41:124 days 15 hrs ago 0x76e6d394e9481d50da2500d9f58e21d4956e1923 0xdb7908137be8a89a80c094ac93bee37693a1c9680 Ether
0x40da3991471cb7179e5a9419aa759e96236b614ccd451a3aefa7d813108d17a9248232572021-05-14 5:41:124 days 15 hrs ago 0x76e6d394e9481d50da2500d9f58e21d4956e1923 0xdb7908137be8a89a80c094ac93bee37693a1c9680 Ether
0x40da3991471cb7179e5a9419aa759e96236b614ccd451a3aefa7d813108d17a9248232572021-05-14 5:41:124 days 15 hrs ago 0x76e6d394e9481d50da2500d9f58e21d4956e1923 0x2b27b93bcd2ed768b5f365f4577d6eeb27186f4f0 Ether
0x40da3991471cb7179e5a9419aa759e96236b614ccd451a3aefa7d813108d17a9248232572021-05-14 5:41:124 days 15 hrs ago 0x76e6d394e9481d50da2500d9f58e21d4956e1923 0x2b27b93bcd2ed768b5f365f4577d6eeb27186f4f0 Ether
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Holdefi

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, Unlicense license

Contract Source Code (Solidity Multiple files format)

File 1 of 6: Holdefi.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;

import "./SafeMath.sol";
import "./HoldefiPausableOwnable.sol";
import "./HoldefiCollaterals.sol";


/// @notice File: contracts/HoldefiPrices.sol
interface HoldefiPricesInterface {
	function getAssetValueFromAmount(address asset, uint256 amount) external view returns(uint256 value);
	function getAssetAmountFromValue(address asset, uint256 value) external view returns(uint256 amount);	
}

/// @notice File: contracts/HoldefiSettings.sol
interface HoldefiSettingsInterface {

	/// @notice Markets Features
	struct MarketSettings {
		bool isExist;
		bool isActive;      

		uint256 borrowRate;
		uint256 borrowRateUpdateTime;

		uint256 suppliersShareRate;
		uint256 suppliersShareRateUpdateTime;

		uint256 promotionRate;
	}

	/// @notice Collateral Features
	struct CollateralSettings {
		bool isExist;
		bool isActive;    

		uint256 valueToLoanRate; 
		uint256 VTLUpdateTime;

		uint256 penaltyRate;
		uint256 penaltyUpdateTime;

		uint256 bonusRate;
	}

	function getInterests(address market)
		external
		view
		returns (uint256 borrowRate, uint256 supplyRateBase, uint256 promotionRate);
	function resetPromotionRate (address market) external;
	function getMarketsList() external view returns(address[] memory marketsList);
	function marketAssets(address market) external view returns(MarketSettings memory);
	function collateralAssets(address collateral) external view returns(CollateralSettings memory);
}

/// @title Main Holdefi contract
/// @author Holdefi Team
/// @dev The address of ETH considered as 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
/// @dev All indexes are scaled by (secondsPerYear * rateDecimals)
/// @dev All values are based ETH price considered 1 and all values decimals considered 30
contract Holdefi is HoldefiPausableOwnable {

	using SafeMath for uint256;

	/// @notice Markets are assets can be supplied and borrowed
	struct Market {
		uint256 totalSupply;

		uint256 supplyIndex;      				// Scaled by: secondsPerYear * rateDecimals
		uint256 supplyIndexUpdateTime;

		uint256 totalBorrow;

		uint256 borrowIndex;      				// Scaled by: secondsPerYear * rateDecimals
		uint256 borrowIndexUpdateTime;

		uint256 promotionReserveScaled;      	// Scaled by: secondsPerYear * rateDecimals
		uint256 promotionReserveLastUpdateTime;

		uint256 promotionDebtScaled;      		// Scaled by: secondsPerYear * rateDecimals
		uint256 promotionDebtLastUpdateTime;
	}

	/// @notice Collaterals are assets can be used only as collateral for borrowing with no interest
	struct Collateral {
		uint256 totalCollateral;
		uint256 totalLiquidatedCollateral;
	}

	/// @notice Users profile for each market
	struct MarketAccount {
		mapping (address => uint) allowance;
		uint256 balance;
		uint256 accumulatedInterest;

		uint256 lastInterestIndex;      		// Scaled by: secondsPerYear * rateDecimals
	}

	/// @notice Users profile for each collateral
	struct CollateralAccount {
		mapping (address => uint) allowance;
		uint256 balance;
		uint256 lastUpdateTime;
	}

	struct MarketData {
		uint256 balance;
		uint256 interest;
		uint256 currentIndex; 
	}

	address constant public ethAddress = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;

	/// @notice All rates in this contract are scaled by rateDecimals
	uint256 constant public rateDecimals = 10 ** 4;

	uint256 constant public secondsPerYear = 31536000;

	/// @dev For round up borrow interests
	uint256 constant private oneUnit = 1;

	/// @dev Used for calculating liquidation threshold 
	/// @dev There is 5% gap between value to loan rate and liquidation rate
	uint256 constant private fivePercentLiquidationGap = 500;

	/// @notice Contract for getting protocol settings
	HoldefiSettingsInterface public holdefiSettings;

	/// @notice Contract for getting asset prices
	HoldefiPricesInterface public holdefiPrices;

	/// @notice Contract for holding collaterals
	HoldefiCollaterals public holdefiCollaterals;

	/// @dev Markets: marketAddress => marketDetails
	mapping (address => Market) public marketAssets;

	/// @dev Collaterals: collateralAddress => collateralDetails
	mapping (address => Collateral) public collateralAssets;

	/// @dev Markets Debt after liquidation: collateralAddress => marketAddress => marketDebtBalance
	mapping (address => mapping (address => uint)) public marketDebt;

	/// @dev Users Supplies: userAddress => marketAddress => supplyDetails
	mapping (address => mapping (address => MarketAccount)) private supplies;

	/// @dev Users Borrows: userAddress => collateralAddress => marketAddress => borrowDetails
	mapping (address => mapping (address => mapping (address => MarketAccount))) private borrows;

	/// @dev Users Collaterals: userAddress => collateralAddress => collateralDetails
	mapping (address => mapping (address => CollateralAccount)) private collaterals;
	
	// ----------- Events -----------

	/// @notice Event emitted when a market asset is supplied
	event Supply(
		address sender,
		address indexed supplier,
		address indexed market,
		uint256 amount,
		uint256 balance,
		uint256 interest,
		uint256 index,
		uint16 referralCode
	);

	/// @notice Event emitted when a supply is withdrawn
	event WithdrawSupply(
		address sender,
		address indexed supplier,
		address indexed market,
		uint256 amount,
		uint256 balance,
		uint256 interest,
		uint256 index
	);

	/// @notice Event emitted when a collateral asset is deposited
	event Collateralize(
		address sender,
		address indexed collateralizer,
		address indexed collateral,
		uint256 amount,
		uint256 balance
	);

	/// @notice Event emitted when a collateral is withdrawn
	event WithdrawCollateral(
		address sender,
		address indexed collateralizer,
		address indexed collateral,
		uint256 amount,
		uint256 balance
	);

	/// @notice Event emitted when a market asset is borrowed
	event Borrow(
		address sender,
		address indexed borrower,
		address indexed market,
		address indexed collateral,
		uint256 amount,
		uint256 balance,
		uint256 interest,
		uint256 index,
		uint16 referralCode
	);

	/// @notice Event emitted when a borrow is repaid
	event RepayBorrow(
		address sender,
		address indexed borrower,
		address indexed market,
		address indexed collateral,
		uint256 amount,
		uint256 balance,
		uint256 interest,
		uint256 index
	);

	/// @notice Event emitted when the supply index is updated for a market asset
	event UpdateSupplyIndex(address indexed market, uint256 newSupplyIndex, uint256 supplyRate);

	/// @notice Event emitted when the borrow index is updated for a market asset
	event UpdateBorrowIndex(address indexed market, uint256 newBorrowIndex);

	/// @notice Event emitted when a collateral is liquidated
	event CollateralLiquidated(
		address indexed borrower,
		address indexed market,
		address indexed collateral,
		uint256 marketDebt,
		uint256 liquidatedCollateral
	);

	/// @notice Event emitted when a liquidated collateral is purchased in exchange for the specified market
	event BuyLiquidatedCollateral(
		address indexed market,
		address indexed collateral,
		uint256 marketAmount,
		uint256 collateralAmount
	);

	/// @notice Event emitted when HoldefiPrices contract is changed
	event HoldefiPricesContractChanged(address newAddress, address oldAddress);

	/// @notice Event emitted when a liquidation reserve is withdrawn by the owner
	event LiquidationReserveWithdrawn(address indexed collateral, uint256 amount);

	/// @notice Event emitted when a liquidation reserve is deposited
	event LiquidationReserveDeposited(address indexed collateral, uint256 amount);

	/// @notice Event emitted when a promotion reserve is withdrawn by the owner
	event PromotionReserveWithdrawn(address indexed market, uint256 amount);

	/// @notice Event emitted when a promotion reserve is deposited
	event PromotionReserveDeposited(address indexed market, uint256 amount);

	/// @notice Event emitted when a promotion reserve is updated
	event PromotionReserveUpdated(address indexed market, uint256 promotionReserve);

	/// @notice Event emitted when a promotion debt is updated
	event PromotionDebtUpdated(address indexed market, uint256 promotionDebt);

	/// @notice Initializes the Holdefi contract
    /// @param holdefiSettingsAddress Holdefi settings contract address
    /// @param holdefiPricesAddress Holdefi prices contract address
	constructor(
		HoldefiSettingsInterface holdefiSettingsAddress,
		HoldefiPricesInterface holdefiPricesAddress
	)
		public
	{
		holdefiSettings = holdefiSettingsAddress;
		holdefiPrices = holdefiPricesAddress;
		holdefiCollaterals = new HoldefiCollaterals();
	}


	/// @dev Modifier to check if the asset is ETH or not
	/// @param asset Address of the given asset
    modifier isNotETHAddress(address asset) {
        require (asset != ethAddress, "Asset should not be ETH address");
        _;
    }

	/// @dev Modifier to check if the market is active or not
	/// @param market Address of the given market
    modifier marketIsActive(address market) {
		require (holdefiSettings.marketAssets(market).isActive, "Market is not active");
        _;
    }

	/// @dev Modifier to check if the collateral is active or not
	/// @param collateral Address of the given collateral
    modifier collateralIsActive(address collateral) {
		require (holdefiSettings.collateralAssets(collateral).isActive, "Collateral is not active");
        _;
    }

	/// @dev Modifier to check if the account address is equal to the msg.sender or not
    /// @param account The given account address
    modifier accountIsValid(address account) {
		require (msg.sender != account, "Account is not valid");
        _;
    }

    receive() external payable {
        revert();
    }

	/// @notice Returns balance and interest of an account for a given market
    /// @dev supplyInterest = accumulatedInterest + (balance * (marketSupplyIndex - userLastSupplyInterestIndex))
    /// @param account Supplier address to get supply information
    /// @param market Address of the given market
    /// @return balance Supplied amount on the specified market
    /// @return interest Profit earned
    /// @return currentSupplyIndex Supply index for the given market at current time
	function getAccountSupply(address account, address market)
		public
		view
		returns (uint256 balance, uint256 interest, uint256 currentSupplyIndex)
	{
		balance = supplies[account][market].balance;

		(currentSupplyIndex,,) = getCurrentSupplyIndex(market);

		uint256 deltaInterestIndex = currentSupplyIndex.sub(supplies[account][market].lastInterestIndex);
		uint256 deltaInterestScaled = deltaInterestIndex.mul(balance);
		uint256 deltaInterest = deltaInterestScaled.div(secondsPerYear).div(rateDecimals);
		
		interest = supplies[account][market].accumulatedInterest.add(deltaInterest);
	}

	/// @notice Returns balance and interest of an account for a given market on a given collateral
    /// @dev borrowInterest = accumulatedInterest + (balance * (marketBorrowIndex - userLastBorrowInterestIndex))
    /// @param account Borrower address to get Borrow information
    /// @param market Address of the given market
    /// @param collateral Address of the given collateral
    /// @return balance Borrowed amount on the specified market
    /// @return interest The amount of interest the borrower should pay
    /// @return currentBorrowIndex Borrow index for the given market at current time
	function getAccountBorrow(address account, address market, address collateral)
		public
		view
		returns (uint256 balance, uint256 interest, uint256 currentBorrowIndex)
	{
		balance = borrows[account][collateral][market].balance;

		(currentBorrowIndex,,) = getCurrentBorrowIndex(market);

		uint256 deltaInterestIndex =
			currentBorrowIndex.sub(borrows[account][collateral][market].lastInterestIndex);

		uint256 deltaInterestScaled = deltaInterestIndex.mul(balance);
		uint256 deltaInterest = deltaInterestScaled.div(secondsPerYear).div(rateDecimals);
		if (balance > 0) {
			deltaInterest = deltaInterest.add(oneUnit);
		}

		interest = borrows[account][collateral][market].accumulatedInterest.add(deltaInterest);
	}


	/// @notice Returns collateral balance, time since last activity, borrow power, total borrow value, and liquidation status for a given collateral
    /// @dev borrowPower = (collateralValue / collateralValueToLoanRate) - totalBorrowValue
    /// @dev liquidationThreshold = collateralValueToLoanRate - 5%
    /// @dev User will be in liquidation state if (collateralValue / totalBorrowValue) < liquidationThreshold
    /// @param account Account address to get collateral information
    /// @param collateral Address of the given collateral
    /// @return balance Amount of the specified collateral
    /// @return timeSinceLastActivity Time since last activity performed by the account
    /// @return borrowPowerValue The borrowing power for the account of the given collateral
    /// @return totalBorrowValue Accumulative borrowed values on the given collateral
    /// @return underCollateral A boolean value indicates whether the user is in the liquidation state or not
	function getAccountCollateral(address account, address collateral)
		public
		view
		returns (
			uint256 balance,
			uint256 timeSinceLastActivity,
			uint256 borrowPowerValue,
			uint256 totalBorrowValue,
			bool underCollateral
		)
	{
		uint256 valueToLoanRate = holdefiSettings.collateralAssets(collateral).valueToLoanRate;
		if (valueToLoanRate == 0) {
			return (0, 0, 0, 0, false);
		}

		balance = collaterals[account][collateral].balance;

		uint256 collateralValue = holdefiPrices.getAssetValueFromAmount(collateral, balance);
		uint256 liquidationThresholdRate = valueToLoanRate.sub(fivePercentLiquidationGap);

		uint256 totalBorrowPowerValue = collateralValue.mul(rateDecimals).div(valueToLoanRate);
		uint256 liquidationThresholdValue = collateralValue.mul(rateDecimals).div(liquidationThresholdRate);

		totalBorrowValue = getAccountTotalBorrowValue(account, collateral);
		if (totalBorrowValue > 0) {
			timeSinceLastActivity = block.timestamp.sub(collaterals[account][collateral].lastUpdateTime);
		}

		borrowPowerValue = 0;
		if (totalBorrowValue < totalBorrowPowerValue) {
			borrowPowerValue = totalBorrowPowerValue.sub(totalBorrowValue);
		}

		underCollateral = false;	
		if (totalBorrowValue > liquidationThresholdValue) {
			underCollateral = true;
		}
	}

	/// @notice Returns maximum amount spender can withdraw from account supplies on a given market
	/// @param account Supplier address
	/// @param spender Spender address
	/// @param market Address of the given market
	/// @return res Maximum amount spender can withdraw from account supplies on a given market
	function getAccountWithdrawSupplyAllowance (address account, address spender, address market)
		external 
		view
		returns (uint256 res)
	{
		res = supplies[account][market].allowance[spender];
	}

	/// @notice Returns maximum amount spender can withdraw from account balance on a given collateral
	/// @param account Account address
	/// @param spender Spender address
	/// @param collateral Address of the given collateral
	/// @return res Maximum amount spender can withdraw from account balance on a given collateral
	function getAccountWithdrawCollateralAllowance (
		address account, 
		address spender, 
		address collateral
	)
		external 
		view
		returns (uint256 res)
	{
		res = collaterals[account][collateral].allowance[spender];
	}

	/// @notice Returns maximum amount spender can withdraw from account borrows on a given market based on a given collteral
	/// @param account Borrower address
	/// @param spender Spender address
	/// @param market Address of the given market
	/// @param collateral Address of the given collateral
	/// @return res Maximum amount spender can withdraw from account borrows on a given market based on a given collteral
	function getAccountBorrowAllowance (
		address account, 
		address spender, 
		address market, 
		address collateral
	)
		external 
		view
		returns (uint256 res)
	{
		res = borrows[account][collateral][market].allowance[spender];
	}

	/// @notice Returns total borrow value of an account based on a given collateral 
	/// @param account Account address
    /// @param collateral Address of the given collateral
    /// @return totalBorrowValue Accumulative borrowed values on the given collateral
	function getAccountTotalBorrowValue (address account, address collateral)
		public
		view
		returns (uint256 totalBorrowValue)
	{
		MarketData memory borrowData;
		address market;
		uint256 totalDebt;
		uint256 assetValue;
		
		totalBorrowValue = 0;
		address[] memory marketsList = holdefiSettings.getMarketsList();
		for (uint256 i = 0 ; i < marketsList.length ; i++) {
			market = marketsList[i];
			
			(borrowData.balance, borrowData.interest,) = getAccountBorrow(account, market, collateral);
			totalDebt = borrowData.balance.add(borrowData.interest);

			assetValue = holdefiPrices.getAssetValueFromAmount(market, totalDebt);
			totalBorrowValue = totalBorrowValue.add(assetValue);
		}
	}

	/// @notice The collateral reserve amount for buying liquidated collateral
    /// @param collateral Address of the given collateral
    /// @return reserve Liquidation reserves for the given collateral
	function getLiquidationReserve (address collateral) public view returns(uint256 reserve) {
		address market;
		uint256 assetValue;
		uint256 totalDebtValue = 0;

		address[] memory marketsList = holdefiSettings.getMarketsList();
		for (uint256 i = 0 ; i < marketsList.length ; i++) {
			market = marketsList[i];
			assetValue = holdefiPrices.getAssetValueFromAmount(market, marketDebt[collateral][market]);
			totalDebtValue = totalDebtValue.add(assetValue); 
		}

		uint256 bonusRate = holdefiSettings.collateralAssets(collateral).bonusRate;
		uint256 totalDebtCollateralValue = totalDebtValue.mul(bonusRate).div(rateDecimals);
		uint256 liquidatedCollateralNeeded = holdefiPrices.getAssetAmountFromValue(
			collateral,
			totalDebtCollateralValue
		);
		
		reserve = 0;
		uint256 totalLiquidatedCollateral = collateralAssets[collateral].totalLiquidatedCollateral;
		if (totalLiquidatedCollateral > liquidatedCollateralNeeded) {
			reserve = totalLiquidatedCollateral.sub(liquidatedCollateralNeeded);
		}
	}

	/// @notice Returns the amount of discounted collateral can be bought in exchange for the amount of a given market
    /// @param market Address of the given market
    /// @param collateral Address of the given collateral
    /// @param marketAmount The amount of market should be paid
    /// @return collateralAmountWithDiscount Amount of discounted collateral can be bought
	function getDiscountedCollateralAmount (address market, address collateral, uint256 marketAmount)
		public
		view
		returns (uint256 collateralAmountWithDiscount)
	{
		uint256 marketValue = holdefiPrices.getAssetValueFromAmount(market, marketAmount);
		uint256 bonusRate = holdefiSettings.collateralAssets(collateral).bonusRate;
		uint256 collateralValue = marketValue.mul(bonusRate).div(rateDecimals);

		collateralAmountWithDiscount = holdefiPrices.getAssetAmountFromValue(collateral, collateralValue);
	}

	/// @notice Returns supply index and supply rate for a given market at current time
	/// @dev newSupplyIndex = oldSupplyIndex + (deltaTime * supplyRate)
    /// @param market Address of the given market
    /// @return supplyIndex Supply index of the given market
    /// @return supplyRate Supply rate of the given market
    /// @return currentTime Current block timestamp
	function getCurrentSupplyIndex (address market)
		public
		view
		returns (
			uint256 supplyIndex,
			uint256 supplyRate,
			uint256 currentTime
		)
	{
		(, uint256 supplyRateBase, uint256 promotionRate) = holdefiSettings.getInterests(market);
		
		currentTime = block.timestamp;
		uint256 deltaTimeSupply = currentTime.sub(marketAssets[market].supplyIndexUpdateTime);

		supplyRate = supplyRateBase.add(promotionRate);
		uint256 deltaTimeInterest = deltaTimeSupply.mul(supplyRate);
		supplyIndex = marketAssets[market].supplyIndex.add(deltaTimeInterest);
	}

	/// @notice Returns borrow index and borrow rate for the given market at current time
	/// @dev newBorrowIndex = oldBorrowIndex + (deltaTime * borrowRate)
    /// @param market Address of the given market
    /// @return borrowIndex Borrow index of the given market
    /// @return borrowRate Borrow rate of the given market
    /// @return currentTime Current block timestamp
	function getCurrentBorrowIndex (address market)
		public
		view
		returns (
			uint256 borrowIndex,
			uint256 borrowRate,
			uint256 currentTime
		)
	{
		borrowRate = holdefiSettings.marketAssets(market).borrowRate;
		
		currentTime = block.timestamp;
		uint256 deltaTimeBorrow = currentTime.sub(marketAssets[market].borrowIndexUpdateTime);

		uint256 deltaTimeInterest = deltaTimeBorrow.mul(borrowRate);
		borrowIndex = marketAssets[market].borrowIndex.add(deltaTimeInterest);
	}

	/// @notice Returns promotion reserve for a given market at current time
	/// @dev promotionReserveScaled is scaled by (secondsPerYear * rateDecimals)
	/// @param market Address of the given market
    /// @return promotionReserveScaled Promotion reserve of the given market
    /// @return currentTime Current block timestamp
	function getPromotionReserve (address market)
		public
		view
		returns (uint256 promotionReserveScaled, uint256 currentTime)
	{
		(uint256 borrowRate, uint256 supplyRateBase,) = holdefiSettings.getInterests(market);
		currentTime = block.timestamp;
	
		uint256 allSupplyInterest = marketAssets[market].totalSupply.mul(supplyRateBase);
		uint256 allBorrowInterest = marketAssets[market].totalBorrow.mul(borrowRate);

		uint256 deltaTime = currentTime.sub(marketAssets[market].promotionReserveLastUpdateTime);
		uint256 currentInterest = allBorrowInterest.sub(allSupplyInterest);
		uint256 deltaTimeInterest = currentInterest.mul(deltaTime);
		promotionReserveScaled = marketAssets[market].promotionReserveScaled.add(deltaTimeInterest);
	}

	/// @notice Returns promotion debt for a given market at current time
	/// @dev promotionDebtScaled is scaled by secondsPerYear * rateDecimals
	/// @param market Address of the given market
    /// @return promotionDebtScaled Promotion debt of the given market
    /// @return currentTime Current block timestamp
	function getPromotionDebt (address market)
		public
		view
		returns (uint256 promotionDebtScaled, uint256 currentTime)
	{
		uint256 promotionRate = holdefiSettings.marketAssets(market).promotionRate;

		currentTime = block.timestamp;
		promotionDebtScaled = marketAssets[market].promotionDebtScaled;

		if (promotionRate != 0) {
			uint256 deltaTime = block.timestamp.sub(marketAssets[market].promotionDebtLastUpdateTime);
			uint256 currentInterest = marketAssets[market].totalSupply.mul(promotionRate);
			uint256 deltaTimeInterest = currentInterest.mul(deltaTime);
			promotionDebtScaled = promotionDebtScaled.add(deltaTimeInterest);
		}
	}

	/// @notice Update a market supply index, promotion reserve, and promotion debt
	/// @param market Address of the given market
	function beforeChangeSupplyRate (address market) public {
		updateSupplyIndex(market);
		updatePromotionReserve(market);
		updatePromotionDebt(market);
	}

	/// @notice Update a market borrow index, supply index, promotion reserve, and promotion debt 
	/// @param market Address of the given market
	function beforeChangeBorrowRate (address market) external {
		updateBorrowIndex(market);
		beforeChangeSupplyRate(market);
	}

	/// @notice Deposit ERC20 asset for supplying
	/// @param market Address of the given market
	/// @param amount The amount of asset supplier supplies
	/// @param referralCode A unique code used as an identifier of the referrer
	function supply(address market, uint256 amount, uint16 referralCode)
		external
		isNotETHAddress(market)
	{
		supplyInternal(msg.sender, market, amount, referralCode);
	}

	/// @notice Deposit ETH for supplying
	/// @notice msg.value The amount of asset supplier supplies
	/// @param referralCode A unique code used as an identifier of the referrer
	function supply(uint16 referralCode) external payable {		
		supplyInternal(msg.sender, ethAddress, msg.value, referralCode);
	}

	/// @notice Sender deposits ERC20 asset belonging to the supplier
	/// @param account Address of the supplier
	/// @param market Address of the given market
	/// @param amount The amount of asset supplier supplies
	/// @param referralCode A unique code used as an identifier of the referrer
	function supplyBehalf(address account, address market, uint256 amount, uint16 referralCode)
		external
		isNotETHAddress(market)
	{
		supplyInternal(account, market, amount, referralCode);
	}

	/// @notice Sender deposits ETH belonging to the supplier
	/// @notice msg.value The amount of ETH sender deposits belonging to the supplier
	/// @param account Address of the supplier
	/// @param referralCode A unique code used as an identifier of the referrer
	function supplyBehalf(address account, uint16 referralCode) 
		external
		payable
	{
		supplyInternal(account, ethAddress, msg.value, referralCode);
	}

	/// @notice Sender approves of the withdarawl for the account in the market asset
	/// @param account Address of the account allowed to withdraw
	/// @param market Address of the given market
	/// @param amount The amount is allowed to be withdrawn
	function approveWithdrawSupply(address account, address market, uint256 amount)
		external
		accountIsValid(account)
		marketIsActive(market)
	{
		supplies[msg.sender][market].allowance[account] = amount;
	}

	/// @notice Withdraw supply of a given market
	/// @param market Address of the given market
	/// @param amount The amount will be withdrawn from the market
	function withdrawSupply(address market, uint256 amount)
		external
	{
		withdrawSupplyInternal(msg.sender, market, amount);
	}

	/// @notice Sender withdraws supply belonging to the supplier
	/// @param account Address of the supplier
	/// @param market Address of the given market
	/// @param amount The amount will be withdrawn from the market
	function withdrawSupplyBehalf(address account, address market, uint256 amount) external {
		uint256 allowance = supplies[account][market].allowance[msg.sender];
		require(
			amount <= allowance, 
			"Withdraw not allowed"
		);
		supplies[account][market].allowance[msg.sender] = allowance.sub(amount);
		withdrawSupplyInternal(account, market, amount);
	}

	/// @notice Deposit ERC20 asset as collateral
	/// @param collateral Address of the given collateral
	/// @param amount The amount will be collateralized
	function collateralize (address collateral, uint256 amount)
		external
		isNotETHAddress(collateral)
	{
		collateralizeInternal(msg.sender, collateral, amount);
	}

	/// @notice Deposit ETH as collateral
	/// @notice msg.value The amount of ETH will be collateralized
	function collateralize () external payable {
		collateralizeInternal(msg.sender, ethAddress, msg.value);
	}

	/// @notice Sender deposits ERC20 asset as collateral belonging to the user
	/// @param account Address of the user
	/// @param collateral Address of the given collateral
	/// @param amount The amount will be collateralized
	function collateralizeBehalf (address account, address collateral, uint256 amount)
		external
		isNotETHAddress(collateral)
	{
		collateralizeInternal(account, collateral, amount);
	}

	/// @notice Sender deposits ETH as collateral belonging to the user
	/// @notice msg.value The amount of ETH Sender deposits as collateral belonging to the user
	/// @param account Address of the user
	function collateralizeBehalf (address account) external payable {
		collateralizeInternal(account, ethAddress, msg.value);
	}

	/// @notice Sender approves the account to withdraw the collateral
	/// @param account The address is allowed to withdraw the collateral
	/// @param collateral Address of the given collateral
	/// @param amount The amount is allowed to be withdrawn
	function approveWithdrawCollateral (address account, address collateral, uint256 amount)
		external
		accountIsValid(account)
		collateralIsActive(collateral)
	{
		collaterals[msg.sender][collateral].allowance[account] = amount;
	}

	/// @notice Withdraw a collateral
	/// @param collateral Address of the given collateral
	/// @param amount The amount will be withdrawn from the collateral
	function withdrawCollateral (address collateral, uint256 amount)
		external
	{
		withdrawCollateralInternal(msg.sender, collateral, amount);
	}

	/// @notice Sender withdraws a collateral belonging to the user
	/// @param account Address of the user
	/// @param collateral Address of the given collateral
	/// @param amount The amount will be withdrawn from the collateral
	function withdrawCollateralBehalf (address account, address collateral, uint256 amount)
		external
	{
		uint256 allowance = collaterals[account][collateral].allowance[msg.sender];
		require(
			amount <= allowance,
			"Withdraw not allowed"
		);
		collaterals[account][collateral].allowance[msg.sender] = allowance.sub(amount);
		withdrawCollateralInternal(account, collateral, amount);
	}

	/// @notice Sender approves the account to borrow a given market based on given collateral
	/// @param account The address allowed to borrow the given market
	/// @param market Address of the given market
	/// @param collateral Address of the given collateral
	/// @param amount The amount is allowed to be withdrawn
	function approveBorrow (address account, address market, address collateral, uint256 amount)
		external
		accountIsValid(account)
		marketIsActive(market)
	{
		borrows[msg.sender][collateral][market].allowance[account] = amount;
	}

	/// @notice Borrow an asset
	/// @param market Address of the given market
	/// @param collateral Address of the given collateral
	/// @param amount The amount of the given market will be borrowed
	/// @param referralCode A unique code used as an identifier of the referrer
	function borrow (address market, address collateral, uint256 amount, uint16 referralCode)
		external
	{
		borrowInternal(msg.sender, market, collateral, amount, referralCode);
	}

	/// @notice Sender borrows an asset belonging to the borrower
	/// @param account Address of the borrower
	/// @param market Address of the given market
	/// @param collateral Address of the given collateral
	/// @param amount The amount will be borrowed
	/// @param referralCode A unique code used as an identifier of the referrer
	function borrowBehalf (address account, address market, address collateral, uint256 amount, uint16 referralCode)
		external
	{
		uint256 allowance = borrows[account][collateral][market].allowance[msg.sender];
		require(
			amount <= allowance,
			"Withdraw not allowed"
		);
		borrows[account][collateral][market].allowance[msg.sender] = allowance.sub(amount);
		borrowInternal(account, market, collateral, amount, referralCode);
	}

	/// @notice Repay an ERC20 asset based on a given collateral
	/// @param market Address of the given market
	/// @param collateral Address of the given collateral
	/// @param amount The amount of the market will be Repaid
	function repayBorrow (address market, address collateral, uint256 amount)
		external
		isNotETHAddress(market)
	{
		repayBorrowInternal(msg.sender, market, collateral, amount);
	}

	/// @notice Repay an ETH based on a given collateral
	/// @notice msg.value The amount of ETH will be repaid
	/// @param collateral Address of the given collateral
	function repayBorrow (address collateral) external payable {		
		repayBorrowInternal(msg.sender, ethAddress, collateral, msg.value);
	}

	/// @notice Sender repays an ERC20 asset based on a given collateral belonging to the borrower
	/// @param account Address of the borrower
	/// @param market Address of the given market
	/// @param collateral Address of the given collateral
	/// @param amount The amount of the market will be repaid
	function repayBorrowBehalf (address account, address market, address collateral, uint256 amount)
		external
		isNotETHAddress(market)
	{
		repayBorrowInternal(account, market, collateral, amount);
	}

	/// @notice Sender repays an ETH based on a given collateral belonging to the borrower
	/// @notice msg.value The amount of ETH sender repays belonging to the borrower
	/// @param account Address of the borrower
	/// @param collateral Address of the given collateral
	function repayBorrowBehalf (address account, address collateral)
		external
		payable
	{		
		repayBorrowInternal(account, ethAddress, collateral, msg.value);
	}

	/// @notice Liquidate borrower's collateral
	/// @param borrower Address of the borrower who should be liquidated
	/// @param market Address of the given market
	/// @param collateral Address of the given collateral
	function liquidateBorrowerCollateral (address borrower, address market, address collateral)
		external
		whenNotPaused("liquidateBorrowerCollateral")
	{
		MarketData memory borrowData;
		(borrowData.balance, borrowData.interest,) = getAccountBorrow(borrower, market, collateral);
		require(borrowData.balance > 0, "User should have debt");

		(uint256 collateralBalance, uint256 timeSinceLastActivity,,, bool underCollateral) = 
			getAccountCollateral(borrower, collateral);
		require (underCollateral || (timeSinceLastActivity > secondsPerYear),
			"User should be under collateral or time is over"
		);

		uint256 totalBorrowedBalance = borrowData.balance.add(borrowData.interest);
		uint256 totalBorrowedBalanceValue = holdefiPrices.getAssetValueFromAmount(market, totalBorrowedBalance);
		
		uint256 liquidatedCollateralValue = totalBorrowedBalanceValue
		.mul(holdefiSettings.collateralAssets(collateral).penaltyRate)
		.div(rateDecimals);

		uint256 liquidatedCollateral =
			holdefiPrices.getAssetAmountFromValue(collateral, liquidatedCollateralValue);

		if (liquidatedCollateral > collateralBalance) {
			liquidatedCollateral = collateralBalance;
		}

		collaterals[borrower][collateral].balance = collateralBalance.sub(liquidatedCollateral);
		collateralAssets[collateral].totalCollateral =
			collateralAssets[collateral].totalCollateral.sub(liquidatedCollateral);
		collateralAssets[collateral].totalLiquidatedCollateral =
			collateralAssets[collateral].totalLiquidatedCollateral.add(liquidatedCollateral);

		delete borrows[borrower][collateral][market];
		beforeChangeSupplyRate(market);
		marketAssets[market].totalBorrow = marketAssets[market].totalBorrow.sub(borrowData.balance);
		marketDebt[collateral][market] = marketDebt[collateral][market].add(totalBorrowedBalance);

		emit CollateralLiquidated(borrower, market, collateral, totalBorrowedBalance, liquidatedCollateral);	
	}

	/// @notice Buy collateral in exchange for ERC20 asset
	/// @param market Address of the market asset should be paid to buy collateral
	/// @param collateral Address of the liquidated collateral
	/// @param marketAmount The amount of the given market will be paid
	function buyLiquidatedCollateral (address market, address collateral, uint256 marketAmount)
		external
		isNotETHAddress(market)
	{
		buyLiquidatedCollateralInternal(market, collateral, marketAmount);
	}

	/// @notice Buy collateral in exchange for ETH
	/// @notice msg.value The amount of the given market that will be paid
	/// @param collateral Address of the liquidated collateral
	function buyLiquidatedCollateral (address collateral) external payable {
		buyLiquidatedCollateralInternal(ethAddress, collateral, msg.value);
	}

	/// @notice Deposit ERC20 asset as liquidation reserve
	/// @param collateral Address of the given collateral
	/// @param amount The amount that will be deposited
	function depositLiquidationReserve(address collateral, uint256 amount)
		external
		isNotETHAddress(collateral)
	{
		depositLiquidationReserveInternal(collateral, amount);
	}

	/// @notice Deposit ETH asset as liquidation reserve
	/// @notice msg.value The amount of ETH that will be deposited
	function depositLiquidationReserve() external payable {
		depositLiquidationReserveInternal(ethAddress, msg.value);
	}

	/// @notice Withdraw liquidation reserve only by the owner
	/// @param collateral Address of the given collateral
	/// @param amount The amount that will be withdrawn
	function withdrawLiquidationReserve (address collateral, uint256 amount) external onlyOwner {
		uint256 maxWithdraw = getLiquidationReserve(collateral);
		uint256 transferAmount = amount;
		
		if (transferAmount > maxWithdraw){
			transferAmount = maxWithdraw;
		}

		collateralAssets[collateral].totalLiquidatedCollateral =
			collateralAssets[collateral].totalLiquidatedCollateral.sub(transferAmount);
		holdefiCollaterals.withdraw(collateral, msg.sender, transferAmount);

		emit LiquidationReserveWithdrawn(collateral, amount);
	}

	/// @notice Deposit ERC20 asset as promotion reserve
	/// @param market Address of the given market
	/// @param amount The amount that will be deposited
	function depositPromotionReserve (address market, uint256 amount)
		external
		isNotETHAddress(market)
	{
		depositPromotionReserveInternal(market, amount);
	}

	/// @notice Deposit ETH as promotion reserve
	/// @notice msg.value The amount of ETH that will be deposited
	function depositPromotionReserve () external payable {
		depositPromotionReserveInternal(ethAddress, msg.value);
	}

	/// @notice Withdraw promotion reserve only by the owner
	/// @param market Address of the given market
	/// @param amount The amount that will be withdrawn
	function withdrawPromotionReserve (address market, uint256 amount) external onlyOwner {
	    (uint256 reserveScaled,) = getPromotionReserve(market);
	    (uint256 debtScaled,) = getPromotionDebt(market);

	    uint256 amountScaled = amount.mul(secondsPerYear).mul(rateDecimals);
	    uint256 increasedDebtScaled = amountScaled.add(debtScaled);
	    require (reserveScaled > increasedDebtScaled, "Amount should be less than max");

	    marketAssets[market].promotionReserveScaled = reserveScaled.sub(amountScaled);

	    transferFromHoldefi(msg.sender, market, amount);

	    emit PromotionReserveWithdrawn(market, amount);
	 }


	/// @notice Set Holdefi prices contract only by the owner
	/// @param newHoldefiPrices Address of the new Holdefi prices contract
	function setHoldefiPricesContract (HoldefiPricesInterface newHoldefiPrices) external onlyOwner {
		emit HoldefiPricesContractChanged(address(newHoldefiPrices), address(holdefiPrices));
		holdefiPrices = newHoldefiPrices;
	}

	/// @notice Promotion reserve and debt settlement
	/// @param market Address of the given market
	function reserveSettlement (address market) external {
		require(msg.sender == address(holdefiSettings), "Sender should be Holdefi Settings contract");

		uint256 promotionReserve = marketAssets[market].promotionReserveScaled;
		uint256 promotionDebt = marketAssets[market].promotionDebtScaled;
		require(promotionReserve > promotionDebt, "Not enough promotion reserve");
		
		promotionReserve = promotionReserve.sub(promotionDebt);
		marketAssets[market].promotionReserveScaled = promotionReserve;
		marketAssets[market].promotionDebtScaled = 0;

		marketAssets[market].promotionReserveLastUpdateTime = block.timestamp;
		marketAssets[market].promotionDebtLastUpdateTime = block.timestamp;

		emit PromotionReserveUpdated(market, promotionReserve);
		emit PromotionDebtUpdated(market, 0);
	}

	/// @notice Update supply index of a market
	/// @param market Address of the given market
	function updateSupplyIndex (address market) internal {
		(uint256 currentSupplyIndex, uint256 supplyRate, uint256 currentTime) =
			getCurrentSupplyIndex(market);

		marketAssets[market].supplyIndex = currentSupplyIndex;
		marketAssets[market].supplyIndexUpdateTime = currentTime;

		emit UpdateSupplyIndex(market, currentSupplyIndex, supplyRate);
	}

	/// @notice Update borrow index of a market
	/// @param market Address of the given market
	function updateBorrowIndex (address market) internal {
		(uint256 currentBorrowIndex,, uint256 currentTime) = getCurrentBorrowIndex(market);

		marketAssets[market].borrowIndex = currentBorrowIndex;
		marketAssets[market].borrowIndexUpdateTime = currentTime;

		emit UpdateBorrowIndex(market, currentBorrowIndex);
	}

	/// @notice Update promotion reserve of a market
	/// @param market Address of the given market
	function updatePromotionReserve(address market) internal {
		(uint256 reserveScaled,) = getPromotionReserve(market);

		marketAssets[market].promotionReserveScaled = reserveScaled;
		marketAssets[market].promotionReserveLastUpdateTime = block.timestamp;

		emit PromotionReserveUpdated(market, reserveScaled);
	}

	/// @notice Update promotion debt of a market
	/// @dev Promotion rate will be set to 0 if (promotionDebt >= promotionReserve)
	/// @param market Address of the given market
	function updatePromotionDebt(address market) internal {
    	(uint256 debtScaled,) = getPromotionDebt(market);
    	if (marketAssets[market].promotionDebtScaled != debtScaled){
      		marketAssets[market].promotionDebtScaled = debtScaled;
      		marketAssets[market].promotionDebtLastUpdateTime = block.timestamp;

      		emit PromotionDebtUpdated(market, debtScaled);
    	}
    	if (marketAssets[market].promotionReserveScaled <= debtScaled) {
      		holdefiSettings.resetPromotionRate(market);
    	}
  	}

	/// @notice transfer ETH or ERC20 asset from this contract
	function transferFromHoldefi(address receiver, address asset, uint256 amount) internal {
		bool success = false;
		if (asset == ethAddress){
			(success, ) = receiver.call{value:amount}("");
		}
		else {
			IERC20 token = IERC20(asset);
			success = token.transfer(receiver, amount);
		}
		require (success, "Cannot Transfer");
	}
	/// @notice transfer ERC20 asset to this contract
	function transferToHoldefi(address receiver, address asset, uint256 amount) internal {
		IERC20 token = IERC20(asset);
		bool success = token.transferFrom(msg.sender, receiver, amount);
		require (success, "Cannot Transfer");
	}

	/// @notice Perform supply operation
	function supplyInternal(address account, address market, uint256 amount, uint16 referralCode)
		internal
		whenNotPaused("supply")
		marketIsActive(market)
	{
		if (market != ethAddress) {
			transferToHoldefi(address(this), market, amount);
		}

		MarketData memory supplyData;
		(supplyData.balance, supplyData.interest, supplyData.currentIndex) = getAccountSupply(account, market);
		
		supplyData.balance = supplyData.balance.add(amount);
		supplies[account][market].balance = supplyData.balance;
		supplies[account][market].accumulatedInterest = supplyData.interest;
		supplies[account][market].lastInterestIndex = supplyData.currentIndex;

		beforeChangeSupplyRate(market);
		
		marketAssets[market].totalSupply = marketAssets[market].totalSupply.add(amount);

		emit Supply(
			msg.sender,
			account,
			market,
			amount,
			supplyData.balance,
			supplyData.interest,
			supplyData.currentIndex,
			referralCode
		);
	}

	/// @notice Perform withdraw supply operation
	function withdrawSupplyInternal (address account, address market, uint256 amount) 
		internal
		whenNotPaused("withdrawSupply")
	{
		MarketData memory supplyData;
		(supplyData.balance, supplyData.interest, supplyData.currentIndex) = getAccountSupply(account, market);
		uint256 totalSuppliedBalance = supplyData.balance.add(supplyData.interest);
		require (totalSuppliedBalance != 0, "Total balance should not be zero");

		uint256 transferAmount = amount;
		if (transferAmount > totalSuppliedBalance){
			transferAmount = totalSuppliedBalance;
		}

		uint256 remaining = 0;
		if (transferAmount <= supplyData.interest) {
			supplyData.interest = supplyData.interest.sub(transferAmount);
		}
		else {
			remaining = transferAmount.sub(supplyData.interest);
			supplyData.interest = 0;
			supplyData.balance = supplyData.balance.sub(remaining);
		}

		supplies[account][market].balance = supplyData.balance;
		supplies[account][market].accumulatedInterest = supplyData.interest;
		supplies[account][market].lastInterestIndex = supplyData.currentIndex;

		beforeChangeSupplyRate(market);
		
		marketAssets[market].totalSupply = marketAssets[market].totalSupply.sub(remaining);	
		
		transferFromHoldefi(msg.sender, market, transferAmount);
	
		emit WithdrawSupply(
			msg.sender,
			account,
			market,
			transferAmount,
			supplyData.balance,
			supplyData.interest,
			supplyData.currentIndex
		);
	}

	/// @notice Perform collateralize operation
	function collateralizeInternal (address account, address collateral, uint256 amount)
		internal
		whenNotPaused("collateralize")
		collateralIsActive(collateral)
	{
		if (collateral != ethAddress) {
			transferToHoldefi(address(holdefiCollaterals), collateral, amount);
		}
		else {
			transferFromHoldefi(address(holdefiCollaterals), collateral, amount);
		}

		uint256 balance = collaterals[account][collateral].balance.add(amount);
		collaterals[account][collateral].balance = balance;
		collaterals[account][collateral].lastUpdateTime = block.timestamp;

		collateralAssets[collateral].totalCollateral = collateralAssets[collateral].totalCollateral.add(amount);	
		
		emit Collateralize(msg.sender, account, collateral, amount, balance);
	}

	/// @notice Perform withdraw collateral operation
	function withdrawCollateralInternal (address account, address collateral, uint256 amount) 
		internal
		whenNotPaused("withdrawCollateral")
	{
		(uint256 balance,, uint256 borrowPowerValue, uint256 totalBorrowValue,) =
			getAccountCollateral(account, collateral);

		require (borrowPowerValue != 0, "Borrow power should not be zero");

		uint256 collateralNedeed = 0;
		if (totalBorrowValue != 0) {
			uint256 valueToLoanRate = holdefiSettings.collateralAssets(collateral).valueToLoanRate;
			uint256 totalCollateralValue = totalBorrowValue.mul(valueToLoanRate).div(rateDecimals);
			collateralNedeed = holdefiPrices.getAssetAmountFromValue(collateral, totalCollateralValue);
		}

		uint256 maxWithdraw = balance.sub(collateralNedeed);
		uint256 transferAmount = amount;
		if (transferAmount > maxWithdraw){
			transferAmount = maxWithdraw;
		}
		balance = balance.sub(transferAmount);
		collaterals[account][collateral].balance = balance;
		collaterals[account][collateral].lastUpdateTime = block.timestamp;

		collateralAssets[collateral].totalCollateral =
			collateralAssets[collateral].totalCollateral.sub(transferAmount);

		holdefiCollaterals.withdraw(collateral, msg.sender, transferAmount);

		emit WithdrawCollateral(msg.sender, account, collateral, transferAmount, balance);
	}

	/// @notice Perform borrow operation
	function borrowInternal (address account, address market, address collateral, uint256 amount, uint16 referralCode)
		internal
		whenNotPaused("borrow")
		marketIsActive(market)
		collateralIsActive(collateral)
	{
		require (
			amount <= (marketAssets[market].totalSupply.sub(marketAssets[market].totalBorrow)),
			"Amount should be less than cash"
		);

		(,, uint256 borrowPowerValue,,) = getAccountCollateral(account, collateral);
		uint256 assetToBorrowValue = holdefiPrices.getAssetValueFromAmount(market, amount);
		require (
			borrowPowerValue >= assetToBorrowValue,
			"Borrow power should be more than new borrow value"
		);

		MarketData memory borrowData;
		(borrowData.balance, borrowData.interest, borrowData.currentIndex) = getAccountBorrow(account, market, collateral);
		
		borrowData.balance = borrowData.balance.add(amount);
		borrows[account][collateral][market].balance = borrowData.balance;
		borrows[account][collateral][market].accumulatedInterest = borrowData.interest;
		borrows[account][collateral][market].lastInterestIndex = borrowData.currentIndex;
		collaterals[account][collateral].lastUpdateTime = block.timestamp;

		beforeChangeSupplyRate(market);

		marketAssets[market].totalBorrow = marketAssets[market].totalBorrow.add(amount);

		transferFromHoldefi(msg.sender, market, amount);

		emit Borrow(
			msg.sender, 
			account,
			market,
			collateral,
			amount,
			borrowData.balance,
			borrowData.interest,
			borrowData.currentIndex,
			referralCode
		);
	}

	/// @notice Perform repay borrow operation
	function repayBorrowInternal (address account, address market, address collateral, uint256 amount)
		internal
		whenNotPaused("repayBorrow")
	{
		MarketData memory borrowData;
		(borrowData.balance, borrowData.interest, borrowData.currentIndex) =
			getAccountBorrow(account, market, collateral);

		uint256 totalBorrowedBalance = borrowData.balance.add(borrowData.interest);
		require (totalBorrowedBalance != 0, "Total balance should not be zero");

		uint256 transferAmount = amount;
		if (transferAmount > totalBorrowedBalance) {
			transferAmount = totalBorrowedBalance;
			if (market == ethAddress) {
				uint256 extra = amount.sub(transferAmount);
				transferFromHoldefi(msg.sender, ethAddress, extra);
			}
		}
		
		if (market != ethAddress) {
			transferToHoldefi(address(this), market, transferAmount);
		}

		uint256 remaining = 0;
		if (transferAmount <= borrowData.interest) {
			borrowData.interest = borrowData.interest.sub(transferAmount);
		}
		else {
			remaining = transferAmount.sub(borrowData.interest);
			borrowData.interest = 0;
			borrowData.balance = borrowData.balance.sub(remaining);
		}
		borrows[account][collateral][market].balance = borrowData.balance;
		borrows[account][collateral][market].accumulatedInterest = borrowData.interest;
		borrows[account][collateral][market].lastInterestIndex = borrowData.currentIndex;
		collaterals[account][collateral].lastUpdateTime = block.timestamp;

		beforeChangeSupplyRate(market);
		
		marketAssets[market].totalBorrow = marketAssets[market].totalBorrow.sub(remaining);	

		emit RepayBorrow (
			msg.sender,
			account,
			market,
			collateral,
			transferAmount,
			borrowData.balance,
			borrowData.interest,
			borrowData.currentIndex
		);
	}

	/// @notice Perform buy liquidated collateral operation
	function buyLiquidatedCollateralInternal (address market, address collateral, uint256 marketAmount)
		internal
		whenNotPaused("buyLiquidatedCollateral")
	{
		uint256 debt = marketDebt[collateral][market];
		require (marketAmount <= debt,
			"Amount should be less than total liquidated assets"
		);

		uint256 collateralAmountWithDiscount =
			getDiscountedCollateralAmount(market, collateral, marketAmount);

		uint256 totalLiquidatedCollateral = collateralAssets[collateral].totalLiquidatedCollateral;
		require (
			collateralAmountWithDiscount <= totalLiquidatedCollateral,
			"Collateral amount with discount should be less than total liquidated assets"
		);

		if (market != ethAddress) {
			transferToHoldefi(address(this), market, marketAmount);
		}

		collateralAssets[collateral].totalLiquidatedCollateral = totalLiquidatedCollateral.sub(collateralAmountWithDiscount);
		marketDebt[collateral][market] = debt.sub(marketAmount);

		holdefiCollaterals.withdraw(collateral, msg.sender, collateralAmountWithDiscount);

		emit BuyLiquidatedCollateral(market, collateral, marketAmount, collateralAmountWithDiscount);
	}

	/// @notice Perform deposit promotion reserve operation
	function depositPromotionReserveInternal (address market, uint256 amount)
		internal
		marketIsActive(market)
	{
		if (market != ethAddress) {
			transferToHoldefi(address(this), market, amount);
		}
		uint256 amountScaled = amount.mul(secondsPerYear).mul(rateDecimals);

		marketAssets[market].promotionReserveScaled = 
			marketAssets[market].promotionReserveScaled.add(amountScaled);

		emit PromotionReserveDeposited(market, amount);
	}

	/// @notice Perform deposit liquidation reserve operation
	function depositLiquidationReserveInternal (address collateral, uint256 amount)
		internal
		collateralIsActive(ethAddress)
	{
		if (collateral != ethAddress) {
			transferToHoldefi(address(holdefiCollaterals), collateral, amount);
		}
		else {
			transferFromHoldefi(address(holdefiCollaterals), collateral, amount);
		}
		collateralAssets[ethAddress].totalLiquidatedCollateral =
			collateralAssets[ethAddress].totalLiquidatedCollateral.add(msg.value);
		
		emit LiquidationReserveDeposited(ethAddress, msg.value);
	}
}

File 2 of 6: HoldefiCollaterals.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.6.12;

import "./IERC20.sol";


/// @title HoldefiCollaterals
/// @author Holdefi Team
/// @notice Collaterals is held by this contract
/// @dev The address of ETH asset considered as 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
contract HoldefiCollaterals {

	address constant public ethAddress = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;

	address public holdefiContract;

	/// @dev Initializes the main Holdefi contract address
	constructor() public {
		holdefiContract = msg.sender;
	}

	/// @notice Modifier to check that only Holdefi contract interacts with the function
    modifier onlyHoldefiContract() {
        require (msg.sender == holdefiContract, "Sender should be holdefi contract");
        _;
    }

	/// @notice Only Holdefi contract can send ETH to this contract
    receive() external payable onlyHoldefiContract {
	}

	/// @notice Holdefi contract withdraws collateral from this contract to recipient account
	/// @param collateral Address of the given collateral
	/// @param recipient Address of the recipient
	/// @param amount Amount to be withdrawn
	function withdraw (address collateral, address recipient, uint256 amount)
		external
		onlyHoldefiContract
	{
		bool success = false;
		if (collateral == ethAddress){
			(success, ) = recipient.call{value:amount}("");
		}
		else {
			IERC20 token = IERC20(collateral);
			success = token.transfer(recipient, amount);
		}
		require (success, "Cannot Transfer");
	}

}

File 3 of 6: HoldefiOwnable.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.6.12;

/// @title HoldefiOwnable
/// @author Holdefi Team
/// @notice Taking ideas from Open Zeppelin's Ownable contract
/// @dev Contract module which provides a basic access control mechanism, where
/// there is an account (an owner) that can be granted exclusive access to
/// specific functions.
///
/// By default, the owner account will be the one that deploys the contract. This
/// can later be changed with {transferOwnership}.
///
/// This module is used through inheritance. It will make available the modifier
/// `onlyOwner`, which can be applied to your functions to restrict their use to
/// the owner.
contract HoldefiOwnable {
    address public owner;
    address public pendingOwner;

    /// @notice Event emitted when an ownership transfer request is recieved
    event OwnershipTransferRequested(address newPendingOwner);

    /// @notice Event emitted when an ownership transfer request is accepted by the pending owner
    event OwnershipTransferred(address newOwner, address oldOwner);

    /// @notice Initializes the contract owner
    constructor () public {
        owner = msg.sender;
        emit OwnershipTransferred(owner, address(0));
    }

    /// @notice Throws if called by any account other than the owner
    modifier onlyOwner() {
        require(msg.sender == owner, "Sender should be owner");
        _;
    }

    /// @notice Transfers ownership of the contract to a new owner
    /// @dev Can only be called by the current owner
    /// @param newOwner Address of new owner
    function transferOwnership(address newOwner) external onlyOwner {
        require(newOwner != address(0), "New owner can not be zero address");
        pendingOwner = newOwner;

        emit OwnershipTransferRequested(newOwner);
    }

    /// @notice Pending owner accepts ownership of the contract
    /// @dev Only Pending owner can call this function
    function acceptTransferOwnership () external {
        require (pendingOwner != address(0), "Pending owner is empty");
        require (pendingOwner == msg.sender, "Pending owner is not same as sender");
        
        emit OwnershipTransferred(pendingOwner, owner);
        owner = pendingOwner;
        pendingOwner = address(0);
    }
}

File 4 of 6: HoldefiPausableOwnable.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;

import "./HoldefiOwnable.sol";

/// @title HoldefiPausableOwnable
/// @author Holdefi Team
/// @notice Taking ideas from Open Zeppelin's Pausable contract
/// @dev Base contract which allows children to implement an emergency stop mechanism.
contract HoldefiPausableOwnable is HoldefiOwnable {

    uint256 constant public maxPauseDuration = 2592000;     //seconds per month

    struct Operation {
        bool isValid;
        uint256 pauseEndTime;
    }

    /// @notice Pauser can pause operations but can't unpause them
    address public pauser;

    mapping(string => Operation) public paused;

    /// @notice Event emitted when the pauser is changed by the owner
    event PauserChanged(address newPauser, address oldPauser);

    /// @notice Event emitted when an operation is paused by the pauser
    event OperationPaused(string operation, uint256 pauseDuration);

    /// @notice Event emitted when an operation is unpaused by the owner
    event OperationUnpaused(string operation);
    
    /// @notice Define valid operations that can be paused
    constructor () public {
        paused["supply"].isValid = true;
        paused["withdrawSupply"].isValid = true;
        paused["collateralize"].isValid = true;
        paused["withdrawCollateral"].isValid = true;
        paused["borrow"].isValid = true;
        paused["repayBorrow"].isValid = true;
        paused["liquidateBorrowerCollateral"].isValid = true;
        paused["buyLiquidatedCollateral"].isValid = true;
    }

    /// @dev Modifier to make a function callable only by owner or pauser
    modifier onlyPausers() {
        require(msg.sender == owner || msg.sender == pauser , "Sender should be owner or pauser");
        _;
    }
    
    /// @dev Modifier to make a function callable only when an operation is not paused
    /// @param operation Name of the operation
    modifier whenNotPaused(string memory operation) {
        require(!isPaused(operation), "Operation is paused");
        _;
    }

    /// @dev Modifier to make a function callable only when an operation is paused
    /// @param operation Name of the operation
    modifier whenPaused(string memory operation) {
        require(isPaused(operation), "Operation is unpaused");
        _;
    }

    /// @dev Modifier to make a function callable only when an operation is valid
    /// @param operation Name of the operation
    modifier operationIsValid(string memory operation) {
        require(paused[operation].isValid ,"Operation is not valid");
        _;
    }

    /// @notice Returns the pause status of a given operation
    /// @param operation Name of the operation
    /// @return res Pause status of a given operation
    function isPaused(string memory operation) public view returns (bool res) {
        if (block.timestamp > paused[operation].pauseEndTime) {
            res = false;
        }
        else {
            res = true;
        }
    }

    /// @notice Called by pausers to pause an operation, triggers stopped state
    /// @param operation Name of the operation
    /// @param pauseDuration The length of time the operation must be paused
    function pause(string memory operation, uint256 pauseDuration)
        public
        onlyPausers
        operationIsValid(operation)
        whenNotPaused(operation)
    {
        require (pauseDuration <= maxPauseDuration, "Duration not in range");
        paused[operation].pauseEndTime = block.timestamp + pauseDuration;
        emit OperationPaused(operation, pauseDuration);
    }

    /// @notice Called by owner to unpause an operation, returns to normal state
    /// @param operation Name of the operation
    function unpause(string memory operation)
        public
        onlyOwner
        operationIsValid(operation)
        whenPaused(operation)
    {
        paused[operation].pauseEndTime = 0;
        emit OperationUnpaused(operation);
    }

    /// @notice Called by pausers to pause operations, triggers stopped state for selected operations
    /// @param operations List of operation names
    /// @param pauseDurations List of durations specifying the pause time of each operation
    function batchPause(string[] memory operations, uint256[] memory pauseDurations) external {
        require (operations.length == pauseDurations.length, "Lists are not equal in length");
        for (uint256 i = 0 ; i < operations.length ; i++) {
            pause(operations[i], pauseDurations[i]);
        }
    }

    /// @notice Called by pausers to pause operations, returns to normal state for selected operations
    /// @param operations List of operation names
    function batchUnpause(string[] memory operations) external {
        for (uint256 i = 0 ; i < operations.length ; i++) {
            unpause(operations[i]);
        }
    }

    /// @notice Called by owner to set a new pauser
    /// @param newPauser Address of new pauser
    function setPauser(address newPauser) external onlyOwner {
        emit PauserChanged(newPauser, pauser);
        pauser = newPauser;
        
    }

}

File 5 of 6: IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

File 6 of 6: SafeMath.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.12;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @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) {
        // 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 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts 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) {
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts 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 mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message 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, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

Contract ABI

[{"inputs":[{"internalType":"contract HoldefiSettingsInterface","name":"holdefiSettingsAddress","type":"address"},{"internalType":"contract HoldefiPricesInterface","name":"holdefiPricesAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"borrower","type":"address"},{"indexed":true,"internalType":"address","name":"market","type":"address"},{"indexed":true,"internalType":"address","name":"collateral","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"balance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"interest","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"uint16","name":"referralCode","type":"uint16"}],"name":"Borrow","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"market","type":"address"},{"indexed":true,"internalType":"address","name":"collateral","type":"address"},{"indexed":false,"internalType":"uint256","name":"marketAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralAmount","type":"uint256"}],"name":"BuyLiquidatedCollateral","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"borrower","type":"address"},{"indexed":true,"internalType":"address","name":"market","type":"address"},{"indexed":true,"internalType":"address","name":"collateral","type":"address"},{"indexed":false,"internalType":"uint256","name":"marketDebt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"liquidatedCollateral","type":"uint256"}],"name":"CollateralLiquidated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"collateralizer","type":"address"},{"indexed":true,"internalType":"address","name":"collateral","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"balance","type":"uint256"}],"name":"Collateralize","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newAddress","type":"address"},{"indexed":false,"internalType":"address","name":"oldAddress","type":"address"}],"name":"HoldefiPricesContractChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"collateral","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LiquidationReserveDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"collateral","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LiquidationReserveWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"operation","type":"string"},{"indexed":false,"internalType":"uint256","name":"pauseDuration","type":"uint256"}],"name":"OperationPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"operation","type":"string"}],"name":"OperationUnpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newPendingOwner","type":"address"}],"name":"OwnershipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOwner","type":"address"},{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newPauser","type":"address"},{"indexed":false,"internalType":"address","name":"oldPauser","type":"address"}],"name":"PauserChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"market","type":"address"},{"indexed":false,"internalType":"uint256","name":"promotionDebt","type":"uint256"}],"name":"PromotionDebtUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"market","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PromotionReserveDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"market","type":"address"},{"indexed":false,"internalType":"uint256","name":"promotionReserve","type":"uint256"}],"name":"PromotionReserveUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"market","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PromotionReserveWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"borrower","type":"address"},{"indexed":true,"internalType":"address","name":"market","type":"address"},{"indexed":true,"internalType":"address","name":"collateral","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"balance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"interest","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"}],"name":"RepayBorrow","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"supplier","type":"address"},{"indexed":true,"internalType":"address","name":"market","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"balance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"interest","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"uint16","name":"referralCode","type":"uint16"}],"name":"Supply","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"market","type":"address"},{"indexed":false,"internalType":"uint256","name":"newBorrowIndex","type":"uint256"}],"name":"UpdateBorrowIndex","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"market","type":"address"},{"indexed":false,"internalType":"uint256","name":"newSupplyIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"supplyRate","type":"uint256"}],"name":"UpdateSupplyIndex","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"collateralizer","type":"address"},{"indexed":true,"internalType":"address","name":"collateral","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"balance","type":"uint256"}],"name":"WithdrawCollateral","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"supplier","type":"address"},{"indexed":true,"internalType":"address","name":"market","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"balance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"interest","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"}],"name":"WithdrawSupply","type":"event"},{"inputs":[],"name":"acceptTransferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"market","type":"address"},{"internalType":"address","name":"collateral","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approveBorrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"collateral","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approveWithdrawCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"market","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approveWithdrawSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string[]","name":"operations","type":"string[]"},{"internalType":"uint256[]","name":"pauseDurations","type":"uint256[]"}],"name":"batchPause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string[]","name":"operations","type":"string[]"}],"name":"batchUnpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"market","type":"address"}],"name":"beforeChangeBorrowRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"market","type":"address"}],"name":"beforeChangeSupplyRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"address","name":"collateral","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint16","name":"referralCode","type":"uint16"}],"name":"borrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"market","type":"address"},{"internalType":"address","name":"collateral","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint16","name":"referralCode","type":"uint16"}],"name":"borrowBehalf","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collateral","type":"address"}],"name":"buyLiquidatedCollateral","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"address","name":"collateral","type":"address"},{"internalType":"uint256","name":"marketAmount","type":"uint256"}],"name":"buyLiquidatedCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"collateralAssets","outputs":[{"internalType":"uint256","name":"totalCollateral","type":"uint256"},{"internalType":"uint256","name":"totalLiquidatedCollateral","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collateral","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"collateralize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"collateralize","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"collateralizeBehalf","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"collateral","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"collateralizeBehalf","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collateral","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"depositLiquidationReserve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositLiquidationReserve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"depositPromotionReserve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"depositPromotionReserve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ethAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"market","type":"address"},{"internalType":"address","name":"collateral","type":"address"}],"name":"getAccountBorrow","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"interest","type":"uint256"},{"internalType":"uint256","name":"currentBorrowIndex","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"market","type":"address"},{"internalType":"address","name":"collateral","type":"address"}],"name":"getAccountBorrowAllowance","outputs":[{"internalType":"uint256","name":"res","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"collateral","type":"address"}],"name":"getAccountCollateral","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"timeSinceLastActivity","type":"uint256"},{"internalType":"uint256","name":"borrowPowerValue","type":"uint256"},{"internalType":"uint256","name":"totalBorrowValue","type":"uint256"},{"internalType":"bool","name":"underCollateral","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"market","type":"address"}],"name":"getAccountSupply","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"interest","type":"uint256"},{"internalType":"uint256","name":"currentSupplyIndex","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"collateral","type":"address"}],"name":"getAccountTotalBorrowValue","outputs":[{"internalType":"uint256","name":"totalBorrowValue","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"collateral","type":"address"}],"name":"getAccountWithdrawCollateralAllowance","outputs":[{"internalType":"uint256","name":"res","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"market","type":"address"}],"name":"getAccountWithdrawSupplyAllowance","outputs":[{"internalType":"uint256","name":"res","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"market","type":"address"}],"name":"getCurrentBorrowIndex","outputs":[{"internalType":"uint256","name":"borrowIndex","type":"uint256"},{"internalType":"uint256","name":"borrowRate","type":"uint256"},{"internalType":"uint256","name":"currentTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"market","type":"address"}],"name":"getCurrentSupplyIndex","outputs":[{"internalType":"uint256","name":"supplyIndex","type":"uint256"},{"internalType":"uint256","name":"supplyRate","type":"uint256"},{"internalType":"uint256","name":"currentTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"address","name":"collateral","type":"address"},{"internalType":"uint256","name":"marketAmount","type":"uint256"}],"name":"getDiscountedCollateralAmount","outputs":[{"internalType":"uint256","name":"collateralAmountWithDiscount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collateral","type":"address"}],"name":"getLiquidationReserve","outputs":[{"internalType":"uint256","name":"reserve","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"market","type":"address"}],"name":"getPromotionDebt","outputs":[{"internalType":"uint256","name":"promotionDebtScaled","type":"uint256"},{"internalType":"uint256","name":"currentTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"market","type":"address"}],"name":"getPromotionReserve","outputs":[{"internalType":"uint256","name":"promotionReserveScaled","type":"uint256"},{"internalType":"uint256","name":"currentTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"holdefiCollaterals","outputs":[{"internalType":"contract HoldefiCollaterals","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"holdefiPrices","outputs":[{"internalType":"contract HoldefiPricesInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"holdefiSettings","outputs":[{"internalType":"contract HoldefiSettingsInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"operation","type":"string"}],"name":"isPaused","outputs":[{"internalType":"bool","name":"res","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"borrower","type":"address"},{"internalType":"address","name":"market","type":"address"},{"internalType":"address","name":"collateral","type":"address"}],"name":"liquidateBorrowerCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"marketAssets","outputs":[{"internalType":"uint256","name":"totalSupply","type":"uint256"},{"internalType":"uint256","name":"supplyIndex","type":"uint256"},{"internalType":"uint256","name":"supplyIndexUpdateTime","type":"uint256"},{"internalType":"uint256","name":"totalBorrow","type":"uint256"},{"internalType":"uint256","name":"borrowIndex","type":"uint256"},{"internalType":"uint256","name":"borrowIndexUpdateTime","type":"uint256"},{"internalType":"uint256","name":"promotionReserveScaled","type":"uint256"},{"internalType":"uint256","name":"promotionReserveLastUpdateTime","type":"uint256"},{"internalType":"uint256","name":"promotionDebtScaled","type":"uint256"},{"internalType":"uint256","name":"promotionDebtLastUpdateTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"marketDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxPauseDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"operation","type":"string"},{"internalType":"uint256","name":"pauseDuration","type":"uint256"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"","type":"string"}],"name":"paused","outputs":[{"internalType":"bool","name":"isValid","type":"bool"},{"internalType":"uint256","name":"pauseEndTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pauser","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rateDecimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"address","name":"collateral","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"repayBorrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collateral","type":"address"}],"name":"repayBorrow","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"collateral","type":"address"}],"name":"repayBorrowBehalf","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"market","type":"address"},{"internalType":"address","name":"collateral","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"repayBorrowBehalf","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"market","type":"address"}],"name":"reserveSettlement","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"secondsPerYear","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract HoldefiPricesInterface","name":"newHoldefiPrices","type":"address"}],"name":"setHoldefiPricesContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newPauser","type":"address"}],"name":"setPauser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"referralCode","type":"uint16"}],"name":"supply","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint16","name":"referralCode","type":"uint16"}],"name":"supply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint16","name":"referralCode","type":"uint16"}],"name":"supplyBehalf","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"market","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint16","name":"referralCode","type":"uint16"}],"name":"supplyBehalf","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"operation","type":"string"}],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collateral","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"collateral","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawCollateralBehalf","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collateral","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawLiquidationReserve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawPromotionReserve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"market","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawSupplyBehalf","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

60806040523480156200001157600080fd5b5060405162006677380380620066778339810160408190526200003491620002aa565b600080546001600160a01b03191633178082556040517f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09262000081926001600160a01b031691620003c6565b60405180910390a1600160036040516200009b906200039d565b908152604051908190036020018120805492151560ff1990931692909217909155600190600390620000cd906200036a565b908152604051908190036020018120805492151560ff1990931692909217909155600190600390620000ff9062000384565b908152604051908190036020018120805492151560ff1990931692909217909155600190600390620001319062000311565b908152604051908190036020018120805492151560ff199093169290921790915560019060039062000163906200032f565b908152604051908190036020018120805492151560ff19909316929092179091556001906003906200019590620003af565b908152604051908190036020018120805492151560ff1990931692909217909155600190600390620001c79062000341565b908152604051908190036020018120805492151560ff1990931692909217909155600190600390620001f990620002e8565b908152604051908190036020018120805492151560ff1990931692909217909155600480546001600160a01b038086166001600160a01b031992831617909255600580549285169290911691909117905562000255906200029c565b604051809103906000f08015801562000272573d6000803e3d6000fd5b50600680546001600160a01b0319166001600160a01b039290921691909117905550620003f99050565b61035b806200631c83390190565b60008060408385031215620002bd578182fd5b8251620002ca81620003e0565b6020840151909250620002dd81620003e0565b809150509250929050565b7f6275794c697175696461746564436f6c6c61746572616c000000000000000000815260170190565b711dda5d1a191c985dd0dbdb1b185d195c985b60721b815260120190565b65626f72726f7760d01b815260060190565b7f6c6971756964617465426f72726f776572436f6c6c61746572616c00000000008152601b0190565b6d7769746864726177537570706c7960901b8152600e0190565b6c636f6c6c61746572616c697a6560981b8152600d0190565b65737570706c7960d01b815260060190565b6a7265706179426f72726f7760a81b8152600b0190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b0381168114620003f657600080fd5b50565b615f1380620004096000396000f3fe6080604052600436106103fd5760003560e01c806377e3e0bc11610213578063a366a66011610123578063d9379354116100ab578063e9cd21b31161007a578063e9cd21b314610b99578063ec30291b14610bb9578063eef9a8d514610bd9578063f2fde38b14610be1578063ffab819914610c0157610407565b8063d937935414610b24578063e30c397814610b44578063e72b602614610b59578063e79faa5814610b7957610407565b8063ca6ba2dd116100f2578063ca6ba2dd14610a8f578063cb7f197b14610aa4578063ced37ed414610ac4578063cf65996314610ae4578063d2d9b06b14610b0457610407565b8063a366a66014610a02578063ae1dfbde14610a22578063b41ff58314610a4f578063c7975ce814610a6f57610407565b80638bc2395d116101a65780639a6dbc30116101755780639a6dbc301461096f5780639ace08451461098f5780639d9c8ffa146109af5780639fd0506d146109b75780639ff6f77c146109cc57610407565b80638bc2395d146108fa5780638da5cb5b1461091a57806396f17e801461092f57806399711e491461094f57610407565b80638165378a116101e25780638165378a1461086957806381bd1b401461088957806382b69a80146108a957806384d47a47146108da57610407565b806377e3e0bc1461080157806378c37b0c1461081457806379ce0029146108345780637b3711071461085457610407565b806332a569e01161030e57806348e27b7e116102a157806356a61f151161027057806356a61f151461078457806363403cf9146107a457806364433d27146107c457806367ced2fb146107d95780636c3e09ff146107ec57610407565b806348e27b7e146106f65780634b06ca5e14610716578063519c4f7314610736578063539097271461075657610407565b806340d88175116102dd57806340d881751461069b57806341398b15146106bb57806341691931146106d0578063466f14ca146106e357610407565b806332a569e01461061b57806333ec68c51461063b578063350c35e91461065b57806335b841c71461067b57610407565b8063194154d41161039157806321b3b0fd1161036057806321b3b0fd14610577578063252e40b1146105a6578063299dee48146105bb5780632d88af4a146105db5780632ee63f79146105fb57610407565b8063194154d4146104f45780631a3480b5146105145780631ac260e814610529578063200def811461055757610407565b80631181ea91116103cd5780631181ea911461048c57806313a0ec281461049f57806313b7c416146104bf5780631767688d146104c757610407565b806220311b1461040c57806301057af81461042e5780630491331f1461044e578063062766d11461047957610407565b3661040757600080fd5b600080fd5b34801561041857600080fd5b5061042c6104273660046151a1565b610c21565b005b34801561043a57600080fd5b5061042c610449366004615267565b610c74565b34801561045a57600080fd5b50610463610cbc565b60405161047091906155ae565b60405180910390f35b61042c610487366004614ff1565b610ccb565b61042c61049a366004615232565b610ce7565b3480156104ab57600080fd5b5061042c6104ba366004615267565b610d05565b61042c610d47565b3480156104d357600080fd5b506104e76104e2366004615045565b610d61565b60405161047091906156ba565b34801561050057600080fd5b5061042c61050f3660046150ea565b610d97565b34801561052057600080fd5b506104e7610ea2565b34801561053557600080fd5b50610549610544366004615471565b610ea8565b6040516104709291906156aa565b34801561056357600080fd5b506104e761057236600461500d565b610ed2565b34801561058357600080fd5b50610597610592366004614ff1565b610eef565b60405161047093929190615d97565b3480156105b257600080fd5b506104e7610ff9565b3480156105c757600080fd5b5061042c6105d63660046151a1565b611001565b3480156105e757600080fd5b5061042c6105f6366004614ff1565b611092565b34801561060757600080fd5b5061059761061636600461500d565b611123565b34801561062757600080fd5b506104e761063636600461500d565b611203565b34801561064757600080fd5b5061042c610656366004614ff1565b61138a565b34801561066757600080fd5b5061042c610676366004615267565b6113a5565b34801561068757600080fd5b5061042c610696366004614ff1565b6113b0565b3480156106a757600080fd5b5061042c6106b63660046151e1565b611441565b3480156106c757600080fd5b5061046361144e565b61042c6106de36600461500d565b611460565b61042c6106f1366004614ff1565b61147a565b34801561070257600080fd5b5061042c610711366004615045565b611494565b34801561072257600080fd5b50610597610731366004614ff1565b61198b565b34801561074257600080fd5b506104e761075136600461508f565b611a85565b34801561076257600080fd5b50610776610771366004614ff1565b611ac6565b604051610470929190615d89565b34801561079057600080fd5b5061059761079f366004615045565b611adf565b3480156107b057600080fd5b506107766107bf366004614ff1565b611bec565b3480156107d057600080fd5b506104e7611d13565b61042c6107e7366004615502565b611d1a565b3480156107f857600080fd5b50610463611d34565b61042c61080f366004614ff1565b611d43565b34801561082057600080fd5b5061042c61082f3660046151e1565b611d5c565b34801561084057600080fd5b5061042c61084f366004615292565b611da7565b34801561086057600080fd5b5061042c611deb565b34801561087557600080fd5b506104e7610884366004614ff1565b611eaf565b34801561089557600080fd5b5061042c6108a43660046151a1565b612185565b3480156108b557600080fd5b506108c96108c436600461500d565b612285565b604051610470959493929190615dad565b3480156108e657600080fd5b5061042c6108f536600461539c565b612498565b34801561090657600080fd5b50610776610915366004614ff1565b6124fd565b34801561092657600080fd5b5061046361265b565b34801561093b57600080fd5b5061042c61094a366004615267565b61266a565b34801561095b57600080fd5b5061042c61096a36600461513a565b6126ac565b34801561097b57600080fd5b5061042c61098a366004614ff1565b61275b565b34801561099b57600080fd5b5061042c6109aa3660046151a1565b612889565b61042c6128cc565b3480156109c357600080fd5b506104636128e4565b3480156109d857600080fd5b506109ec6109e7366004614ff1565b6128f3565b6040516104709a99989796959493929190615dd2565b348015610a0e57600080fd5b506104e7610a1d3660046151a1565b612947565b348015610a2e57600080fd5b50610a42610a3d366004615471565b612af9565b604051610470919061569f565b348015610a5b57600080fd5b5061042c610a6a366004615267565b612b35565b348015610a7b57600080fd5b506104e7610a8a366004615045565b612c63565b348015610a9b57600080fd5b50610463612c99565b348015610ab057600080fd5b5061042c610abf366004614ff1565b612ca8565b348015610ad057600080fd5b5061042c610adf3660046151a1565b612cba565b348015610af057600080fd5b5061042c610aff3660046154a4565b612dba565b348015610b1057600080fd5b5061042c610b1f3660046151a1565b612eea565b348015610b3057600080fd5b5061042c610b3f366004615267565b612f2d565b348015610b5057600080fd5b50610463613038565b348015610b6557600080fd5b5061042c610b74366004615267565b613047565b348015610b8557600080fd5b5061042c610b94366004615471565b613052565b348015610ba557600080fd5b5061042c610bb4366004615361565b613145565b348015610bc557600080fd5b5061042c610bd43660046151a1565b613175565b61042c613206565b348015610bed57600080fd5b5061042c610bfc366004614ff1565b61321f565b348015610c0d57600080fd5b5061042c610c1c3660046150ea565b6132c5565b826001600160a01b038116600080516020615ebe8339815191521415610c625760405162461bcd60e51b8152600401610c5990615bb0565b60405180910390fd5b610c6e33858585613305565b50505050565b816001600160a01b038116600080516020615ebe8339815191521415610cac5760405162461bcd60e51b8152600401610c5990615bb0565b610cb7338484613581565b505050565b6006546001600160a01b031681565b610ce4600080516020615ebe83398151915282346137a2565b50565b610d0182600080516020615ebe83398151915234846139c7565b5050565b816001600160a01b038116600080516020615ebe8339815191521415610d3d5760405162461bcd60e51b8152600401610c5990615bb0565b610cb78383613bd7565b610d5f600080516020615ebe83398151915234613d88565b565b6001600160a01b039283166000908152600a60209081526040808320938616835292815282822093909416815291909252205490565b83336001600160a01b0382161415610dc15760405162461bcd60e51b8152600401610c5990615b53565b600480546040516327fdbddf60e21b815286926001600160a01b0390921691639ff6f77c91610df2918591016155ae565b60e06040518083038186803b158015610e0a57600080fd5b505afa158015610e1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e4291906154e7565b60200151610e625760405162461bcd60e51b8152600401610c5990615aee565b5050336000908152600b602090815260408083206001600160a01b0395861684528252808320958516835294815284822095909316815293909152912055565b61271081565b80516020818301810180516003825292820191909301209152805460019091015460ff9091169082565b600960209081526000928352604080842090915290825290205481565b600480546040516353c9937760e11b815260009283928392839283926001600160a01b03169163a79326ee91610f27918a91016155ae565b60606040518083038186803b158015610f3f57600080fd5b505afa158015610f53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f779190615536565b6001600160a01b0389166000908152600760205260408120600201544297509295509093509150610fa9908590613ee1565b9050610fb58383613f2c565b94506000610fc38287613f51565b6001600160a01b038916600090815260076020526040902060010154909150610fec9082613f2c565b9650505050509193909250565b6301e1338081565b6001600160a01b038084166000908152600a602090815260408083209386168352928152828220338352905220548082111561104f5760405162461bcd60e51b8152600401610c599061596f565b6110598183613ee1565b6001600160a01b038086166000908152600a60209081526040808320938816835292815282822033835290522055610c6e848484613f8b565b6000546001600160a01b031633146110bc5760405162461bcd60e51b8152600401610c59906158f5565b6002546040517f95bb211a5a393c4d30c3edc9a745825fba4e6ad3e3bb949e6bf8ccdfe431a811916110f99184916001600160a01b03169061566c565b60405180910390a1600280546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b038083166000908152600a60209081526040808320938516835292905290812060010154908061115984610eef565b50506001600160a01b038087166000908152600a6020908152604080832093891683529290529081206003015491925090611195908390613ee1565b905060006111a38286613f51565b905060006111c16127106111bb846301e1338061417b565b9061417b565b6001600160a01b03808a166000908152600a60209081526040808320938c16835292905220600201549091506111f79082613f2c565b94505050509250925092565b600061120d614e76565b60008060008094506060600460009054906101000a90046001600160a01b03166001600160a01b031663ab7dab036040518163ffffffff1660e01b815260040160006040518083038186803b15801561126557600080fd5b505afa158015611279573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526112a191908101906152c8565b905060005b815181101561137e578181815181106112bb57fe5b602002602001015194506112d089868a611adf565b50602088018190528188526112e59190613f2c565b60055460405163558febc560e01b81529195506001600160a01b03169063558febc5906113189088908890600401615686565b60206040518083038186803b15801561133057600080fd5b505afa158015611344573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611368919061551e565b92506113748784613f2c565b96506001016112a6565b50505050505092915050565b611393816141bd565b61139c8161422b565b610ce48161429c565b610d013383836143ab565b6000546001600160a01b031633146113da5760405162461bcd60e51b8152600401610c59906158f5565b6005546040517f9aac81f02d797533c2176f6821d7e32446343e83f54e6292010910be498cb3e3916114179184916001600160a01b03169061566c565b60405180910390a1600580546001600160a01b0319166001600160a01b0392909216919091179055565b610c6e33858585856146a0565b600080516020615ebe83398151915281565b610d0182600080516020615ebe8339815191528334613305565b610ce433600080516020615ebe8339815191528334613305565b6040518060400160405280601b81526020017f6c6971756964617465426f72726f776572436f6c6c61746572616c00000000008152506114d381612af9565b156114f05760405162461bcd60e51b8152600401610c599061572f565b6114f8614e76565b611503858585611adf565b5060208301528082526115285760405162461bcd60e51b8152600401610c5990615c84565b60008060006115378887612285565b9450505092509250808061154e57506301e1338082115b61156a5760405162461bcd60e51b8152600401610c5990615cb3565b6020840151845160009161157e9190613f2c565b60055460405163558febc560e01b81529192506000916001600160a01b039091169063558febc5906115b6908c908690600401615686565b60206040518083038186803b1580156115ce57600080fd5b505afa1580156115e2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611606919061551e565b905060006116af6127106111bb600460009054906101000a90046001600160a01b03166001600160a01b031663539097278d6040518263ffffffff1660e01b815260040161165491906155ae565b60e06040518083038186803b15801561166c57600080fd5b505afa158015611680573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a491906154e7565b608001518590613f51565b600554604051635a3b745160e11b81529192506000916001600160a01b039091169063b476e8a2906116e7908d908690600401615686565b60206040518083038186803b1580156116ff57600080fd5b505afa158015611713573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611737919061551e565b9050868111156117445750855b61174e8782613ee1565b6001600160a01b03808e166000908152600c60209081526040808320938f16835292815282822060010193909355600890925290205461178e9082613ee1565b6001600160a01b038b166000908152600860205260409020908155600101546117b79082613f2c565b600860008c6001600160a01b03166001600160a01b0316815260200190815260200160002060010181905550600b60008d6001600160a01b03166001600160a01b0316815260200190815260200160002060008b6001600160a01b03166001600160a01b0316815260200190815260200160002060008c6001600160a01b03166001600160a01b03168152602001908152602001600020600060018201600090556002820160009055600382016000905550506118738b61138a565b87516001600160a01b038c1660009081526007602052604090206003015461189a91613ee1565b6001600160a01b03808d16600081815260076020908152604080832060030195909555928e16815260098352838120918152915220546118da9085613f2c565b600960008c6001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b0316815260200190815260200160002081905550896001600160a01b03168b6001600160a01b03168d6001600160a01b03167f9459a8332762f885ecd10e55595000d48ad3d31187a66259d38102deadc2d6298785604051611975929190615d89565b60405180910390a4505050505050505050505050565b600480546040516327fdbddf60e21b8152600092839283926001600160a01b0390911691639ff6f77c916119c1918891016155ae565b60e06040518083038186803b1580156119d957600080fd5b505afa1580156119ed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a1191906154e7565b6040908101516001600160a01b0386166000908152600760205291822060050154909350429250611a43908390613ee1565b90506000611a518285613f51565b6001600160a01b038716600090815260076020526040902060040154909150611a7a9082613f2c565b945050509193909250565b6001600160a01b039384166000908152600b602090815260408083209387168352928152828220938616825292835281812093909416845291905290205490565b6008602052600090815260409020805460019091015482565b6001600160a01b038084166000908152600b60209081526040808320858516845282528083209386168352929052908120600101549080611b1f8561198b565b50506001600160a01b038088166000908152600b6020908152604080832089851684528252808320938a1683529290529081206003015491925090611b65908390613ee1565b90506000611b738286613f51565b90506000611b8b6127106111bb846301e1338061417b565b90508515611ba157611b9e816001613f2c565b90505b6001600160a01b03808a166000908152600b602090815260408083208b851684528252808320938c1683529290522060020154611bde9082613f2c565b945050505093509350939050565b600480546040516327fdbddf60e21b8152600092839283926001600160a01b0390911691639ff6f77c91611c22918891016155ae565b60e06040518083038186803b158015611c3a57600080fd5b505afa158015611c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c7291906154e7565b60c001516001600160a01b038516600090815260076020526040902060080154935042925090508015611d0d576001600160a01b038416600090815260076020526040812060090154611cc6904290613ee1565b6001600160a01b03861660009081526007602052604081205491925090611ced9084613f51565b90506000611cfb8284613f51565b9050611d078682613f2c565b95505050505b50915091565b62278d0081565b610ce433600080516020615ebe83398151915234846139c7565b6005546001600160a01b031681565b610ce481600080516020615ebe83398151915234613581565b826001600160a01b038116600080516020615ebe8339815191521415611d945760405162461bcd60e51b8152600401610c5990615bb0565b611da0858585856139c7565b5050505050565b826001600160a01b038116600080516020615ebe8339815191521415611ddf5760405162461bcd60e51b8152600401610c5990615bb0565b610c6e338585856139c7565b6001546001600160a01b0316611e135760405162461bcd60e51b8152600401610c5990615793565b6001546001600160a01b03163314611e3d5760405162461bcd60e51b8152600401610c59906158b2565b6001546000546040517f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e092611e80926001600160a01b039182169291169061566c565b60405180910390a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b600080600080600090506060600460009054906101000a90046001600160a01b03166001600160a01b031663ab7dab036040518163ffffffff1660e01b815260040160006040518083038186803b158015611f0957600080fd5b505afa158015611f1d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611f4591908101906152c8565b905060005b815181101561201e57818181518110611f5f57fe5b6020908102919091018101516005546001600160a01b038a81166000908152600985526040808220838616835290955284902054935163558febc560e01b8152929850169163558febc591611fb8918991600401615686565b60206040518083038186803b158015611fd057600080fd5b505afa158015611fe4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612008919061551e565b93506120148385613f2c565b9250600101611f4a565b5060048054604051635390972760e01b81526000926001600160a01b0390921691635390972791612051918b91016155ae565b60e06040518083038186803b15801561206957600080fd5b505afa15801561207d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120a191906154e7565b60c00151905060006120b96127106111bb8685613f51565b600554604051635a3b745160e11b81529192506000916001600160a01b039091169063b476e8a2906120f1908c908690600401615686565b60206040518083038186803b15801561210957600080fd5b505afa15801561211d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612141919061551e565b6001600160a01b038a1660009081526008602052604081206001015490995090915081811115612178576121758183613ee1565b98505b5050505050505050919050565b82336001600160a01b03821614156121af5760405162461bcd60e51b8152600401610c5990615b53565b60048054604051635390972760e01b815285926001600160a01b03909216916353909727916121e0918591016155ae565b60e06040518083038186803b1580156121f857600080fd5b505afa15801561220c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061223091906154e7565b602001516122505760405162461bcd60e51b8152600401610c599061582a565b5050336000908152600c602090815260408083206001600160a01b039586168452825280832095909416825293909352912055565b60048054604051635390972760e01b8152600092839283928392839283926001600160a01b03909116916353909727916122c1918b91016155ae565b60e06040518083038186803b1580156122d957600080fd5b505afa1580156122ed573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061231191906154e7565b60400151905080612334576000806000806000955095509550955095505061248e565b6001600160a01b038089166000908152600c602090815260408083208b8516845290915280822060010154600554915163558febc560e01b81529099509192169063558febc59061238b908b908b90600401615686565b60206040518083038186803b1580156123a357600080fd5b505afa1580156123b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123db919061551e565b905060006123eb836101f4613ee1565b905060006123ff846111bb85612710613f51565b90506000612413836111bb86612710613f51565b905061241f8c8c611203565b9650861561245e576001600160a01b03808d166000908152600c60209081526040808320938f168352929052206002015461245b904290613ee1565b98505b6000975081871015612477576124748288613ee1565b97505b600095508087111561248857600195505b50505050505b9295509295909350565b80518251146124b95760405162461bcd60e51b8152600401610c5990615b1c565b60005b8251811015610cb7576124f58382815181106124d457fe5b60200260200101518383815181106124e857fe5b6020026020010151612dba565b6001016124bc565b600480546040516353c9937760e11b81526000928392839283926001600160a01b039092169163a79326ee91612535918991016155ae565b60606040518083038186803b15801561254d57600080fd5b505afa158015612561573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125859190615536565b506001600160a01b038716600090815260076020526040812054429650929450909250906125b39083613f51565b6001600160a01b038716600090815260076020526040812060030154919250906125dd9085613f51565b6001600160a01b03881660009081526007602081905260408220015491925090612608908790613ee1565b905060006126168385613ee1565b905060006126248284613f51565b6001600160a01b038b1660009081526007602052604090206006015490915061264d9082613f2c565b985050505050505050915091565b6000546001600160a01b031681565b816001600160a01b038116600080516020615ebe83398151915214156126a25760405162461bcd60e51b8152600401610c5990615bb0565b610cb78383613d88565b6001600160a01b038086166000908152600b6020908152604080832087851684528252808320938816835292815282822033835290522054808311156127045760405162461bcd60e51b8152600401610c599061596f565b61270e8184613ee1565b6001600160a01b038088166000908152600b6020908152604080832089851684528252808320938a1683529281528282203383529052205561275386868686866146a0565b505050505050565b6004546001600160a01b031633146127855760405162461bcd60e51b8152600401610c5990615925565b6001600160a01b038116600090815260076020526040902060068101546008909101548082116127c75760405162461bcd60e51b8152600401610c5990615c1e565b6127d18282613ee1565b6001600160a01b03841660008181526007602081905260408083206006810186905560088101939093554291830182905560099092015551919350907f5c52fff46bef66b4a440521759999ef9670832e376b98d7ee002659734ef7bc89061283a9085906156ba565b60405180910390a2826001600160a01b03167f9399961fe2581dafb3996f569092eecc117e76e8cce149b01db1d5cf51bcc531600060405161287c91906156ba565b60405180910390a2505050565b816001600160a01b038116600080516020615ebe83398151915214156128c15760405162461bcd60e51b8152600401610c5990615bb0565b610c6e848484613581565b610d5f600080516020615ebe83398151915234613bd7565b6002546001600160a01b031681565b6007602052806000526040600020600091509050806000015490806001015490806002015490806003015490806004015490806005015490806006015490806007015490806008015490806009015490508a565b60055460405163558febc560e01b815260009182916001600160a01b039091169063558febc59061297e9088908790600401615686565b60206040518083038186803b15801561299657600080fd5b505afa1580156129aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129ce919061551e565b60048054604051635390972760e01b81529293506000926001600160a01b0390911691635390972791612a03918991016155ae565b60e06040518083038186803b158015612a1b57600080fd5b505afa158015612a2f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a5391906154e7565b60c0015190506000612a6b6127106111bb8585613f51565b600554604051635a3b745160e11b81529192506001600160a01b03169063b476e8a290612a9e9089908590600401615686565b60206040518083038186803b158015612ab657600080fd5b505afa158015612aca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aee919061551e565b979650505050505050565b6000600382604051612b0b919061558f565b908152602001604051809103902060010154421115612b2c57506000612b30565b5060015b919050565b6000546001600160a01b03163314612b5f5760405162461bcd60e51b8152600401610c59906158f5565b6000612b6a83611eaf565b90508181811115612b785750805b6001600160a01b038416600090815260086020526040902060010154612b9e9082613ee1565b6001600160a01b0380861660009081526008602052604090819020600101929092556006549151636ce5768960e11b815291169063d9caed1290612bea908790339086906004016155c2565b600060405180830381600087803b158015612c0457600080fd5b505af1158015612c18573d6000803e3d6000fd5b50505050836001600160a01b03167fc0f567bdb4bab92957ab0c733f377dac6ad0ebec922e60e308dcae1afc43d9ef84604051612c5591906156ba565b60405180910390a250505050565b6001600160a01b039283166000908152600c60209081526040808320938616835292815282822093909416815291909252205490565b6004546001600160a01b031681565b612cb181614bdc565b610ce48161138a565b82336001600160a01b0382161415612ce45760405162461bcd60e51b8152600401610c5990615b53565b600480546040516327fdbddf60e21b815285926001600160a01b0390921691639ff6f77c91612d15918591016155ae565b60e06040518083038186803b158015612d2d57600080fd5b505afa158015612d41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d6591906154e7565b60200151612d855760405162461bcd60e51b8152600401610c5990615aee565b5050336000908152600a602090815260408083206001600160a01b039586168452825280832095909416825293909352912055565b6000546001600160a01b0316331480612ddd57506002546001600160a01b031633145b612df95760405162461bcd60e51b8152600401610c5990615d54565b81600381604051612e0a919061558f565b9081526040519081900360200190205460ff16612e395760405162461bcd60e51b8152600401610c59906157c3565b82612e4381612af9565b15612e605760405162461bcd60e51b8152600401610c599061572f565b62278d00831115612e835760405162461bcd60e51b8152600401610c5990615c55565b824201600385604051612e96919061558f565b9081526020016040518091039020600101819055507fa24d4c9947433144a2a494705b9c99834a270e90aa4ec8bdc3c8556c93064f428484604051612edc9291906156d6565b60405180910390a150505050565b826001600160a01b038116600080516020615ebe8339815191521415612f225760405162461bcd60e51b8152600401610c5990615bb0565b610c6e8484846137a2565b6000546001600160a01b03163314612f575760405162461bcd60e51b8152600401610c59906158f5565b6000612f62836124fd565b5090506000612f7084611bec565b5090506000612f8f612710612f89866301e13380613f51565b90613f51565b90506000612f9d8284613f2c565b9050808411612fbe5760405162461bcd60e51b8152600401610c59906156f8565b612fc88483613ee1565b6001600160a01b038716600090815260076020526040902060060155612fef338787614c45565b856001600160a01b03167f19cfdb0a7a01ce6ee79f50ab5304dced2cdc9b1e77b711c114cd92a8d1cfa84f8660405161302891906156ba565b60405180910390a2505050505050565b6001546001600160a01b031681565b610d01338383613f8b565b6000546001600160a01b0316331461307c5760405162461bcd60e51b8152600401610c59906158f5565b8060038160405161308d919061558f565b9081526040519081900360200190205460ff166130bc5760405162461bcd60e51b8152600401610c59906157c3565b816130c681612af9565b6130e25760405162461bcd60e51b8152600401610c5990615b81565b60006003846040516130f4919061558f565b9081526020016040518091039020600101819055507f7b56fddce5fc3f50e214df66a44317b6b62ee16a8f730326d1861c01b1f6a9678360405161313891906156c3565b60405180910390a1505050565b60005b8151811015610d015761316d82828151811061316057fe5b6020026020010151613052565b600101613148565b6001600160a01b038084166000908152600c60209081526040808320938616835292815282822033835290522054808211156131c35760405162461bcd60e51b8152600401610c599061596f565b6131cd8183613ee1565b6001600160a01b038086166000908152600c60209081526040808320938816835292815282822033835290522055610c6e8484846143ab565b610d5f33600080516020615ebe83398151915234613581565b6000546001600160a01b031633146132495760405162461bcd60e51b8152600401610c59906158f5565b6001600160a01b03811661326f5760405162461bcd60e51b8152600401610c5990615a07565b600180546001600160a01b0319166001600160a01b0383161790556040517fb5f93621aaa9609df127191dc93af5225a2e67cf57d8b1c12df0e4fffcafecb2906132ba9083906155ae565b60405180910390a150565b826001600160a01b038116600080516020615ebe83398151915214156132fd5760405162461bcd60e51b8152600401610c5990615bb0565b611da0858585855b6040518060400160405280600b81526020016a7265706179426f72726f7760a81b81525061333281612af9565b1561334f5760405162461bcd60e51b8152600401610c599061572f565b613357614e76565b613362868686611adf565b60408401526020830181905281835260009161337d91613f2c565b90508061339c5760405162461bcd60e51b8152600401610c5990615ab9565b83818111156133ef5750806001600160a01b038716600080516020615ebe83398151915214156133ef5760006133d28683613ee1565b90506133ed33600080516020615ebe83398151915283614c45565b505b6001600160a01b038716600080516020615ebe8339815191521461341857613418308883614d6d565b60008360200151821161343e5760208401516134349083613ee1565b6020850152613467565b602084015161344e908390613ee1565b6000602086015284519091506134649082613ee1565b84525b83516001600160a01b038a81166000818152600b602090815260408083208d8616808552908352818420958f1684529482528083206001810196909655818a0151600280880191909155818b0151600390970196909655928252600c8152828220938252929092529020429101556134de8861138a565b6001600160a01b0388166000908152600760205260409020600301546135049082613ee1565b6001600160a01b03808a16600081815260076020908152604091829020600301949094558751938801518882015191518c85169593948f16937faafc6a5355a2c7d228082caaf814b75e4edda64221b54310a8b49a1e0fa9f02c9361356e9333938b939290615607565b60405180910390a4505050505050505050565b6040518060400160405280600d81526020016c636f6c6c61746572616c697a6560981b8152506135b081612af9565b156135cd5760405162461bcd60e51b8152600401610c599061572f565b60048054604051635390972760e01b815285926001600160a01b03909216916353909727916135fe918591016155ae565b60e06040518083038186803b15801561361657600080fd5b505afa15801561362a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061364e91906154e7565b6020015161366e5760405162461bcd60e51b8152600401610c599061582a565b6001600160a01b038416600080516020615ebe833981519152146136a8576006546136a3906001600160a01b03168585614d6d565b6136bf565b6006546136bf906001600160a01b03168585614c45565b6001600160a01b038086166000908152600c602090815260408083209388168352929052908120600101546136f49085613f2c565b6001600160a01b038781166000908152600c60209081526040808320938a168352928152828220600181018590554260029091015560089052205490915061373c9085613f2c565b6001600160a01b0380871660008181526008602052604090819020939093559151908816907f329580f0bfda310435774ccdfedced004d0398b20893d50d160e22d17dc1eef890613792903390899087906155e6565b60405180910390a3505050505050565b6040518060400160405280601781526020017f6275794c697175696461746564436f6c6c61746572616c0000000000000000008152506137e181612af9565b156137fe5760405162461bcd60e51b8152600401610c599061572f565b6001600160a01b03808416600090815260096020908152604080832093881683529290522054808311156138445760405162461bcd60e51b8152600401610c5990615d02565b6000613851868686612947565b6001600160a01b038616600090815260086020526040902060010154909150808211156138905760405162461bcd60e51b8152600401610c5990615a48565b6001600160a01b038716600080516020615ebe833981519152146138b9576138b9308887614d6d565b6138c38183613ee1565b6001600160a01b0387166000908152600860205260409020600101556138e98386613ee1565b6001600160a01b0380881660009081526009602090815260408083208c8516845290915290819020929092556006549151636ce5768960e11b815291169063d9caed129061393f908990339087906004016155c2565b600060405180830381600087803b15801561395957600080fd5b505af115801561396d573d6000803e3d6000fd5b50505050856001600160a01b0316876001600160a01b03167f3625a9db2808130a85d7ee8ebebcc50d2dc813dceab24eb2ea338208bfe7ad3987856040516139b6929190615d89565b60405180910390a350505050505050565b60405180604001604052806006815260200165737570706c7960d01b8152506139ef81612af9565b15613a0c5760405162461bcd60e51b8152600401610c599061572f565b600480546040516327fdbddf60e21b815286926001600160a01b0390921691639ff6f77c91613a3d918591016155ae565b60e06040518083038186803b158015613a5557600080fd5b505afa158015613a69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a8d91906154e7565b60200151613aad5760405162461bcd60e51b8152600401610c5990615aee565b6001600160a01b038516600080516020615ebe83398151915214613ad657613ad6308686614d6d565b613ade614e76565b613ae88787611123565b60408401526020830152808252613aff9086613f2c565b8082526001600160a01b038881166000908152600a60209081526040808320938b1683529281529082902060018101939093558301516002830155820151600390910155613b4c8661138a565b6001600160a01b038616600090815260076020526040902054613b6f9086613f2c565b6001600160a01b03808816600081815260076020908152604091829020949094558451938501518582015191519294938c16937f3907893e31751fa905efeaed7eb741f574cc25081ea97d8b61b72ca0098975aa936139b69333938d93929091908d90615635565b60048054604051635390972760e01b8152600080516020615ebe833981519152926001600160a01b0390921691635390972791613c16918591016155ae565b60e06040518083038186803b158015613c2e57600080fd5b505afa158015613c42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c6691906154e7565b60200151613c865760405162461bcd60e51b8152600401610c599061582a565b6001600160a01b038316600080516020615ebe83398151915214613cc057600654613cbb906001600160a01b03168484614d6d565b613cd7565b600654613cd7906001600160a01b03168484614c45565b600080516020615ebe83398151915260005260086020527f353c2eb9e53a4a4a6d45d72082ff2e9dc829d1125618772a83eb0e7f86632c4354613d1a9034613f2c565b600080516020615ebe833981519152600081905260086020527f353c2eb9e53a4a4a6d45d72082ff2e9dc829d1125618772a83eb0e7f86632c43919091556040517fd20725a752206fd0ab2c59aea525cc6a8ab3a4abc426d1b147cd6f70ddb6b3439061287c9034906156ba565b600480546040516327fdbddf60e21b815284926001600160a01b0390921691639ff6f77c91613db9918591016155ae565b60e06040518083038186803b158015613dd157600080fd5b505afa158015613de5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e0991906154e7565b60200151613e295760405162461bcd60e51b8152600401610c5990615aee565b6001600160a01b038316600080516020615ebe83398151915214613e5257613e52308484614d6d565b6000613e68612710612f89856301e13380613f51565b6001600160a01b038516600090815260076020526040902060060154909150613e919082613f2c565b6001600160a01b038516600081815260076020526040908190206006019290925590517f96e899243fea7f4ec20196f130cadb8eeaa1f1359a52a7c9be05a84caaf1d15190612c559086906156ba565b6000613f2383836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250614e13565b90505b92915050565b600082820183811015613f235760405162461bcd60e51b8152600401610c599061575c565b600082613f6057506000613f26565b82820282848281613f6d57fe5b0414613f235760405162461bcd60e51b8152600401610c59906159c6565b6040518060400160405280600e81526020016d7769746864726177537570706c7960901b815250613fbb81612af9565b15613fd85760405162461bcd60e51b8152600401610c599061572f565b613fe0614e76565b613fea8585611123565b60408401526020830181905281835260009161400591613f2c565b9050806140245760405162461bcd60e51b8152600401610c5990615ab9565b83818111156140305750805b60008360200151821161405657602084015161404c9083613ee1565b602085015261407f565b6020840151614066908390613ee1565b60006020860152845190915061407c9082613ee1565b84525b83516001600160a01b038981166000908152600a60209081526040808320938c16835292815290829020600181019390935586015160028301558501516003909101556140cb8761138a565b6001600160a01b0387166000908152600760205260409020546140ee9082613ee1565b6001600160a01b038816600090815260076020526040902055614112338884614c45565b866001600160a01b0316886001600160a01b03167f5dde65f16d871c3d3acc3940bc4341c6f21d1f039535c80b00a9c688cb137a1e3385886000015189602001518a60400151604051614169959493929190615607565b60405180910390a35050505050505050565b6000613f2383836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250614e3f565b60008060006141cb84610eef565b6001600160a01b0387166000818152600760205260409081902060018101869055600201839055519396509194509250907f47d6b7a10346c15222b1397eae9d7e54fe791c53dec1305baf26c899ee457dea90612c559086908690615d89565b6000614236826124fd565b506001600160a01b038316600081815260076020819052604091829020600681018590554291015551919250907f5c52fff46bef66b4a440521759999ef9670832e376b98d7ee002659734ef7bc8906142909084906156ba565b60405180910390a25050565b60006142a782611bec565b506001600160a01b038316600090815260076020526040902060080154909150811461432c576001600160a01b038216600081815260076020526040908190206008810184905542600990910155517f9399961fe2581dafb3996f569092eecc117e76e8cce149b01db1d5cf51bcc531906143239084906156ba565b60405180910390a25b6001600160a01b0382166000908152600760205260409020600601548110610d015760048054604051637513a32f60e01b81526001600160a01b0390911691637513a32f9161437d918691016155ae565b600060405180830381600087803b15801561439757600080fd5b505af1158015612753573d6000803e3d6000fd5b604051806040016040528060128152602001711dda5d1a191c985dd0dbdb1b185d195c985b60721b8152506143df81612af9565b156143fc5760405162461bcd60e51b8152600401610c599061572f565b600080600061440b8787612285565b509350935050925081600014156144345760405162461bcd60e51b8152600401610c59906157f3565b6000811561455e5760048054604051635390972760e01b81526000926001600160a01b039092169163539097279161446e918c91016155ae565b60e06040518083038186803b15801561448657600080fd5b505afa15801561449a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144be91906154e7565b60400151905060006144d66127106111bb8685613f51565b600554604051635a3b745160e11b81529192506001600160a01b03169063b476e8a290614509908c908590600401615686565b60206040518083038186803b15801561452157600080fd5b505afa158015614535573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614559919061551e565b925050505b600061456a8583613ee1565b905086818111156145785750805b6145828682613ee1565b6001600160a01b038b81166000908152600c60209081526040808320938e16835292815282822060018101859055426002909101556008905220549096506145ca9082613ee1565b6001600160a01b03808b1660009081526008602052604090819020929092556006549151636ce5768960e11b815291169063d9caed1290614613908c90339086906004016155c2565b600060405180830381600087803b15801561462d57600080fd5b505af1158015614641573d6000803e3d6000fd5b50505050886001600160a01b03168a6001600160a01b03167f2c47e95ec6b72bd16d61b3f98761e5edf7ec10ca5210c7693d2a699ea2a0836733848a60405161468c939291906155e6565b60405180910390a350505050505050505050565b60405180604001604052806006815260200165626f72726f7760d01b8152506146c881612af9565b156146e55760405162461bcd60e51b8152600401610c599061572f565b600480546040516327fdbddf60e21b815287926001600160a01b0390921691639ff6f77c91614716918591016155ae565b60e06040518083038186803b15801561472e57600080fd5b505afa158015614742573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061476691906154e7565b602001516147865760405162461bcd60e51b8152600401610c5990615aee565b60048054604051635390972760e01b815287926001600160a01b03909216916353909727916147b7918591016155ae565b60e06040518083038186803b1580156147cf57600080fd5b505afa1580156147e3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061480791906154e7565b602001516148275760405162461bcd60e51b8152600401610c599061582a565b6001600160a01b03871660009081526007602052604090206003810154905461484f91613ee1565b85111561486e5760405162461bcd60e51b8152600401610c5990615be7565b600061487a8988612285565b505060055460405163558febc560e01b8152919450600093506001600160a01b0316915063558febc5906148b4908c908b90600401615686565b60206040518083038186803b1580156148cc57600080fd5b505afa1580156148e0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614904919061551e565b9050808210156149265760405162461bcd60e51b8152600401610c5990615861565b61492e614e76565b6149398b8b8b611adf565b604084015260208301528082526149509089613f2c565b8160000181815250508060000151600b60008d6001600160a01b03166001600160a01b0316815260200190815260200160002060008b6001600160a01b03166001600160a01b0316815260200190815260200160002060008c6001600160a01b03166001600160a01b03168152602001908152602001600020600101819055508060200151600b60008d6001600160a01b03166001600160a01b0316815260200190815260200160002060008b6001600160a01b03166001600160a01b0316815260200190815260200160002060008c6001600160a01b03166001600160a01b03168152602001908152602001600020600201819055508060400151600b60008d6001600160a01b03166001600160a01b0316815260200190815260200160002060008b6001600160a01b03166001600160a01b0316815260200190815260200160002060008c6001600160a01b03166001600160a01b031681526020019081526020016000206003018190555042600c60008d6001600160a01b03166001600160a01b0316815260200190815260200160002060008b6001600160a01b03166001600160a01b0316815260200190815260200160002060020181905550614b178a61138a565b6001600160a01b038a16600090815260076020526040902060030154614b3d9089613f2c565b6001600160a01b038b16600090815260076020526040902060030155614b64338b8a614c45565b886001600160a01b03168a6001600160a01b03168c6001600160a01b03167f81bfde55fca859d0d4d80d624d1cbb08a55933c6e219d4703ab15fbd0d393b9a338c8660000151876020015188604001518f604051614bc796959493929190615635565b60405180910390a45050505050505050505050565b600080614be88361198b565b6001600160a01b038616600081815260076020526040908190206004810186905560050183905551939550909350917f9843bb8e9ab36412f4235cce7cd94c6d986b5f7232f90e6a4fc88b21e5149793915061287c9085906156ba565b60006001600160a01b038316600080516020615ebe8339815191521415614cca57836001600160a01b031682604051614c7d906155ab565b60006040518083038185875af1925050503d8060008114614cba576040519150601f19603f3d011682016040523d82523d6000602084013e614cbf565b606091505b505080915050614d50565b60405163a9059cbb60e01b815283906001600160a01b0382169063a9059cbb90614cfa9088908790600401615686565b602060405180830381600087803b158015614d1457600080fd5b505af1158015614d28573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614d4c9190615455565b9150505b80610c6e5760405162461bcd60e51b8152600401610c599061599d565b6040516323b872dd60e01b815282906000906001600160a01b038316906323b872dd90614da2903390899088906004016155c2565b602060405180830381600087803b158015614dbc57600080fd5b505af1158015614dd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614df49190615455565b905080611da05760405162461bcd60e51b8152600401610c599061599d565b60008184841115614e375760405162461bcd60e51b8152600401610c5991906156c3565b505050900390565b60008183614e605760405162461bcd60e51b8152600401610c5991906156c3565b506000838581614e6c57fe5b0495945050505050565b60405180606001604052806000815260200160008152602001600081525090565b600082601f830112614ea7578081fd5b8135614eba614eb582615e3e565b615e17565b818152915060208083019084810160005b84811015614ef457614ee2888484358a0101614eff565b84529282019290820190600101614ecb565b505050505092915050565b600082601f830112614f0f578081fd5b813567ffffffffffffffff811115614f25578182fd5b614f38601f8201601f1916602001615e17565b9150808252836020828501011115614f4f57600080fd5b8060208401602084013760009082016020015292915050565b600060e08284031215614f79578081fd5b614f8360e0615e17565b90508151614f9081615e9f565b81526020820151614fa081615e9f565b8060208301525060408201516040820152606082015160608201526080820151608082015260a082015160a082015260c082015160c082015292915050565b803561ffff81168114613f2657600080fd5b600060208284031215615002578081fd5b8135613f2381615e8a565b6000806040838503121561501f578081fd5b823561502a81615e8a565b9150602083013561503a81615e8a565b809150509250929050565b600080600060608486031215615059578081fd5b833561506481615e8a565b9250602084013561507481615e8a565b9150604084013561508481615e8a565b809150509250925092565b600080600080608085870312156150a4578081fd5b84356150af81615e8a565b935060208501356150bf81615e8a565b925060408501356150cf81615e8a565b915060608501356150df81615e8a565b939692955090935050565b600080600080608085870312156150ff578384fd5b843561510a81615e8a565b9350602085013561511a81615e8a565b9250604085013561512a81615e8a565b9396929550929360600135925050565b600080600080600060a08688031215615151578081fd5b853561515c81615e8a565b9450602086013561516c81615e8a565b9350604086013561517c81615e8a565b925060608601359150608086013561519381615ead565b809150509295509295909350565b6000806000606084860312156151b5578081fd5b83356151c081615e8a565b925060208401356151d081615e8a565b929592945050506040919091013590565b600080600080608085870312156151f6578182fd5b843561520181615e8a565b9350602085013561521181615e8a565b9250604085013591506152278660608701614fdf565b905092959194509250565b60008060408385031215615244578182fd5b823561524f81615e8a565b915061525e8460208501614fdf565b90509250929050565b60008060408385031215615279578182fd5b823561528481615e8a565b946020939093013593505050565b6000806000606084860312156152a6578081fd5b83356152b181615e8a565b925060208401359150604084013561508481615ead565b600060208083850312156152da578182fd5b825167ffffffffffffffff8111156152f0578283fd5b8301601f81018513615300578283fd5b805161530e614eb582615e3e565b818152838101908385018584028501860189101561532a578687fd5b8694505b8385101561535557805161534181615e8a565b83526001949094019391850191850161532e565b50979650505050505050565b600060208284031215615372578081fd5b813567ffffffffffffffff811115615388578182fd5b61539484828501614e97565b949350505050565b600080604083850312156153ae578182fd5b823567ffffffffffffffff808211156153c5578384fd5b6153d186838701614e97565b93506020915081850135818111156153e7578384fd5b85019050601f810186136153f9578283fd5b8035615407614eb582615e3e565b81815283810190838501858402850186018a1015615423578687fd5b8694505b83851015615445578035835260019490940193918501918501615427565b5080955050505050509250929050565b600060208284031215615466578081fd5b8151613f2381615e9f565b600060208284031215615482578081fd5b813567ffffffffffffffff811115615498578182fd5b61539484828501614eff565b600080604083850312156154b6578182fd5b823567ffffffffffffffff8111156154cc578283fd5b6154d885828601614eff565b95602094909401359450505050565b600060e082840312156154f8578081fd5b613f238383614f68565b600060208284031215615513578081fd5b8135613f2381615ead565b60006020828403121561552f578081fd5b5051919050565b60008060006060848603121561554a578081fd5b8351925060208401519150604084015190509250925092565b6000815180845261557b816020860160208601615e5e565b601f01601f19169290920160200192915050565b600082516155a1818460208701615e5e565b9190910192915050565b90565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b039390931683526020830191909152604082015260600190565b6001600160a01b03959095168552602085019390935260408401919091526060830152608082015260a00190565b6001600160a01b03969096168652602086019490945260408501929092526060840152608083015261ffff1660a082015260c00190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b9115158252602082015260400190565b90815260200190565b600060208252613f236020830184615563565b6000604082526156e96040830185615563565b90508260208301529392505050565b6020808252601e908201527f416d6f756e742073686f756c64206265206c657373207468616e206d61780000604082015260600190565b60208082526013908201527213dc195c985d1a5bdb881a5cc81c185d5cd959606a1b604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526016908201527550656e64696e67206f776e657220697320656d70747960501b604082015260600190565b60208082526016908201527513dc195c985d1a5bdb881a5cc81b9bdd081d985b1a5960521b604082015260600190565b6020808252601f908201527f426f72726f7720706f7765722073686f756c64206e6f74206265207a65726f00604082015260600190565b60208082526018908201527f436f6c6c61746572616c206973206e6f74206163746976650000000000000000604082015260600190565b60208082526031908201527f426f72726f7720706f7765722073686f756c64206265206d6f7265207468616e604082015270206e657720626f72726f772076616c756560781b606082015260800190565b60208082526023908201527f50656e64696e67206f776e6572206973206e6f742073616d652061732073656e6040820152623232b960e91b606082015260800190565b60208082526016908201527529b2b73232b91039b437bab6321031329037bbb732b960511b604082015260600190565b6020808252602a908201527f53656e6465722073686f756c6420626520486f6c646566692053657474696e676040820152691cc818dbdb9d1c9858dd60b21b606082015260800190565b60208082526014908201527315da5d1a191c985dc81b9bdd08185b1b1bddd95960621b604082015260600190565b6020808252600f908201526e21b0b73737ba102a3930b739b332b960891b604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526021908201527f4e6577206f776e65722063616e206e6f74206265207a65726f206164647265736040820152607360f81b606082015260800190565b6020808252604b908201527f436f6c6c61746572616c20616d6f756e74207769746820646973636f756e742060408201527f73686f756c64206265206c657373207468616e20746f74616c206c697175696460608201526a617465642061737365747360a81b608082015260a00190565b6020808252818101527f546f74616c2062616c616e63652073686f756c64206e6f74206265207a65726f604082015260600190565b6020808252601490820152734d61726b6574206973206e6f742061637469766560601b604082015260600190565b6020808252601d908201527f4c6973747320617265206e6f7420657175616c20696e206c656e677468000000604082015260600190565b6020808252601490820152731058d8dbdd5b9d081a5cc81b9bdd081d985b1a5960621b604082015260600190565b60208082526015908201527413dc195c985d1a5bdb881a5cc81d5b9c185d5cd959605a1b604082015260600190565b6020808252601f908201527f41737365742073686f756c64206e6f7420626520455448206164647265737300604082015260600190565b6020808252601f908201527f416d6f756e742073686f756c64206265206c657373207468616e206361736800604082015260600190565b6020808252601c908201527f4e6f7420656e6f7567682070726f6d6f74696f6e207265736572766500000000604082015260600190565b6020808252601590820152744475726174696f6e206e6f7420696e2072616e676560581b604082015260600190565b602080825260159082015274155cd95c881cda1bdd5b19081a185d99481919589d605a1b604082015260600190565b6020808252602f908201527f557365722073686f756c6420626520756e64657220636f6c6c61746572616c2060408201526e37b9103a34b6b29034b99037bb32b960891b606082015260800190565b60208082526032908201527f416d6f756e742073686f756c64206265206c657373207468616e20746f74616c604082015271206c6971756964617465642061737365747360701b606082015260800190565b6020808252818101527f53656e6465722073686f756c64206265206f776e6572206f7220706175736572604082015260600190565b918252602082015260400190565b9283526020830191909152604082015260600190565b9485526020850193909352604084019190915260608301521515608082015260a00190565b998a5260208a019890985260408901969096526060880194909452608087019290925260a086015260c085015260e08401526101008301526101208201526101400190565b60405181810167ffffffffffffffff81118282101715615e3657600080fd5b604052919050565b600067ffffffffffffffff821115615e54578081fd5b5060209081020190565b60005b83811015615e79578181015183820152602001615e61565b83811115610c6e5750506000910152565b6001600160a01b0381168114610ce457600080fd5b8015158114610ce457600080fd5b61ffff81168114610ce457600080fdfe000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeea264697066735822122038fe2570367900bad3c4dfbc91d9613a4b9f4156ff17046a25082319e4bd7c1c64736f6c634300060c0033608060405234801561001057600080fd5b50600080546001600160a01b03191633179055610329806100326000396000f3fe6080604052600436106100375760003560e01c8062d3afc71461008c57806341398b15146100bd578063d9caed12146100d257610087565b36610087576000546001600160a01b031633146100855760405162461bcd60e51b81526004018080602001828103825260218152602001806102d36021913960400191505060405180910390fd5b005b600080fd5b34801561009857600080fd5b506100a1610115565b604080516001600160a01b039092168252519081900360200190f35b3480156100c957600080fd5b506100a1610124565b3480156100de57600080fd5b50610085600480360360608110156100f557600080fd5b506001600160a01b0381358116916020810135909116906040013561013c565b6000546001600160a01b031681565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b6000546001600160a01b031633146101855760405162461bcd60e51b81526004018080602001828103825260218152602001806102d36021913960400191505060405180910390fd5b60006001600160a01b03841673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415610205576040516001600160a01b038416908390600081818185875af1925050503d80600081146101f5576040519150601f19603f3d011682016040523d82523d6000602084013e6101fa565b606091505b505080915050610288565b6040805163a9059cbb60e01b81526001600160a01b038581166004830152602482018590529151869283169163a9059cbb9160448083019260209291908290030181600087803b15801561025857600080fd5b505af115801561026c573d6000803e3d6000fd5b505050506040513d602081101561028257600080fd5b50519150505b806102cc576040805162461bcd60e51b815260206004820152600f60248201526e21b0b73737ba102a3930b739b332b960891b604482015290519081900360640190fd5b5050505056fe53656e6465722073686f756c6420626520686f6c6465666920636f6e7472616374a26469706673582212201c9680aad6f8ca45225b25bbf11d6a9fc22a61789477d9f2522a05d48b5b911964736f6c634300060c0033000000000000000000000000db7908137be8a89a80c094ac93bee37693a1c9680000000000000000000000002b27b93bcd2ed768b5f365f4577d6eeb27186f4f

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000db7908137be8a89a80c094ac93bee37693a1c9680000000000000000000000002b27b93bcd2ed768b5f365f4577d6eeb27186f4f

-----Decoded View---------------
Arg [0] : holdefiSettingsAddress (address): 0xdb7908137be8a89a80c094ac93bee37693a1c968
Arg [1] : holdefiPricesAddress (address): 0x2b27b93bcd2ed768b5f365f4577d6eeb27186f4f

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000db7908137be8a89a80c094ac93bee37693a1c968
Arg [1] : 0000000000000000000000002b27b93bcd2ed768b5f365f4577d6eeb27186f4f


Deployed ByteCode Sourcemap

1877:51665:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9999:8;;;1877:51665;;;;32010:184;;;;;;;;;;-1:-1:-1;32010:184:0;;;;;:::i;:::-;;:::i;:::-;;27369:168;;;;;;;;;;-1:-1:-1;27369:168:0;;;;;:::i;:::-;;:::i;4068:44::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;36296:147;;;;;;:::i;:::-;;:::i;25691:156::-;;;;;;:::i;:::-;;:::i;36615:179::-;;;;;;;;;;-1:-1:-1;36615:179:0;;;;;:::i;:::-;;:::i;38205:117::-;;;:::i;15120:202::-;;;;;;;;;;-1:-1:-1;15120:202:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;30288:237::-;;;;;;;;;;-1:-1:-1;30288:237:0;;;;;:::i;:::-;;:::i;3436:46::-;;;;;;;;;;;;;:::i;677:42:3:-;;;;;;;;;;-1:-1:-1;677:42:3;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;4445:64:0:-;;;;;;;;;;-1:-1:-1;4445:64:0;;;;;:::i;:::-;;:::i;20086:576::-;;;;;;;;;;-1:-1:-1;20086:576:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;3488:49::-;;;;;;;;;;;;;:::i;26842:364::-;;;;;;;;;;-1:-1:-1;26842:364:0;;;;;:::i;:::-;;:::i;5116:152:3:-;;;;;;;;;;-1:-1:-1;5116:152:3;;;;;:::i;:::-;;:::i;10520:607:0:-;;;;;;;;;;-1:-1:-1;10520:607:0;;;;;:::i;:::-;;:::i;16831:717::-;;;;;;;;;;-1:-1:-1;16831:717:0;;;;;:::i;:::-;;:::i;23758:158::-;;;;;;;;;;-1:-1:-1;23758:158:0;;;;;:::i;:::-;;:::i;29177:147::-;;;;;;;;;;-1:-1:-1;29177:147:0;;;;;:::i;:::-;;:::i;39268:226::-;;;;;;;;;;-1:-1:-1;39268:226:0;;;;;:::i;:::-;;:::i;30810:182::-;;;;;;;;;;-1:-1:-1;30810:182:0;;;;;:::i;:::-;;:::i;3283:79::-;;;;;;;;;;;;;:::i;33296:165::-;;;;;;:::i;:::-;;:::i;32367:137::-;;;;;;:::i;:::-;;:::i;33687:1939::-;;;;;;;;;;-1:-1:-1;33687:1939:0;;;;;:::i;:::-;;:::i;21051:497::-;;;;;;;;;;-1:-1:-1;21051:497:0;;;;;:::i;:::-;;:::i;16315:244::-;;;;;;;;;;-1:-1:-1;16315:244:0;;;;;:::i;:::-;;:::i;4285:55::-;;;;;;;;;;-1:-1:-1;4285:55:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;11746:739::-;;;;;;;;;;-1:-1:-1;11746:739:0;;;;;:::i;:::-;;:::i;22963:660::-;;;;;;;;;;-1:-1:-1;22963:660:0;;;;;:::i;:::-;;:::i;409:50:3:-;;;;;;;;;;;;;:::i;24792:129:0:-;;;;;;:::i;:::-;;:::i;3972:43::-;;;;;;;;;;;;;:::i;28388:127::-;;;;;;:::i;:::-;;:::i;25223:196::-;;;;;;;;;;-1:-1:-1;25223:196:0;;;;;:::i;:::-;;:::i;24431:176::-;;;;;;;;;;-1:-1:-1;24431:176:0;;;;;:::i;:::-;;:::i;1989:346:2:-;;;;;;;;;;;;;:::i;17760:1033:0:-;;;;;;;;;;-1:-1:-1;17760:1033:0;;;;;:::i;:::-;;:::i;28774:237::-;;;;;;;;;;-1:-1:-1;28774:237:0;;;;;:::i;:::-;;:::i;13482:1318::-;;;;;;;;;;-1:-1:-1;13482:1318:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;:::i;4348:320:3:-;;;;;;;;;;-1:-1:-1;4348:320:3;;;;;:::i;:::-;;:::i;21886:753:0:-;;;;;;;;;;-1:-1:-1;21886:753:0;;;;;:::i;:::-;;:::i;722:20:2:-;;;;;;;;;;;;;:::i;37924:164:0:-;;;;;;;;;;-1:-1:-1;37924:164:0;;;;;:::i;:::-;;:::i;31336:442::-;;;;;;;;;;-1:-1:-1;31336:442:0;;;;;:::i;:::-;;:::i;39599:808::-;;;;;;;;;;-1:-1:-1;39599:808:0;;;;;:::i;:::-;;:::i;27990:188::-;;;;;;;;;;-1:-1:-1;27990:188:0;;;;;:::i;:::-;;:::i;36919:120::-;;;:::i;647:21:3:-;;;;;;;;;;;;;:::i;4169:47:0:-;;;;;;;;;;-1:-1:-1;4169:47:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;;;:::i;19182:517::-;;;;;;;;;;-1:-1:-1;19182:517:0;;;;;:::i;:::-;;:::i;2862:236:3:-;;;;;;;;;;-1:-1:-1;2862:236:3;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;37215:547:0:-;;;;;;;;;;-1:-1:-1;37215:547:0;;;;;:::i;:::-;;:::i;15655:232::-;;;;;;;;;;-1:-1:-1;15655:232:0;;;;;:::i;:::-;;:::i;3871:47::-;;;;;;;;;;;;;:::i;24066:128::-;;;;;;;;;;-1:-1:-1;24066:128:0;;;;;:::i;:::-;;:::i;26106:213::-;;;;;;;;;;-1:-1:-1;26106:213:0;;;;;:::i;:::-;;:::i;3313:395:3:-;;;;;;;;;;-1:-1:-1;3313:395:3;;;;;:::i;:::-;;:::i;35900:208:0:-;;;;;;;;;;-1:-1:-1;35900:208:0;;;;;:::i;:::-;;:::i;38488:640::-;;;;;;;;;;-1:-1:-1;38488:640:0;;;;;:::i;:::-;;:::i;749:27:2:-;;;;;;;;;;;;;:::i;26485:130:0:-;;;;;;;;;;-1:-1:-1;26485:130:0;;;;;:::i;:::-;;:::i;3846:247:3:-;;;;;;;;;;-1:-1:-1;3846:247:3;;;;;:::i;:::-;;:::i;4831:176::-;;;;;;;;;;-1:-1:-1;4831:176:3;;;;;:::i;:::-;;:::i;29561:399:0:-;;;;;;;;;;-1:-1:-1;29561:399:0;;;;;:::i;:::-;;:::i;27647:109::-;;;:::i;1621:239:2:-;;;;;;;;;;-1:-1:-1;1621:239:2;;;;;:::i;:::-;;:::i;32815:204:0:-;;;;;;;;;;-1:-1:-1;32815:204:0;;;;;:::i;:::-;;:::i;32010:184::-;32115:6;-1:-1:-1;;;;;9061:19:0;;-1:-1:-1;;;;;;;;;;;9061:19:0;;9052:64;;;;-1:-1:-1;;;9052:64:0;;;;;;;:::i;:::-;;;;;;;;;32130:59:::1;32150:10;32162:6;32170:10;32182:6;32130:19;:59::i;:::-;32010:184:::0;;;;:::o;27369:168::-;27460:10;-1:-1:-1;;;;;9061:19:0;;-1:-1:-1;;;;;;;;;;;9061:19:0;;9052:64;;;;-1:-1:-1;;;9052:64:0;;;;;;;:::i;:::-;27479:53:::1;27501:10;27513;27525:6;27479:21;:53::i;:::-;27369:168:::0;;;:::o;4068:44::-;;;-1:-1:-1;;;;;4068:44:0;;:::o;36296:147::-;36372:66;-1:-1:-1;;;;;;;;;;;36416:10:0;36428:9;36372:31;:66::i;:::-;36296:147;:::o;25691:156::-;25782:60;25797:7;-1:-1:-1;;;;;;;;;;;25818:9:0;25829:12;25782:14;:60::i;:::-;25691:156;;:::o;36615:179::-;36717:10;-1:-1:-1;;;;;9061:19:0;;-1:-1:-1;;;;;;;;;;;9061:19:0;;9052:64;;;;-1:-1:-1;;;9052:64:0;;;;;;;:::i;:::-;36736:53:::1;36770:10;36782:6;36736:33;:53::i;38205:117::-:0;38263:54;-1:-1:-1;;;;;;;;;;;38307:9:0;38263:31;:54::i;:::-;38205:117::o;15120:202::-;-1:-1:-1;;;;;15273:17:0;;;15247:11;15273:17;;;:8;:17;;;;;;;;:25;;;;;;;;;;;:44;;;;;;;;;;;;;15120:202::o;30288:237::-;30411:7;9887:10;-1:-1:-1;;;;;9887:21:0;;;;9878:55;;;;-1:-1:-1;;;9878:55:0;;;;;;;:::i;:::-;9306:15:::1;::::0;;:36:::1;::::0;-1:-1:-1;;;9306:36:0;;30438:6;;-1:-1:-1;;;;;9306:15:0;;::::1;::::0;:28:::1;::::0;:36:::1;::::0;30438:6;;9306:36:::1;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:45;;;9297:79;;;;-1:-1:-1::0;;;9297:79:0::1;;;;;;;:::i;:::-;-1:-1:-1::0;;30461:10:0::2;30453:19;::::0;;;:7:::2;:19;::::0;;;;;;;-1:-1:-1;;;;;30453:31:0;;::::2;::::0;;;;;;;:39;;::::2;::::0;;;;;;;;:58;;;::::2;::::0;;;;;;;;:67;30288:237::o;3436:46::-;3475:7;3436:46;:::o;677:42:3:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;4445:64:0:-;;;;;;;;;;;;;;;;;;;;;;;;:::o;20086:576::-;20302:15;;;:36;;-1:-1:-1;;;20302:36:0;;20169:19;;;;;;;;;;-1:-1:-1;;;;;20302:15:0;;:28;;:36;;20331:6;;20302:36;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;20423:20:0;;20381:23;20423:20;;;:12;:20;;;;;:42;;;20361:15;;-1:-1:-1;20250:88:0;;-1:-1:-1;20250:88:0;;-1:-1:-1;20381:23:0;-1:-1:-1;20407:59:0;;20361:15;;20407;:59::i;:::-;20381:85;-1:-1:-1;20486:33:0;:14;20505:13;20486:18;:33::i;:::-;20473:46;-1:-1:-1;20524:25:0;20552:31;:15;20473:46;20552:19;:31::i;:::-;-1:-1:-1;;;;;20602:20:0;;;;;;:12;:20;;;;;:32;;;20524:59;;-1:-1:-1;20602:55:0;;20524:59;20602:36;:55::i;:::-;20588:69;;20086:576;;;;;;;;;:::o;3488:49::-;3529:8;3488:49;:::o;26842:364::-;-1:-1:-1;;;;;26955:17:0;;;26935;26955;;;:8;:17;;;;;;;;:25;;;;;;;;;;;26991:10;26955:47;;;;;;27020:19;;;;27007:66;;;;-1:-1:-1;;;27007:66:0;;;;;;;:::i;:::-;27128:21;:9;27142:6;27128:13;:21::i;:::-;-1:-1:-1;;;;;27078:17:0;;;;;;;:8;:17;;;;;;;;:25;;;;;;;;;;;27114:10;27078:47;;;;;:71;27154:47;27087:7;27096:6;27194;27154:22;:47::i;5116:152:3:-;1393:5:2;;-1:-1:-1;;;;;1393:5:2;1379:10;:19;1371:54;;;;-1:-1:-1;;;1371:54:2;;;;;;;:::i;:::-;5214:6:3::1;::::0;5189:32:::1;::::0;::::1;::::0;::::1;::::0;5203:9;;-1:-1:-1;;;;;5214:6:3::1;::::0;5189:32:::1;:::i;:::-;;;;;;;;5232:6;:18:::0;;-1:-1:-1;;;;;;5232:18:3::1;-1:-1:-1::0;;;;;5232:18:3;;;::::1;::::0;;;::::1;::::0;;5116:152::o;10520:607:0:-;-1:-1:-1;;;;;10689:17:0;;;10609:15;10689:17;;;:8;:17;;;;;;;;:25;;;;;;;;;;;:33;;;;10609:15;10754:29;10707:6;10754:21;:29::i;:::-;-1:-1:-1;;;;;;;10842:17:0;;;10790:26;10842:17;;;:8;:17;;;;;;;;:25;;;;;;;;;;;:43;;;10729:54;;-1:-1:-1;10790:26:0;10819:67;;10729:54;;10819:22;:67::i;:::-;10790:96;-1:-1:-1;10891:27:0;10921:31;10790:96;10944:7;10921:22;:31::i;:::-;10891:61;-1:-1:-1;10957:21:0;10981:57;3475:7;10981:39;10891:61;3529:8;10981:23;:39::i;:::-;:43;;:57::i;:::-;-1:-1:-1;;;;;11058:17:0;;;;;;;:8;:17;;;;;;;;:25;;;;;;;;;:45;;;10957:81;;-1:-1:-1;11058:64:0;;10957:81;11058:49;:64::i;:::-;11047:75;;10520:607;;;;;;;;:::o;16831:717::-;16935:24;16968:28;;:::i;:::-;17001:14;17020:17;17042:18;17088:1;17069:20;;17094:28;17125:15;;;;;;;;;-1:-1:-1;;;;;17125:15:0;-1:-1:-1;;;;;17125:30:0;;:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;17125:32:0;;;;;;;;;;;;:::i;:::-;17094:63;;17167:9;17162:382;17187:11;:18;17183:1;:22;17162:382;;;17228:11;17240:1;17228:14;;;;;;;;;;;;;;17219:23;;17298:45;17315:7;17324:6;17332:10;17298:16;:45::i;:::-;-1:-1:-1;17274:19:0;;;17253:90;;;;;;17361:43;;17253:90;17361:22;:43::i;:::-;17425:13;;:56;;-1:-1:-1;;;17425:56:0;;17349:55;;-1:-1:-1;;;;;;17425:13:0;;:37;;:56;;17463:6;;17349:55;;17425:56;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;17412:69;-1:-1:-1;17506:32:0;:16;17412:69;17506:20;:32::i;:::-;17487:51;-1:-1:-1;17208:3:0;;17162:382;;;;16831:717;;;;;;;;;:::o;23758:158::-;23819:25;23837:6;23819:17;:25::i;:::-;23849:30;23872:6;23849:22;:30::i;:::-;23884:27;23904:6;23884:19;:27::i;29177:147::-;29261:58;29288:10;29300;29312:6;29261:26;:58::i;39268:226::-;1393:5:2;;-1:-1:-1;;;;;1393:5:2;1379:10;:19;1371:54;;;;-1:-1:-1;;;1371:54:2;;;;;;;:::i;:::-;39437:13:0::1;::::0;39373:79:::1;::::0;::::1;::::0;::::1;::::0;39410:16;;-1:-1:-1;;;;;39437:13:0::1;::::0;39373:79:::1;:::i;:::-;;;;;;;;39457:13;:32:::0;;-1:-1:-1;;;;;;39457:32:0::1;-1:-1:-1::0;;;;;39457:32:0;;;::::1;::::0;;;::::1;::::0;;39268:226::o;30810:182::-;30919:68;30934:10;30946:6;30954:10;30966:6;30974:12;30919:14;:68::i;3283:79::-;-1:-1:-1;;;;;;;;;;;3283:79:0;:::o;33296:165::-;33393:63;33413:7;-1:-1:-1;;;;;;;;;;;33434:10:0;33446:9;33393:19;:63::i;32367:137::-;32433:66;32453:10;-1:-1:-1;;;;;;;;;;;32477:10:0;32489:9;32433:19;:66::i;33687:1939::-;2007:131:3;;;;;;;;;;;;;;;;;2075:19;2084:9;2075:8;:19::i;:::-;2074:20;2066:52;;;;-1:-1:-1;;;2066:52:3;;;;;;;:::i;:::-;33846:28:0::1;;:::i;:::-;33924:46;33941:8;33951:6;33959:10;33924:16;:46::i;:::-;-1:-1:-1::0;33900:19:0::1;::::0;::::1;33879:91:::0;;;;33975:56:::1;;;;-1:-1:-1::0;;;33975:56:0::1;;;;;;;:::i;:::-;34039:25;34066:29:::0;34099:20:::1;34128:42;34149:8;34159:10;34128:20;:42::i;:::-;34038:132;;;;;;;;34184:15;:59;;;;3529:8;34204:21;:38;34184:59;34175:128;;;;-1:-1:-1::0;;;34175:128:0::1;;;;;;;:::i;:::-;34364:19;::::0;::::1;::::0;34341:18;;34310:28:::1;::::0;34341:43:::1;::::0;:18;:22:::1;:43::i;:::-;34425:13;::::0;:67:::1;::::0;-1:-1:-1;;;34425:67:0;;34310:74;;-1:-1:-1;34389:33:0::1;::::0;-1:-1:-1;;;;;34425:13:0;;::::1;::::0;:37:::1;::::0;:67:::1;::::0;34463:6;;34310:74;;34425:67:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;34389:103;;34501:33;34537:113;3475:7;34537:91;34571:15;;;;;;;;;-1:-1:-1::0;;;;;34571:15:0::1;-1:-1:-1::0;;;;;34571:32:0::1;;34604:10;34571:44;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:56;;::::0;34537:25;;:33:::1;:91::i;:113::-;34692:13;::::0;:76:::1;::::0;-1:-1:-1;;;34692:76:0;;34501:149;;-1:-1:-1;34657:28:0::1;::::0;-1:-1:-1;;;;;34692:13:0;;::::1;::::0;:37:::1;::::0;:76:::1;::::0;34730:10;;34501:149;;34692:76:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;34657:111;;34802:17;34779:20;:40;34775:98;;;-1:-1:-1::0;34850:17:0;34775:98:::1;34923:43;:17:::0;34945:20;34923:21:::1;:43::i;:::-;-1:-1:-1::0;;;;;34879:21:0;;::::1;;::::0;;;:11:::1;:21;::::0;;;;;;;:33;;::::1;::::0;;;;;;;;:41:::1;;:87:::0;;;;35022:16:::1;:28:::0;;;;;:44;:70:::1;::::0;35071:20;35022:48:::1;:70::i;:::-;-1:-1:-1::0;;;;;34971:28:0;::::1;;::::0;;;:16:::1;:28;::::0;;;;:121;;;35158:54:::1;;::::0;:80:::1;::::0;35217:20;35158:58:::1;:80::i;:::-;35097:16;:28;35114:10;-1:-1:-1::0;;;;;35097:28:0::1;-1:-1:-1::0;;;;;35097:28:0::1;;;;;;;;;;;;:54;;:141;;;;35252:7;:17;35260:8;-1:-1:-1::0;;;;;35252:17:0::1;-1:-1:-1::0;;;;;35252:17:0::1;;;;;;;;;;;;:29;35270:10;-1:-1:-1::0;;;;;35252:29:0::1;-1:-1:-1::0;;;;;35252:29:0::1;;;;;;;;;;;;:37;35282:6;-1:-1:-1::0;;;;;35252:37:0::1;-1:-1:-1::0;;;;;35252:37:0::1;;;;;;;;;;;;;35245:44;;;;;;;;;;;;;;;;;;;;35294:30;35317:6;35294:22;:30::i;:::-;35401:18:::0;;-1:-1:-1;;;;;35364:20:0;::::1;35401:18;35364:20:::0;;;:12:::1;:20;::::0;;;;:32:::1;;::::0;:56:::1;::::0;:36:::1;:56::i;:::-;-1:-1:-1::0;;;;;35329:20:0;;::::1;;::::0;;;:12:::1;:20;::::0;;;;;;;:32:::1;;:91:::0;;;;35458:22;;::::1;::::0;;:10:::1;:22:::0;;;;;:30;;;;;;;:56:::1;::::0;35493:20;35458:34:::1;:56::i;:::-;35425:10;:22;35436:10;-1:-1:-1::0;;;;;35425:22:0::1;-1:-1:-1::0;;;;;35425:22:0::1;;;;;;;;;;;;:30;35448:6;-1:-1:-1::0;;;;;35425:30:0::1;-1:-1:-1::0;;;;;35425:30:0::1;;;;;;;;;;;;:89;;;;35565:10;-1:-1:-1::0;;;;;35526:94:0::1;35557:6;-1:-1:-1::0;;;;;35526:94:0::1;35547:8;-1:-1:-1::0;;;;;35526:94:0::1;;35577:20;35599;35526:94;;;;;;;:::i;:::-;;;;;;;;2129:1:3;;;;;;;;33687:1939:0::0;;;;:::o;21051:497::-;21228:15;;;:36;;-1:-1:-1;;;21228:36:0;;21134:19;;;;;;-1:-1:-1;;;;;21228:15:0;;;;:28;;:36;;21257:6;;21228:36;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:47;;;;;-1:-1:-1;;;;;21360:20:0;;21318:23;21360:20;;;:12;:20;;;;;:42;;;21228:47;;-1:-1:-1;21298:15:0;;-1:-1:-1;21344:59:0;;21298:15;;21344;:59::i;:::-;21318:85;-1:-1:-1;21410:25:0;21438:31;21318:85;21458:10;21438:19;:31::i;:::-;-1:-1:-1;;;;;21488:20:0;;;;;;:12;:20;;;;;:32;;;21410:59;;-1:-1:-1;21488:55:0;;21410:59;21488:36;:55::i;:::-;21474:69;;21051:497;;;;;;;:::o;16315:244::-;-1:-1:-1;;;;;16499:16:0;;;16473:11;16499:16;;;:7;:16;;;;;;;;:28;;;;;;;;;;;:36;;;;;;;;;;;:55;;;;;;;;;;;;;16315:244::o;4285:55::-;;;;;;;;;;;;;;;;;;;:::o;11746:739::-;-1:-1:-1;;;;;11935:16:0;;;11855:15;11935:16;;;:7;:16;;;;;;;;:28;;;;;;;;;;:36;;;;;;;;;;;:44;;;;11855:15;12011:29;11964:6;12011:21;:29::i;:::-;-1:-1:-1;;;;;;;12103:16:0;;;12047:26;12103:16;;;:7;:16;;;;;;;;:28;;;;;;;;;;:36;;;;;;;;;;;:54;;;11986;;-1:-1:-1;12047:26:0;12080:78;;11986:54;;12080:22;:78::i;:::-;12047:111;-1:-1:-1;12165:27:0;12195:31;12047:111;12218:7;12195:22;:31::i;:::-;12165:61;-1:-1:-1;12231:21:0;12255:57;3475:7;12255:39;12165:61;3529:8;12255:23;:39::i;:57::-;12231:81;-1:-1:-1;12321:11:0;;12317:71;;12356:26;:13;3619:1;12356:17;:26::i;:::-;12340:42;;12317:71;-1:-1:-1;;;;;12405:16:0;;;;;;;:7;:16;;;;;;;;:28;;;;;;;;;;:36;;;;;;;;;:56;;;:75;;12466:13;12405:60;:75::i;:::-;12394:86;;11746:739;;;;;;;;;;:::o;22963:660::-;23117:15;;;:36;;-1:-1:-1;;;23117:36:0;;23036:27;;;;;;-1:-1:-1;;;;;23117:15:0;;;;:28;;:36;;23146:6;;23117:36;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:50;;;-1:-1:-1;;;;;23230:20:0;;;;;;:12;:20;;;;;:40;;;;-1:-1:-1;23188:15:0;;-1:-1:-1;23117:50:0;-1:-1:-1;23281:18:0;;23277:342;;-1:-1:-1;;;;;23347:20:0;;23307:17;23347:20;;;:12;:20;;;;;:48;;;23327:69;;:15;;:19;:69::i;:::-;-1:-1:-1;;;;;23428:20:0;;23402:23;23428:20;;;:12;:20;;;;;:32;23307:89;;-1:-1:-1;23402:23:0;23428:51;;23465:13;23428:36;:51::i;:::-;23402:77;-1:-1:-1;23485:25:0;23513:30;23402:77;23533:9;23513:19;:30::i;:::-;23485:58;-1:-1:-1;23571:42:0;:19;23485:58;23571:23;:42::i;:::-;23549:64;;23277:342;;;;22963:660;;;;:::o;409:50:3:-;452:7;409:50;:::o;24792:129:0:-;24853:63;24868:10;-1:-1:-1;;;;;;;;;;;24892:9:0;24903:12;24853:14;:63::i;3972:43::-;;;-1:-1:-1;;;;;3972:43:0;;:::o;28388:127::-;28457:53;28479:7;-1:-1:-1;;;;;;;;;;;28500:9:0;28457:21;:53::i;25223:196::-;25346:6;-1:-1:-1;;;;;9061:19:0;;-1:-1:-1;;;;;;;;;;;9061:19:0;;9052:64;;;;-1:-1:-1;;;9052:64:0;;;;;;;:::i;:::-;25361:53:::1;25376:7;25385:6;25393;25401:12;25361:14;:53::i;:::-;25223:196:::0;;;;;:::o;24431:176::-;24531:6;-1:-1:-1;;;;;9061:19:0;;-1:-1:-1;;;;;;;;;;;9061:19:0;;9052:64;;;;-1:-1:-1;;;9052:64:0;;;;;;;:::i;:::-;24546:56:::1;24561:10;24573:6;24581;24589:12;24546:14;:56::i;1989:346:2:-:0;2054:12;;-1:-1:-1;;;;;2054:12:2;2045:62;;;;-1:-1:-1;;;2045:62:2;;;;;;;:::i;:::-;2127:12;;-1:-1:-1;;;;;2127:12:2;2143:10;2127:26;2118:75;;;;-1:-1:-1;;;2118:75:2;;;;;;;:::i;:::-;2240:12;;;2254:5;2219:41;;;;;;-1:-1:-1;;;;;2240:12:2;;;;2254:5;;;2219:41;:::i;:::-;;;;;;;;2279:12;;;;2271:20;;-1:-1:-1;;;;;;2271:20:2;;;-1:-1:-1;;;;;2279:12:2;;2271:20;;;;2302:25;;;1989:346::o;17760:1033:0:-;17832:15;17854:14;17873:18;17896:22;17921:1;17896:26;;17929:28;17960:15;;;;;;;;;-1:-1:-1;;;;;17960:15:0;-1:-1:-1;;;;;17960:30:0;;:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;17960:32:0;;;;;;;;;;;;:::i;:::-;17929:63;;18002:9;17997:236;18022:11;:18;18018:1;:22;17997:236;;;18063:11;18075:1;18063:14;;;;;;;;;;;;;;;;;;;18096:13;;-1:-1:-1;;;;;18142:22:0;;;18096:13;18142:22;;;:10;:22;;;;;;:30;;;;;;;;;;;;18096:77;;-1:-1:-1;;;18096:77:0;;18063:14;;-1:-1:-1;18096:13:0;;:37;;:77;;18063:14;;18096:77;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;18083:90;-1:-1:-1;18196:30:0;:14;18083:90;18196:18;:30::i;:::-;18179:47;-1:-1:-1;18043:3:0;;17997:236;;;-1:-1:-1;18259:15:0;;;:44;;-1:-1:-1;;;18259:44:0;;18239:17;;-1:-1:-1;;;;;18259:15:0;;;;:32;;:44;;18292:10;;18259:44;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:54;;;;-1:-1:-1;18318:32:0;18353:47;3475:7;18353:29;:14;18259:54;18353:18;:29::i;:47::-;18442:13;;:88;;-1:-1:-1;;;18442:88:0;;18318:82;;-1:-1:-1;18405:34:0;;-1:-1:-1;;;;;18442:13:0;;;;:37;;:88;;18485:10;;18318:82;;18442:88;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;18591:28:0;;18549:1;18591:28;;;:16;:28;;;;;:54;;;18549:1;;-1:-1:-1;18405:125:0;;-1:-1:-1;18654:54:0;;;18650:139;;;18726:57;:25;18756:26;18726:29;:57::i;:::-;18716:67;;18650:139;17760:1033;;;;;;;;;;;:::o;28774:237::-;28893:7;9887:10;-1:-1:-1;;;;;9887:21:0;;;;9878:55;;;;-1:-1:-1;;;9878:55:0;;;;;;;:::i;:::-;9586:15:::1;::::0;;:44:::1;::::0;-1:-1:-1;;;9586:44:0;;28924:10;;-1:-1:-1;;;;;9586:15:0;;::::1;::::0;:32:::1;::::0;:44:::1;::::0;28924:10;;9586:44:::1;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:53;;;9577:91;;;;-1:-1:-1::0;;;9577:91:0::1;;;;;;;:::i;:::-;-1:-1:-1::0;;28955:10:0::2;28943:23;::::0;;;:11:::2;:23;::::0;;;;;;;-1:-1:-1;;;;;28943:35:0;;::::2;::::0;;;;;;;:54;;;::::2;::::0;;;;;;;;:63;28774:237::o;13482:1318::-;13759:15;;;:44;;-1:-1:-1;;;13759:44:0;;13584:15;;;;;;;;;;;;-1:-1:-1;;;;;13759:15:0;;;;:32;;:44;;13792:10;;13759:44;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:60;;;;-1:-1:-1;13828:20:0;13824:64;;13864:1;13867;13870;13873;13876:5;13856:26;;;;;;;;;;;;;13824:64;-1:-1:-1;;;;;13904:20:0;;;;;;;:11;:20;;;;;;;;:32;;;;;;;;;;;:40;;;13977:13;;:58;;-1:-1:-1;;;13977:58:0;;13904:40;;-1:-1:-1;13904:20:0;;13977:13;;:37;;:58;;13925:10;;13904:40;;13977:58;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;13951:84;-1:-1:-1;14040:32:0;14075:46;:15;3809:3;14075:19;:46::i;:::-;14040:81;-1:-1:-1;14128:29:0;14160:54;14198:15;14160:33;:15;3475:7;14160:19;:33::i;:54::-;14128:86;-1:-1:-1;14219:33:0;14255:63;14293:24;14255:33;:15;3475:7;14255:19;:33::i;:63::-;14219:99;;14344:47;14371:7;14380:10;14344:26;:47::i;:::-;14325:66;-1:-1:-1;14400:20:0;;14396:130;;-1:-1:-1;;;;;14472:20:0;;;;;;;:11;:20;;;;;;;;:32;;;;;;;;;:47;;;14452:68;;:15;;:19;:68::i;:::-;14428:92;;14396:130;14551:1;14532:20;;14580:21;14561:16;:40;14557:120;;;14628:43;:21;14654:16;14628:25;:43::i;:::-;14609:62;;14557:120;14701:5;14683:23;;14735:25;14716:16;:44;14712:84;;;14786:4;14768:22;;14712:84;13482:1318;;;;;;;;;;;;;;:::o;4348:320:3:-;4479:14;:21;4458:10;:17;:42;4449:85;;;;-1:-1:-1;;;4449:85:3;;;;;;;:::i;:::-;4550:9;4545:116;4570:10;:17;4566:1;:21;4545:116;;;4610:39;4616:10;4627:1;4616:13;;;;;;;;;;;;;;4631:14;4646:1;4631:17;;;;;;;;;;;;;;4610:5;:39::i;:::-;4590:3;;4545:116;;21886:753:0;22070:15;;;:36;;-1:-1:-1;;;22070:36:0;;21962:30;;;;;;;;-1:-1:-1;;;;;22070:15:0;;;;:28;;:36;;22099:6;;22070:36;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;;22176:20:0;;22148:25;22176:20;;;:12;:20;;;;;:32;22125:15;;-1:-1:-1;22022:84:0;;-1:-1:-1;22022:84:0;;-1:-1:-1;22148:25:0;22176:52;;22022:84;22176:36;:52::i;:::-;-1:-1:-1;;;;;22261:20:0;;22233:25;22261:20;;;:12;:20;;;;;:32;;;22148:80;;-1:-1:-1;22233:25:0;22261:48;;22298:10;22261:36;:48::i;:::-;-1:-1:-1;;;;;22352:20:0;;22316:17;22352:20;;;:12;:20;;;;;;;:51;;22233:76;;-1:-1:-1;22316:17:0;22336:68;;:11;;:15;:68::i;:::-;22316:88;-1:-1:-1;22409:23:0;22435:40;:17;22457;22435:21;:40::i;:::-;22409:66;-1:-1:-1;22480:25:0;22508:30;22409:66;22528:9;22508:19;:30::i;:::-;-1:-1:-1;;;;;22568:20:0;;;;;;:12;:20;;;;;:43;;;22480:58;;-1:-1:-1;22568:66:0;;22480:58;22568:47;:66::i;:::-;22543:91;;21886:753;;;;;;;;;;:::o;722:20:2:-;;;-1:-1:-1;;;;;722:20:2;;:::o;37924:164:0:-;38021:6;-1:-1:-1;;;;;9061:19:0;;-1:-1:-1;;;;;;;;;;;9061:19:0;;9052:64;;;;-1:-1:-1;;;9052:64:0;;;;;;;:::i;:::-;38036:47:::1;38068:6;38076;38036:31;:47::i;31336:442::-:0;-1:-1:-1;;;;;31488:16:0;;;31468:17;31488:16;;;:7;:16;;;;;;;;:28;;;;;;;;;;:36;;;;;;;;;;;31535:10;31488:58;;;;;;31564:19;;;;31551:65;;;;-1:-1:-1;;;31551:65:0;;;;;;;:::i;:::-;31682:21;:9;31696:6;31682:13;:21::i;:::-;-1:-1:-1;;;;;31621:16:0;;;;;;;:7;:16;;;;;;;;:28;;;;;;;;;;:36;;;;;;;;;;;31668:10;31621:58;;;;;:82;31708:65;31629:7;31650:6;31638:10;31752:6;31760:12;31708:14;:65::i;:::-;31336:442;;;;;;:::o;39599:808::-;39687:15;;-1:-1:-1;;;;;39687:15:0;39665:10;:38;39657:93;;;;-1:-1:-1;;;39657:93:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;39784:20:0;;39757:24;39784:20;;;:12;:20;;;;;:43;;;;39856:40;;;;;39909:32;;;39901:73;;;;-1:-1:-1;;;39901:73:0;;;;;;;:::i;:::-;40002:35;:16;40023:13;40002:20;:35::i;:::-;-1:-1:-1;;;;;40042:20:0;;;;;;:12;:20;;;;;;;;:43;;;:62;;;40109:40;;;:44;;;;40214:15;40160:51;;;:69;;;40234:48;;;;:66;40312:49;39983:54;;-1:-1:-1;40042:20:0;40312:49;;;;39983:54;;40312:49;:::i;:::-;;;;;;;;40392:6;-1:-1:-1;;;;;40371:31:0;;40400:1;40371:31;;;;;;:::i;:::-;;;;;;;;39599:808;;;:::o;27990:188::-;28104:10;-1:-1:-1;;;;;9061:19:0;;-1:-1:-1;;;;;;;;;;;9061:19:0;;9052:64;;;;-1:-1:-1;;;9052:64:0;;;;;;;:::i;:::-;28123:50:::1;28145:7;28154:10;28166:6;28123:21;:50::i;36919:120::-:0;36978:56;-1:-1:-1;;;;;;;;;;;37024:9:0;36978:33;:56::i;647:21:3:-;;;-1:-1:-1;;;;;647:21:3;;:::o;4169:47:0:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;19182:517::-;19377:13;;:59;;-1:-1:-1;;;19377:59:0;;19310:36;;;;-1:-1:-1;;;;;19377:13:0;;;;:37;;:59;;19415:6;;19423:12;;19377:59;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;19461:15;;;:44;;-1:-1:-1;;;19461:44:0;;19355:81;;-1:-1:-1;19441:17:0;;-1:-1:-1;;;;;19461:15:0;;;;:32;;:44;;19494:10;;19461:44;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:54;;;;-1:-1:-1;19520:23:0;19546:44;3475:7;19546:26;:11;19461:54;19546:15;:26::i;:44::-;19628:13;;:66;;-1:-1:-1;;;19628:66:0;;19520:70;;-1:-1:-1;;;;;;19628:13:0;;:37;;:66;;19666:10;;19520:70;;19628:66;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;19597:97;19182:517;-1:-1:-1;;;;;;;19182:517:0:o;2862:236:3:-;2926:8;2969:6;2976:9;2969:17;;;;;;:::i;:::-;;;;;;;;;;;;;:30;;;2951:15;:48;2947:144;;;-1:-1:-1;3022:5:3;2947:144;;;-1:-1:-1;3075:4:3;2947:144;2862:236;;;:::o;37215:547:0:-;1393:5:2;;-1:-1:-1;;;;;1393:5:2;1379:10;:19;1371:54;;;;-1:-1:-1;;;1371:54:2;;;;;;;:::i;:::-;37312:19:0::1;37334:33;37356:10;37334:21;:33::i;:::-;37312:55:::0;-1:-1:-1;37397:6:0;37416:28;;::::1;37412:73;;;-1:-1:-1::0;37468:11:0;37412:73:::1;-1:-1:-1::0;;;;;37552:28:0;::::1;;::::0;;;:16:::1;:28;::::0;;;;:54:::1;;::::0;:74:::1;::::0;37611:14;37552:58:::1;:74::i;:::-;-1:-1:-1::0;;;;;37491:28:0;;::::1;;::::0;;;:16:::1;:28;::::0;;;;;;:54:::1;;:135:::0;;;;37631:18:::1;::::0;:67;;-1:-1:-1;;;37631:67:0;;:18;::::1;::::0;:27:::1;::::0;:67:::1;::::0;37508:10;;37671::::1;::::0;37683:14;;37631:67:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;37738:10;-1:-1:-1::0;;;;;37710:47:0::1;;37750:6;37710:47;;;;;;:::i;:::-;;;;;;;;1436:1:2;;37215:547:0::0;;:::o;15655:232::-;-1:-1:-1;;;;;15831:20:0;;;15805:11;15831:20;;;:11;:20;;;;;;;;:32;;;;;;;;;;;:51;;;;;;;;;;;;;15655:232::o;3871:47::-;;;-1:-1:-1;;;;;3871:47:0;;:::o;24066:128::-;24129:25;24147:6;24129:17;:25::i;:::-;24159:30;24182:6;24159:22;:30::i;26106:213::-;26216:7;9887:10;-1:-1:-1;;;;;9887:21:0;;;;9878:55;;;;-1:-1:-1;;;9878:55:0;;;;;;;:::i;:::-;9306:15:::1;::::0;;:36:::1;::::0;-1:-1:-1;;;9306:36:0;;26243:6;;-1:-1:-1;;;;;9306:15:0;;::::1;::::0;:28:::1;::::0;:36:::1;::::0;26243:6;;9306:36:::1;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:45;;;9297:79;;;;-1:-1:-1::0;;;9297:79:0::1;;;;;;;:::i;:::-;-1:-1:-1::0;;26267:10:0::2;26258:20;::::0;;;:8:::2;:20;::::0;;;;;;;-1:-1:-1;;;;;26258:28:0;;::::2;::::0;;;;;;;:47;;;::::2;::::0;;;;;;;;:56;26106:213::o;3313:395:3:-;1772:5;;-1:-1:-1;;;;;1772:5:3;1758:10;:19;;:43;;-1:-1:-1;1795:6:3;;-1:-1:-1;;;;;1795:6:3;1781:10;:20;1758:43;1750:89;;;;-1:-1:-1;;;1750:89:3;;;;;;;:::i;:::-;3439:9:::1;2616:6;2623:9;2616:17;;;;;;:::i;:::-;::::0;;;::::1;::::0;;;;;::::1;::::0;;;:25;::::1;;2608:60;;;;-1:-1:-1::0;;;2608:60:3::1;;;;;;;:::i;:::-;3473:9:::2;2075:19;2084:9;2075:8;:19::i;:::-;2074:20;2066:52;;;;-1:-1:-1::0;;;2066:52:3::2;;;;;;;:::i;:::-;452:7:::3;3509:13;:33;;3500:68;;;;-1:-1:-1::0;;;3500:68:3::3;;;;;;;:::i;:::-;3630:13;3612:15;:31;3579:6;3586:9;3579:17;;;;;;:::i;:::-;;;;;;;;;;;;;:30;;:64;;;;3659:41;3675:9;3686:13;3659:41;;;;;;;:::i;:::-;;;;;;;;2679:1:::2;1850::::1;3313:395:::0;;:::o;35900:208:0:-;36023:6;-1:-1:-1;;;;;9061:19:0;;-1:-1:-1;;;;;;;;;;;9061:19:0;;9052:64;;;;-1:-1:-1;;;9052:64:0;;;;;;;:::i;:::-;36038:65:::1;36070:6;36078:10;36090:12;36038:31;:65::i;38488:640::-:0;1393:5:2;;-1:-1:-1;;;;;1393:5:2;1379:10;:19;1371:54;;;;-1:-1:-1;;;1371:54:2;;;;;;;:::i;:::-;38583:21:0::1;38609:27;38629:6;38609:19;:27::i;:::-;38582:54;;;38645:18;38668:24;38685:6;38668:16;:24::i;:::-;-1:-1:-1::0;38644:48:0;-1:-1:-1;38702:20:0::1;38725:44;3475:7;38725:26;:6:::0;3529:8:::1;38725:10;:26::i;:::-;:30:::0;::::1;:44::i;:::-;38702:67:::0;-1:-1:-1;38777:27:0::1;38807:28;38702:67:::0;38824:10;38807:16:::1;:28::i;:::-;38777:58;;38868:19;38852:13;:35;38843:79;;;;-1:-1:-1::0;;;38843:79:0::1;;;;;;;:::i;:::-;38978:31;:13:::0;38996:12;38978:17:::1;:31::i;:::-;-1:-1:-1::0;;;;;38932:20:0;::::1;;::::0;;;:12:::1;:20;::::0;;;;:43:::1;;:77:::0;39019:47:::1;39039:10;38945:6:::0;39059;39019:19:::1;:47::i;:::-;39107:6;-1:-1:-1::0;;;;;39081:41:0::1;;39115:6;39081:41;;;;;;:::i;:::-;;;;;;;;1436:1:2;;;;38488:640:0::0;;:::o;749:27:2:-;;;-1:-1:-1;;;;;749:27:2;;:::o;26485:130:0:-;26560:50;26583:10;26595:6;26603;26560:22;:50::i;3846:247:3:-;1393:5:2;;-1:-1:-1;;;;;1393:5:2;1379:10;:19;1371:54;;;;-1:-1:-1;;;1371:54:2;;;;;;;:::i;:::-;3949:9:3::1;2616:6;2623:9;2616:17;;;;;;:::i;:::-;::::0;;;::::1;::::0;;;;;::::1;::::0;;;:25;::::1;;2608:60;;;;-1:-1:-1::0;;;2608:60:3::1;;;;;;;:::i;:::-;3980:9:::2;2342:19;2351:9;2342:8;:19::i;:::-;2334:53;;;;-1:-1:-1::0;;;2334:53:3::2;;;;;;;:::i;:::-;4040:1:::3;4007:6;4014:9;4007:17;;;;;;:::i;:::-;;;;;;;;;;;;;:30;;:34;;;;4057:28;4075:9;4057:28;;;;;;:::i;:::-;;;;;;;;2679:1:::2;1436::2::1;3846:247:3::0;:::o;4831:176::-;4906:9;4901:99;4926:10;:17;4922:1;:21;4901:99;;;4966:22;4974:10;4985:1;4974:13;;;;;;;;;;;;;;4966:7;:22::i;:::-;4946:3;;4901:99;;29561:399:0;-1:-1:-1;;;;;29688:20:0;;;29668:17;29688:20;;;:11;:20;;;;;;;;:32;;;;;;;;;;;29731:10;29688:54;;;;;;29760:19;;;;29747:65;;;;-1:-1:-1;;;29747:65:0;;;;;;;:::i;:::-;29874:21;:9;29888:6;29874:13;:21::i;:::-;-1:-1:-1;;;;;29817:20:0;;;;;;;:11;:20;;;;;;;;:32;;;;;;;;;;;29860:10;29817:54;;;;;:78;29900:55;29829:7;29838:10;29948:6;29900:26;:55::i;27647:109::-;27695:56;27717:10;-1:-1:-1;;;;;;;;;;;27741:9:0;27695:21;:56::i;1621:239:2:-;1393:5;;-1:-1:-1;;;;;1393:5:2;1379:10;:19;1371:54;;;;-1:-1:-1;;;1371:54:2;;;;;;;:::i;:::-;-1:-1:-1;;;;;1704:22:2;::::1;1696:68;;;;-1:-1:-1::0;;;1696:68:2::1;;;;;;;:::i;:::-;1775:12;:23:::0;;-1:-1:-1;;;;;;1775:23:2::1;-1:-1:-1::0;;;;;1775:23:2;::::1;;::::0;;1816:36:::1;::::0;::::1;::::0;::::1;::::0;1775:23;;1816:36:::1;:::i;:::-;;;;;;;;1621:239:::0;:::o;32815:204:0:-;32943:6;-1:-1:-1;;;;;9061:19:0;;-1:-1:-1;;;;;;;;;;;9061:19:0;;9052:64;;;;-1:-1:-1;;;9052:64:0;;;;;;;:::i;:::-;32958:56:::1;32978:7;32987:6;32995:10;33007:6;49437:1773:::0;2007:131:3;;;;;;;;;;;;;-1:-1:-1;;;2007:131:3;;;2075:19;2084:9;2075:8;:19::i;:::-;2074:20;2066:52;;;;-1:-1:-1;;;2066:52:3;;;;;;;:::i;:::-;49587:28:0::1;;:::i;:::-;49693:45;49710:7;49719:6;49727:10;49693:16;:45::i;:::-;49662:23;::::0;::::1;49620:118:::0;49641:19:::1;::::0;::::1;49620:118:::0;;;;;;49621:18:::1;::::0;49776:43:::1;::::0;:22:::1;:43::i;:::-;49745:74:::0;-1:-1:-1;49833:25:0;49824:71:::1;;;;-1:-1:-1::0;;;49824:71:0::1;;;;;;;:::i;:::-;49927:6:::0;49942:37;;::::1;49938:236;;;-1:-1:-1::0;50004:20:0;-1:-1:-1;;;;;50034:20:0;::::1;-1:-1:-1::0;;;;;;;;;;;50034:20:0::1;50030:139;;;50063:13;50079:26;:6:::0;50090:14;50079:10:::1;:26::i;:::-;50063:42;;50112:50;50132:10;-1:-1:-1::0;;;;;;;;;;;50156:5:0::1;50112:19;:50::i;:::-;50030:139;;-1:-1:-1::0;;;;;50186:20:0;::::1;-1:-1:-1::0;;;;;;;;;;;50186:20:0::1;50182:94;;50214:56;50240:4;50247:6;50255:14;50214:17;:56::i;:::-;50282:17;50330:10;:19;;;50312:14;:37;50308:277;;50379:19;::::0;::::1;::::0;:39:::1;::::0;50403:14;50379:23:::1;:39::i;:::-;50357:19;::::0;::::1;:61:::0;50308:277:::1;;;50470:19;::::0;::::1;::::0;50451:39:::1;::::0;:14;;:18:::1;:39::i;:::-;50518:1;50496:19;::::0;::::1;:23:::0;50546:18;;50439:51;;-1:-1:-1;50546:33:0::1;::::0;50439:51;50546:22:::1;:33::i;:::-;50525:54:::0;;50308:277:::1;50636:18:::0;;-1:-1:-1;;;;;50589:16:0;;::::1;50636:18;50589:16:::0;;;:7:::1;:16;::::0;;;;;;;:28;;::::1;::::0;;;;;;;;;:36;;::::1;::::0;;;;;;;;:44:::1;::::0;::::1;:65:::0;;;;50718:19;;::::1;::::0;50659:56:::1;::::0;;::::1;:78:::0;;;;50799:23;;::::1;::::0;50742:54:::1;::::0;;::::1;:80:::0;;;;50827:20;;;:11:::1;:20:::0;;;;;:32;;;;;;;;;50877:15:::1;50827:47:::0;::::1;:65:::0;50899:30:::1;50589:36:::0;50899:22:::1;:30::i;:::-;-1:-1:-1::0;;;;;50973:20:0;::::1;;::::0;;;:12:::1;:20;::::0;;;;:32:::1;;::::0;:47:::1;::::0;51010:9;50973:36:::1;:47::i;:::-;-1:-1:-1::0;;;;;50938:20:0;;::::1;;::::0;;;:12:::1;:20;::::0;;;;;;;;:32:::1;;:82:::0;;;;51128:18;;51152:19;;::::1;::::0;51177:23;;::::1;::::0;51033:172;;;;::::1;::::0;50938:20;;51033:172;::::1;::::0;::::1;::::0;::::1;::::0;51051:10:::1;::::0;51108:14;;51128:18;51177:23;51033:172:::1;:::i;:::-;;;;;;;;2129:1:3;;;;49437:1773:0::0;;;;;:::o;45661:763::-;2007:131:3;;;;;;;;;;;;;-1:-1:-1;;;2007:131:3;;;2075:19;2084:9;2075:8;:19::i;:::-;2074:20;2066:52;;;;-1:-1:-1;;;2066:52:3;;;;;;;:::i;:::-;9586:15:0::1;::::0;;:44:::1;::::0;-1:-1:-1;;;9586:44:0;;45814:10;;-1:-1:-1;;;;;9586:15:0;;::::1;::::0;:32:::1;::::0;:44:::1;::::0;45814:10;;9586:44:::1;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:53;;;9577:91;;;;-1:-1:-1::0;;;9577:91:0::1;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;45837:24:0;::::2;-1:-1:-1::0;;;;;;;;;;;45837:24:0::2;45833:197;;45895:18;::::0;45869:66:::2;::::0;-1:-1:-1;;;;;45895:18:0::2;45916:10:::0;45928:6;45869:17:::2;:66::i;:::-;45833:197;;;45984:18;::::0;45956:68:::2;::::0;-1:-1:-1;;;;;45984:18:0::2;46005:10:::0;46017:6;45956:19:::2;:68::i;:::-;-1:-1:-1::0;;;;;46054:20:0;;::::2;46036:15;46054:20:::0;;;:11:::2;:20;::::0;;;;;;;:32;;::::2;::::0;;;;;;;;:40:::2;;::::0;:52:::2;::::0;46099:6;46054:44:::2;:52::i;:::-;-1:-1:-1::0;;;;;46111:20:0;;::::2;;::::0;;;:11:::2;:20;::::0;;;;;;;:32;;::::2;::::0;;;;;;;;:40:::2;::::0;::::2;:50:::0;;;46216:15:::2;46166:47;::::0;;::::2;:65:::0;46285:16:::2;:28:::0;;;:44;46111:50;;-1:-1:-1;46285:56:0::2;::::0;46334:6;46285:48:::2;:56::i;:::-;-1:-1:-1::0;;;;;46238:28:0;;::::2;;::::0;;;:16:::2;:28;::::0;;;;;;:103;;;;46356:63;;;;::::2;::::0;::::2;::::0;::::2;::::0;46370:10:::2;::::0;46403:6;;46411:7;;46356:63:::2;:::i;:::-;;;;;;;;9679:1;2129::3::1;45661:763:0::0;;;;:::o;51273:1152::-;2007:131:3;;;;;;;;;;;;;;;;;2075:19;2084:9;2075:8;:19::i;:::-;2074:20;2066:52;;;;-1:-1:-1;;;2066:52:3;;;;;;;:::i;:::-;-1:-1:-1;;;;;51451:22:0;;::::1;51436:12;51451:22:::0;;;:10:::1;:22;::::0;;;;;;;:30;;::::1;::::0;;;;;;;51495:20;;::::1;;51486:92;;;;-1:-1:-1::0;;;51486:92:0::1;;;;;;;:::i;:::-;51585:36;51628:63;51658:6;51666:10;51678:12;51628:29;:63::i;:::-;-1:-1:-1::0;;;;;51734:28:0;::::1;51698:33;51734:28:::0;;;:16:::1;:28;::::0;;;;:54:::1;;::::0;51585:106;;-1:-1:-1;51807:57:0;;::::1;;51793:159;;;;-1:-1:-1::0;;;51793:159:0::1;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;51963:20:0;::::1;-1:-1:-1::0;;;;;;;;;;;51963:20:0::1;51959:92;;51991:54;52017:4;52024:6;52032:12;51991:17;:54::i;:::-;52114:59;:25:::0;52144:28;52114:29:::1;:59::i;:::-;-1:-1:-1::0;;;;;52057:28:0;::::1;;::::0;;;:16:::1;:28;::::0;;;;:54:::1;;:116:::0;52211:22:::1;:4:::0;52220:12;52211:8:::1;:22::i;:::-;-1:-1:-1::0;;;;;52178:22:0;;::::1;;::::0;;;:10:::1;:22;::::0;;;;;;;:30;;::::1;::::0;;;;;;;;;:55;;;;52240:18:::1;::::0;:81;;-1:-1:-1;;;52240:81:0;;:18;::::1;::::0;:27:::1;::::0;:81:::1;::::0;52189:10;;52280::::1;::::0;52292:28;;52240:81:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;52365:10;-1:-1:-1::0;;;;;52333:87:0::1;52357:6;-1:-1:-1::0;;;;;52333:87:0::1;;52377:12;52391:28;52333:87;;;;;;;:::i;:::-;;;;;;;;2129:1:3;;;51273:1152:0::0;;;;:::o;43152:960::-;2007:131:3;;;;;;;;;;;;;-1:-1:-1;;;2007:131:3;;;2075:19;2084:9;2075:8;:19::i;:::-;2074:20;2066:52;;;;-1:-1:-1;;;2066:52:3;;;;;;;:::i;:::-;9306:15:0::1;::::0;;:36:::1;::::0;-1:-1:-1;;;9306:36:0;;43303:6;;-1:-1:-1;;;;;9306:15:0;;::::1;::::0;:28:::1;::::0;:36:::1;::::0;43303:6;;9306:36:::1;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:45;;;9297:79;;;;-1:-1:-1::0;;;9297:79:0::1;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;43322:20:0;::::2;-1:-1:-1::0;;;;;;;;;;;43322:20:0::2;43318:86;;43350:48;43376:4;43383:6;43391;43350:17;:48::i;:::-;43410:28;;:::i;:::-;43512:33;43529:7;43538:6;43512:16;:33::i;:::-;43485:23;::::0;::::2;43443:102:::0;43464:19:::2;::::0;::::2;43443:102:::0;;;;43575:30:::2;::::0;43598:6;43575:22:::2;:30::i;:::-;43554:51:::0;;;-1:-1:-1;;;;;43610:17:0;;::::2;43554:18;43610:17:::0;;;:8:::2;:17;::::0;;;;;;;:25;;::::2;::::0;;;;;;;;;:33:::2;::::0;::::2;:54:::0;;;;43717:19;::::2;::::0;43669:45:::2;::::0;::::2;:67:::0;43787:23;::::2;::::0;43741:43:::2;::::0;;::::2;:69:::0;43817:30:::2;43610:25:::0;43817:22:::2;:30::i;:::-;-1:-1:-1::0;;;;;43891:20:0;::::2;;::::0;;;:12:::2;:20;::::0;;;;:32;:44:::2;::::0;43928:6;43891:36:::2;:44::i;:::-;-1:-1:-1::0;;;;;43856:20:0;;::::2;;::::0;;;:12:::2;:20;::::0;;;;;;;;:79;;;;44012:18;;44036:19;;::::2;::::0;44061:23;;::::2;::::0;43947:160;;43856:20;;43947:160;;::::2;::::0;::::2;::::0;::::2;::::0;43959:10:::2;::::0;44000:6;;44012:18;44036:19;;44061:23;44090:12;;43947:160:::2;:::i;53006:533::-:0;9586:15;;;:44;;-1:-1:-1;;;9586:44:0;;-1:-1:-1;;;;;;;;;;;3320:42:0;-1:-1:-1;;;;;9586:15:0;;;;:32;;:44;;3320:42;;9586:44;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:53;;;9577:91;;;;-1:-1:-1;;;9577:91:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;53143:24:0;::::1;-1:-1:-1::0;;;;;;;;;;;53143:24:0::1;53139:197;;53201:18;::::0;53175:66:::1;::::0;-1:-1:-1;;;;;53201:18:0::1;53222:10:::0;53234:6;53175:17:::1;:66::i;:::-;53139:197;;;53290:18;::::0;53262:68:::1;::::0;-1:-1:-1;;;;;53290:18:0::1;53311:10:::0;53323:6;53262:19:::1;:68::i;:::-;-1:-1:-1::0;;;;;;;;;;;53401:28:0::1;::::0;:16:::1;:28;::::0;:54;;:69:::1;::::0;53460:9:::1;53401:58;:69::i;:::-;-1:-1:-1::0;;;;;;;;;;;53340:28:0::1;::::0;;;:16:::1;:28;::::0;:54;:130;;;;:28;53484:50;::::1;::::0;::::1;::::0;53524:9:::1;::::0;53484:50:::1;:::i;52488:453::-:0;9306:15;;;:36;;-1:-1:-1;;;9306:36:0;;52592:6;;-1:-1:-1;;;;;9306:15:0;;;;:28;;:36;;52592:6;;9306:36;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:45;;;9297:79;;;;-1:-1:-1;;;9297:79:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;52611:20:0;::::1;-1:-1:-1::0;;;;;;;;;;;52611:20:0::1;52607:86;;52639:48;52665:4;52672:6;52680;52639:17;:48::i;:::-;52697:20;52720:44;3475:7;52720:26;:6:::0;3529:8:::1;52720:10;:26::i;:44::-;-1:-1:-1::0;;;;;52822:20:0;::::1;;::::0;;;:12:::1;:20;::::0;;;;:43:::1;;::::0;52697:67;;-1:-1:-1;52822:61:0::1;::::0;52697:67;52822:47:::1;:61::i;:::-;-1:-1:-1::0;;;;;52771:20:0;::::1;;::::0;;;:12:::1;:20;::::0;;;;;;:43:::1;;:112:::0;;;;52895:41;;::::1;::::0;::::1;::::0;52929:6;;52895:41:::1;:::i;1367:136:5:-:0;1425:7;1452:43;1456:1;1459;1452:43;;;;;;;;;;;;;;;;;:3;:43::i;:::-;1445:50;;1367:136;;;;;:::o;903:181::-;961:7;993:5;;;1017:6;;;;1009:46;;;;-1:-1:-1;;;1009:46:5;;;;;;;:::i;2257:471::-;2315:7;2560:6;2556:47;;-1:-1:-1;2590:1:5;2583:8;;2556:47;2627:5;;;2631:1;2627;:5;:1;2651:5;;;;;:10;2643:56;;;;-1:-1:-1;;;2643:56:5;;;;;;;:::i;44165:1445:0:-;2007:131:3;;;;;;;;;;;;;-1:-1:-1;;;2007:131:3;;;2075:19;2084:9;2075:8;:19::i;:::-;2074:20;2066:52;;;;-1:-1:-1;;;2066:52:3;;;;;;;:::i;:::-;44302:28:0::1;;:::i;:::-;44404:33;44421:7;44430:6;44404:16;:33::i;:::-;44377:23;::::0;::::1;44335:102:::0;44356:19:::1;::::0;::::1;44335:102:::0;;;;;;44336:18:::1;::::0;44473:43:::1;::::0;:22:::1;:43::i;:::-;44442:74:::0;-1:-1:-1;44530:25:0;44521:71:::1;;;;-1:-1:-1::0;;;44521:71:0::1;;;;;;;:::i;:::-;44624:6:::0;44639:37;;::::1;44635:91;;;-1:-1:-1::0;44700:20:0;44635:91:::1;44732:17;44780:10;:19;;;44762:14;:37;44758:277;;44829:19;::::0;::::1;::::0;:39:::1;::::0;44853:14;44829:23:::1;:39::i;:::-;44807:19;::::0;::::1;:61:::0;44758:277:::1;;;44920:19;::::0;::::1;::::0;44901:39:::1;::::0;:14;;:18:::1;:39::i;:::-;44968:1;44946:19;::::0;::::1;:23:::0;44996:18;;44889:51;;-1:-1:-1;44996:33:0::1;::::0;44889:51;44996:22:::1;:33::i;:::-;44975:54:::0;;44758:277:::1;45077:18:::0;;-1:-1:-1;;;;;45041:17:0;;::::1;45077:18;45041:17:::0;;;:8:::1;:17;::::0;;;;;;;:25;;::::1;::::0;;;;;;;;;:33:::1;::::0;::::1;:54:::0;;;;45148:19;::::1;::::0;45100:45:::1;::::0;::::1;:67:::0;45218:23;::::1;::::0;45172:43:::1;::::0;;::::1;:69:::0;45248:30:::1;45041:25:::0;45248:22:::1;:30::i;:::-;-1:-1:-1::0;;;;;45322:20:0;::::1;;::::0;;;:12:::1;:20;::::0;;;;:32;:47:::1;::::0;45359:9;45322:36:::1;:47::i;:::-;-1:-1:-1::0;;;;;45287:20:0;::::1;;::::0;;;:12:::1;:20;::::0;;;;:82;45379:55:::1;45399:10;45300:6:::0;45419:14;45379:19:::1;:55::i;:::-;45496:6;-1:-1:-1::0;;;;;45447:158:0::1;45483:7;-1:-1:-1::0;;;;;45447:158:0::1;;45467:10;45508:14;45528:10;:18;;;45552:10;:19;;;45577:10;:23;;;45447:158;;;;;;;;;;:::i;:::-;;;;;;;;2129:1:3;;;;44165:1445:0::0;;;;:::o;3204:132:5:-;3262:7;3289:39;3293:1;3296;3289:39;;;;;;;;;;;;;;;;;:3;:39::i;40506:358:0:-;40565:26;40593:18;40613:19;40640:29;40662:6;40640:21;:29::i;:::-;-1:-1:-1;;;;;40676:20:0;;;;;;:12;:20;;;;;;;:32;;;:53;;;40734:42;;:56;;;40802:57;40564:105;;-1:-1:-1;40564:105:0;;-1:-1:-1;40564:105:0;-1:-1:-1;40676:20:0;40802:57;;;;40564:105;;;;40802:57;:::i;41390:319::-;41453:21;41479:27;41499:6;41479:19;:27::i;:::-;-1:-1:-1;;;;;;41513:20:0;;;;;;:12;:20;;;;;;;;;:43;;;:59;;;41631:15;41577:51;;:69;41658:46;41452:54;;-1:-1:-1;41513:20:0;41658:46;;;;41452:54;;41658:46;:::i;:::-;;;;;;;;41390:319;;:::o;41892:523::-;41955:18;41978:24;41995:6;41978:16;:24::i;:::-;-1:-1:-1;;;;;;42014:20:0;;;;;;:12;:20;;;;;:40;;;41954:48;;-1:-1:-1;42014:54:0;;42010:267;;-1:-1:-1;;;;;42080:20:0;;;;;;:12;:20;;;;;;;:40;;;:53;;;42195:15;42144:48;;;;:66;42228:40;;;;;42123:10;;42228:40;:::i;:::-;;;;;;;;42010:267;-1:-1:-1;;;;;42288:20:0;;;;;;:12;:20;;;;;:43;;;:57;-1:-1:-1;42284:125:0;;42358:15;;;:42;;-1:-1:-1;;;42358:42:0;;-1:-1:-1;;;;;42358:15:0;;;;:34;;:42;;42393:6;;42358:42;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;46481:1320;2007:131:3;;;;;;;;;;;;;-1:-1:-1;;;2007:131:3;;;2075:19;2084:9;2075:8;:19::i;:::-;2074:20;2066:52;;;;-1:-1:-1;;;2066:52:3;;;;;;;:::i;:::-;46631:15:0::1;46649:24:::0;46675::::1;46708:41;46729:7;46738:10;46708:20;:41::i;:::-;46630:119;;;;;;;;46765:16;46785:1;46765:21;;46756:66;;;;-1:-1:-1::0;;;46756:66:0::1;;;;;;;:::i;:::-;46829:24;46866:21:::0;;46862:313:::1;;46921:15;::::0;;:44:::1;::::0;-1:-1:-1;;;46921:44:0;;46895:23:::1;::::0;-1:-1:-1;;;;;46921:15:0;;::::1;::::0;:32:::1;::::0;:44:::1;::::0;46954:10;;46921:44:::1;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:60;;::::0;;-1:-1:-1;46987:28:0::1;47018:55;3475:7;47018:37;:16:::0;46921:60;47018:20:::1;:37::i;:55::-;47098:13;::::0;:71:::1;::::0;-1:-1:-1;;;47098:71:0;;46987:86;;-1:-1:-1;;;;;;47098:13:0::1;::::0;:37:::1;::::0;:71:::1;::::0;47136:10;;46987:86;;47098:71:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;47079:90;;46862:313;;;47181:19;47203:29;:7:::0;47215:16;47203:11:::1;:29::i;:::-;47181:51:::0;-1:-1:-1;47262:6:0;47277:28;;::::1;47273:73;;;-1:-1:-1::0;47329:11:0;47273:73:::1;47360:27;:7:::0;47372:14;47360:11:::1;:27::i;:::-;-1:-1:-1::0;;;;;47392:20:0;;::::1;;::::0;;;:11:::1;:20;::::0;;;;;;;:32;;::::1;::::0;;;;;;;;:40:::1;::::0;::::1;:50:::0;;;47497:15:::1;47447:47;::::0;;::::1;:65:::0;47570:16:::1;:28:::0;;;:44;47392:50;;-1:-1:-1;47570:64:0::1;::::0;47619:14;47570:48:::1;:64::i;:::-;-1:-1:-1::0;;;;;47519:28:0;;::::1;;::::0;;;:16:::1;:28;::::0;;;;;;:115;;;;47641:18:::1;::::0;:67;;-1:-1:-1;;;47641:67:0;;:18;::::1;::::0;:27:::1;::::0;:67:::1;::::0;47536:10;;47681::::1;::::0;47693:14;;47641:67:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;47760:10;-1:-1:-1::0;;;;;47720:76:0::1;47751:7;-1:-1:-1::0;;;;;47720:76:0::1;;47739:10;47772:14;47788:7;47720:76;;;;;;;;:::i;:::-;;;;;;;;2129:1:3;;;;;;46481:1320:0::0;;;;:::o;47845:1542::-;2007:131:3;;;;;;;;;;;;;-1:-1:-1;;;2007:131:3;;;2075:19;2084:9;2075:8;:19::i;:::-;2074:20;2066:52;;;;-1:-1:-1;;;2066:52:3;;;;;;;:::i;:::-;9306:15:0::1;::::0;;:36:::1;::::0;-1:-1:-1;;;9306:36:0;;48017:6;;-1:-1:-1;;;;;9306:15:0;;::::1;::::0;:28:::1;::::0;:36:::1;::::0;48017:6;;9306:36:::1;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:45;;;9297:79;;;;-1:-1:-1::0;;;9297:79:0::1;;;;;;;:::i;:::-;9586:15:::2;::::0;;:44:::2;::::0;-1:-1:-1;;;9586:44:0;;48047:10;;-1:-1:-1;;;;;9586:15:0;;::::2;::::0;:32:::2;::::0;:44:::2;::::0;48047:10;;9586:44:::2;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:53;;;9577:91;;;;-1:-1:-1::0;;;9577:91:0::2;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;48128:20:0;::::3;;::::0;;;:12:::3;:20;::::0;;;;:32:::3;::::0;::::3;::::0;48091;;:70:::3;::::0;:36:::3;:70::i;:::-;48080:6;:82;;48066:140;;;;-1:-1:-1::0;;;48066:140:0::3;;;;;;;:::i;:::-;48217:24;48247:41;48268:7;48277:10;48247:20;:41::i;:::-;-1:-1:-1::0;;48322:13:0::3;::::0;:53:::3;::::0;-1:-1:-1;;;48322:53:0;;48213:75;;-1:-1:-1;48293:26:0::3;::::0;-1:-1:-1;;;;;;48322:13:0::3;::::0;-1:-1:-1;48322:37:0::3;::::0;:53:::3;::::0;48360:6;;48368;;48322:53:::3;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;48293:82;;48414:18;48394:16;:38;;48380:114;;;;-1:-1:-1::0;;;48380:114:0::3;;;;;;;:::i;:::-;48501:28;;:::i;:::-;48603:45;48620:7;48629:6;48637:10;48603:16;:45::i;:::-;48576:23;::::0;::::3;48534:114:::0;48555:19:::3;::::0;::::3;48534:114:::0;;;;48678:30:::3;::::0;48701:6;48678:22:::3;:30::i;:::-;48657:10;:18;;:51;;;::::0;::::3;48760:10;:18;;;48713:7;:16;48721:7;-1:-1:-1::0;;;;;48713:16:0::3;-1:-1:-1::0;;;;;48713:16:0::3;;;;;;;;;;;;:28;48730:10;-1:-1:-1::0;;;;;48713:28:0::3;-1:-1:-1::0;;;;;48713:28:0::3;;;;;;;;;;;;:36;48742:6;-1:-1:-1::0;;;;;48713:36:0::3;-1:-1:-1::0;;;;;48713:36:0::3;;;;;;;;;;;;:44;;:65;;;;48842:10;:19;;;48783:7;:16;48791:7;-1:-1:-1::0;;;;;48783:16:0::3;-1:-1:-1::0;;;;;48783:16:0::3;;;;;;;;;;;;:28;48800:10;-1:-1:-1::0;;;;;48783:28:0::3;-1:-1:-1::0;;;;;48783:28:0::3;;;;;;;;;;;;:36;48812:6;-1:-1:-1::0;;;;;48783:36:0::3;-1:-1:-1::0;;;;;48783:36:0::3;;;;;;;;;;;;:56;;:78;;;;48923:10;:23;;;48866:7;:16;48874:7;-1:-1:-1::0;;;;;48866:16:0::3;-1:-1:-1::0;;;;;48866:16:0::3;;;;;;;;;;;;:28;48883:10;-1:-1:-1::0;;;;;48866:28:0::3;-1:-1:-1::0;;;;;48866:28:0::3;;;;;;;;;;;;:36;48895:6;-1:-1:-1::0;;;;;48866:36:0::3;-1:-1:-1::0;;;;;48866:36:0::3;;;;;;;;;;;;:54;;:80;;;;49001:15;48951:11;:20;48963:7;-1:-1:-1::0;;;;;48951:20:0::3;-1:-1:-1::0;;;;;48951:20:0::3;;;;;;;;;;;;:32;48972:10;-1:-1:-1::0;;;;;48951:32:0::3;-1:-1:-1::0;;;;;48951:32:0::3;;;;;;;;;;;;:47;;:65;;;;49023:30;49046:6;49023:22;:30::i;:::-;-1:-1:-1::0;;;;;49095:20:0;::::3;;::::0;;;:12:::3;:20;::::0;;;;:32:::3;;::::0;:44:::3;::::0;49132:6;49095:36:::3;:44::i;:::-;-1:-1:-1::0;;;;;49060:20:0;::::3;;::::0;;;:12:::3;:20;::::0;;;;:32:::3;;:79:::0;49146:47:::3;49166:10;49073:6:::0;49186;49146:19:::3;:47::i;:::-;49259:10;-1:-1:-1::0;;;;;49205:177:0::3;49247:6;-1:-1:-1::0;;;;;49205:177:0::3;49234:7;-1:-1:-1::0;;;;;49205:177:0::3;;49217:10;49275:6;49287:10;:18;;;49311:10;:19;;;49336:10;:23;;;49365:12;49205:177;;;;;;;;;;;:::i;:::-;;;;;;;;9679:1;;;9387::::2;2129::3::1;47845:1542:0::0;;;;;;:::o;40963:323::-;41022:26;41051:19;41074:29;41096:6;41074:21;:29::i;:::-;-1:-1:-1;;;;;41110:20:0;;;;;;:12;:20;;;;;;;:32;;;:53;;;41168:42;;:56;;;41236:45;41021:82;;-1:-1:-1;41021:82:0;;-1:-1:-1;41110:20:0;41236:45;;-1:-1:-1;41236:45:0;;41021:82;;41236:45;:::i;42481:340::-;42573:12;-1:-1:-1;;;;;42602:19:0;;-1:-1:-1;;;;;;;;;;;42602:19:0;42598:178;;;42642:8;-1:-1:-1;;;;;42642:13:0;42662:6;42642:31;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;42628:45;;;;;42598:178;;;42738:32;;-1:-1:-1;;;42738:32:0;;42716:5;;-1:-1:-1;;;;;42738:14:0;;;;;:32;;42753:8;;42763:6;;42738:32;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;42728:42;;42598:178;;42789:7;42780:36;;;;-1:-1:-1;;;42780:36:0;;;;;;;:::i;42876:232::-;43014:48;;-1:-1:-1;;;43014:48:0;;42988:5;;42966:12;;-1:-1:-1;;;;;43014:18:0;;;;;:48;;43033:10;;43045:8;;43055:6;;43014:48;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;42999:63;;43076:7;43067:36;;;;-1:-1:-1;;;43067:36:0;;;;;;;:::i;1806:192:5:-;1892:7;1928:12;1920:6;;;;1912:29;;;;-1:-1:-1;;;1912:29:5;;;;;;;;:::i;:::-;-1:-1:-1;;;1964:5:5;;;1806:192::o;3832:278::-;3918:7;3953:12;3946:5;3938:28;;;;-1:-1:-1;;;3938:28:5;;;;;;;;:::i;:::-;;3977:9;3993:1;3989;:5;;;;;;;3832:278;-1:-1:-1;;;;;3832:278:5:o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;:::o;1048:708::-;;1175:3;1168:4;1160:6;1156:17;1152:27;1142:2;;-1:-1;;1183:12;1142:2;1230:6;1217:20;1252:90;1267:74;1334:6;1267:74;:::i;:::-;1252:90;:::i;:::-;1370:21;;;1243:99;-1:-1;1414:4;1427:14;;;;1402:17;;;1522:1;1507:243;1532:6;1529:1;1526:13;1507:243;;;1639:47;1682:3;1414:4;1615:3;1602:17;1406:6;1590:30;;1639:47;:::i;:::-;1627:60;;1701:14;;;;1729;;;;1554:1;1547:9;1507:243;;;1511:14;;;;;1135:621;;;;:::o;2828:442::-;;2930:3;2923:4;2915:6;2911:17;2907:27;2897:2;;-1:-1;;2938:12;2897:2;2985:6;2972:20;52547:18;52539:6;52536:30;52533:2;;;-1:-1;;52569:12;52533:2;3007:65;52642:9;52623:17;;-1:-1;;52619:33;52710:4;52700:15;3007:65;:::i;:::-;2998:74;;3092:6;3085:5;3078:21;3196:3;52710:4;3187:6;3120;3178:16;;3175:25;3172:2;;;3213:1;;3203:12;3172:2;55537:6;52710:4;3120:6;3116:17;52710:4;3154:5;3150:16;55514:30;55593:1;55575:16;;;52710:4;55575:16;55568:27;3154:5;2890:380;-1:-1;;2890:380::o;3335:1333::-;;3469:4;3457:9;3452:3;3448:19;3444:30;3441:2;;;-1:-1;;3477:12;3441:2;3505:20;3469:4;3505:20;:::i;:::-;3496:29;;2578:6;2572:13;2590:30;2614:5;2590:30;:::i;:::-;3585:83;;3733:2;3795:22;;2572:13;2590:30;2572:13;2590:30;:::i;:::-;3766:57;3733:2;3752:5;3748:16;3741:83;;3896:2;3965:9;3961:22;6438:13;3896:2;3915:5;3911:16;3904:86;4060:2;4129:9;4125:22;6438:13;4060:2;4079:5;4075:16;4068:86;4222:3;4292:9;4288:22;6438:13;4222:3;4242:5;4238:16;4231:86;4391:3;4461:9;4457:22;6438:13;4391:3;4411:5;4407:16;4400:86;4552:3;4622:9;4618:22;6438:13;4552:3;4572:5;4568:16;4561:86;3435:1233;;;;:::o;6088:128::-;6154:20;;53729:6;53718:18;;56473:34;;56463:2;;56521:1;;56511:12;6501:241;;6605:2;6593:9;6584:7;6580:23;6576:32;6573:2;;;-1:-1;;6611:12;6573:2;85:6;72:20;97:33;124:5;97:33;:::i;6749:366::-;;;6870:2;6858:9;6849:7;6845:23;6841:32;6838:2;;;-1:-1;;6876:12;6838:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;6928:63;-1:-1;7028:2;7067:22;;72:20;97:33;72:20;97:33;:::i;:::-;7036:63;;;;6832:283;;;;;:::o;7122:491::-;;;;7260:2;7248:9;7239:7;7235:23;7231:32;7228:2;;;-1:-1;;7266:12;7228:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;7318:63;-1:-1;7418:2;7457:22;;72:20;97:33;72:20;97:33;:::i;:::-;7426:63;-1:-1;7526:2;7565:22;;72:20;97:33;72:20;97:33;:::i;:::-;7534:63;;;;7222:391;;;;;:::o;7620:617::-;;;;;7775:3;7763:9;7754:7;7750:23;7746:33;7743:2;;;-1:-1;;7782:12;7743:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;7834:63;-1:-1;7934:2;7973:22;;72:20;97:33;72:20;97:33;:::i;:::-;7942:63;-1:-1;8042:2;8081:22;;72:20;97:33;72:20;97:33;:::i;:::-;8050:63;-1:-1;8150:2;8189:22;;72:20;97:33;72:20;97:33;:::i;:::-;7737:500;;;;-1:-1;7737:500;;-1:-1;;7737:500::o;8244:617::-;;;;;8399:3;8387:9;8378:7;8374:23;8370:33;8367:2;;;-1:-1;;8406:12;8367:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;8458:63;-1:-1;8558:2;8597:22;;72:20;97:33;72:20;97:33;:::i;:::-;8566:63;-1:-1;8666:2;8705:22;;72:20;97:33;72:20;97:33;:::i;:::-;8361:500;;;;-1:-1;8674:63;;8774:2;8813:22;6290:20;;-1:-1;;8361:500::o;8868:741::-;;;;;;9039:3;9027:9;9018:7;9014:23;9010:33;9007:2;;;-1:-1;;9046:12;9007:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;9098:63;-1:-1;9198:2;9237:22;;72:20;97:33;72:20;97:33;:::i;:::-;9206:63;-1:-1;9306:2;9345:22;;72:20;97:33;72:20;97:33;:::i;:::-;9314:63;-1:-1;9414:2;9453:22;;6290:20;;-1:-1;9522:3;9561:22;;6154:20;6179:32;6154:20;6179:32;:::i;:::-;9531:62;;;;9001:608;;;;;;;;:::o;9616:491::-;;;;9754:2;9742:9;9733:7;9729:23;9725:32;9722:2;;;-1:-1;;9760:12;9722:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;9812:63;-1:-1;9912:2;9951:22;;72:20;97:33;72:20;97:33;:::i;:::-;9716:391;;9920:63;;-1:-1;;;10020:2;10059:22;;;;6290:20;;9716:391::o;10114:615::-;;;;;10268:3;10256:9;10247:7;10243:23;10239:33;10236:2;;;-1:-1;;10275:12;10236:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;10327:63;-1:-1;10427:2;10466:22;;72:20;97:33;72:20;97:33;:::i;:::-;10435:63;-1:-1;10535:2;10574:22;;6290:20;;-1:-1;10661:52;10705:7;10643:2;10681:22;;10661:52;:::i;:::-;10651:62;;10230:499;;;;;;;:::o;10736:364::-;;;10856:2;10844:9;10835:7;10831:23;10827:32;10824:2;;;-1:-1;;10862:12;10824:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;10914:63;-1:-1;11032:52;11076:7;11014:2;11052:22;;11032:52;:::i;:::-;11022:62;;10818:282;;;;;:::o;11107:366::-;;;11228:2;11216:9;11207:7;11203:23;11199:32;11196:2;;;-1:-1;;11234:12;11196:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;11286:63;11386:2;11425:22;;;;6290:20;;-1:-1;;;11190:283::o;11480:489::-;;;;11617:2;11605:9;11596:7;11592:23;11588:32;11585:2;;;-1:-1;;11623:12;11585:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;11675:63;-1:-1;11775:2;11814:22;;6290:20;;-1:-1;11883:2;11921:22;;6154:20;6179:32;6154:20;6179:32;:::i;11976:392::-;;12116:2;;12104:9;12095:7;12091:23;12087:32;12084:2;;;-1:-1;;12122:12;12084:2;12173:17;12167:24;12211:18;12203:6;12200:30;12197:2;;;-1:-1;;12233:12;12197:2;12320:22;;422:4;410:17;;406:27;-1:-1;396:2;;-1:-1;;437:12;396:2;477:6;471:13;499:80;514:64;571:6;514:64;:::i;499:80::-;607:21;;;664:14;;;;639:17;;;753;;;744:27;;;;741:36;-1:-1;738:2;;;-1:-1;;780:12;738:2;-1:-1;806:10;;800:217;825:6;822:1;819:13;800:217;;;226:6;220:13;238:33;265:5;238:33;:::i;:::-;893:61;;847:1;840:9;;;;;968:14;;;;996;;800:217;;;-1:-1;12253:99;12078:290;-1:-1;;;;;;;12078:290::o;12375:397::-;;12514:2;12502:9;12493:7;12489:23;12485:32;12482:2;;;-1:-1;;12520:12;12482:2;12578:17;12565:31;12616:18;12608:6;12605:30;12602:2;;;-1:-1;;12638:12;12602:2;12668:88;12748:7;12739:6;12728:9;12724:22;12668:88;:::i;:::-;12658:98;12476:296;-1:-1;;;;12476:296::o;12779:658::-;;;12960:2;12948:9;12939:7;12935:23;12931:32;12928:2;;;-1:-1;;12966:12;12928:2;13024:17;13011:31;13062:18;;13054:6;13051:30;13048:2;;;-1:-1;;13084:12;13048:2;13114:88;13194:7;13185:6;13174:9;13170:22;13114:88;:::i;:::-;13104:98;;13267:2;;;;13256:9;13252:18;13239:32;13062:18;13283:6;13280:30;13277:2;;;-1:-1;;13313:12;13277:2;13389:22;;;-1:-1;1892:4;1880:17;;1876:27;-1:-1;1866:2;;-1:-1;;1907:12;1866:2;1954:6;1941:20;1976:80;1991:64;2048:6;1991:64;:::i;1976:80::-;2084:21;;;2141:14;;;;2116:17;;;2230;;;2221:27;;;;2218:36;-1:-1;2215:2;;;-1:-1;;2257:12;2215:2;-1:-1;2283:10;;2277:206;2302:6;2299:1;2296:13;2277:206;;;6290:20;;2370:50;;2324:1;2317:9;;;;;2434:14;;;;2462;;2277:206;;;2281:14;13333:88;;;;;;;;12922:515;;;;;:::o;13444:257::-;;13556:2;13544:9;13535:7;13531:23;13527:32;13524:2;;;-1:-1;;13562:12;13524:2;2578:6;2572:13;2590:30;2614:5;2590:30;:::i;14014:347::-;;14128:2;14116:9;14107:7;14103:23;14099:32;14096:2;;;-1:-1;;14134:12;14096:2;14192:17;14179:31;14230:18;14222:6;14219:30;14216:2;;;-1:-1;;14252:12;14216:2;14282:63;14337:7;14328:6;14317:9;14313:22;14282:63;:::i;14368:472::-;;;14499:2;14487:9;14478:7;14474:23;14470:32;14467:2;;;-1:-1;;14505:12;14467:2;14563:17;14550:31;14601:18;14593:6;14590:30;14587:2;;;-1:-1;;14623:12;14587:2;14653:63;14708:7;14699:6;14688:9;14684:22;14653:63;:::i;:::-;14643:73;14753:2;14792:22;;;;6290:20;;-1:-1;;;;14461:379::o;14847:332::-;;14996:3;14984:9;14975:7;14971:23;14967:33;14964:2;;;-1:-1;;15003:12;14964:2;15065:98;15155:7;15131:22;15065:98;:::i;15517:239::-;;15620:2;15608:9;15599:7;15595:23;15591:32;15588:2;;;-1:-1;;15626:12;15588:2;6167:6;6154:20;6179:32;6205:5;6179:32;:::i;15763:263::-;;15878:2;15866:9;15857:7;15853:23;15849:32;15846:2;;;-1:-1;;15884:12;15846:2;-1:-1;6438:13;;15840:186;-1:-1;15840:186::o;16033:535::-;;;;16182:2;16170:9;16161:7;16157:23;16153:32;16150:2;;;-1:-1;;16188:12;16150:2;6444:6;6438:13;16240:74;;16351:2;16405:9;16401:22;6438:13;16359:74;;16470:2;16524:9;16520:22;6438:13;16478:74;;16144:424;;;;;:::o;17693:347::-;;17838:5;52820:12;53130:6;53125:3;53118:19;17932:52;17977:6;53167:4;53162:3;53158:14;53167:4;17958:5;17954:16;17932:52;:::i;:::-;52642:9;55954:14;-1:-1;;55950:28;17996:39;;;;53167:4;17996:39;;17785:255;-1:-1;;17785:255::o;29132:275::-;;18210:5;52820:12;18322:52;18367:6;18362:3;18355:4;18348:5;18344:16;18322:52;:::i;:::-;18386:16;;;;;29268:139;-1:-1;;29268:139::o;29414:379::-;29778:10;29602:191::o;29800:222::-;-1:-1;;;;;53810:54;;;;16795:37;;29927:2;29912:18;;29898:124::o;30029:460::-;-1:-1;;;;;53810:54;;;16654:58;;53810:54;;;;30392:2;30377:18;;16795:37;30475:2;30460:18;;29083:37;;;;30220:2;30205:18;;30191:298::o;30496:460::-;-1:-1;;;;;53810:54;;;;16654:58;;30859:2;30844:18;;29083:37;;;;30942:2;30927:18;;29083:37;30687:2;30672:18;;30658:298::o;30963:684::-;-1:-1;;;;;53810:54;;;;16654:58;;31383:2;31368:18;;29083:37;;;;31466:2;31451:18;;29083:37;;;;31549:2;31534:18;;29083:37;31632:3;31617:19;;29083:37;31210:3;31195:19;;31181:466::o;31654:792::-;-1:-1;;;;;53810:54;;;;16654:58;;32100:2;32085:18;;29083:37;;;;32183:2;32168:18;;29083:37;;;;32266:2;32251:18;;29083:37;32349:3;32334:19;;29083:37;53729:6;53718:18;53821:42;32416:19;;28964:36;31927:3;31912:19;;31898:548::o;32453:333::-;-1:-1;;;;;53810:54;;;16795:37;;53810:54;;32772:2;32757:18;;16795:37;32608:2;32593:18;;32579:207::o;33260:333::-;-1:-1;;;;;53810:54;;;;16795:37;;33579:2;33564:18;;29083:37;33415:2;33400:18;;33386:207::o;33600:210::-;53504:13;;53497:21;16909:34;;33721:2;33706:18;;33692:118::o;33817:321::-;53504:13;;53497:21;16909:34;;34124:2;34109:18;;29083:37;33966:2;33951:18;;33937:201::o;35022:238::-;17623:58;;;35157:2;35142:18;;35128:132::o;35267:310::-;;35414:2;35435:17;35428:47;35489:78;35414:2;35403:9;35399:18;35553:6;35489:78;:::i;35584:421::-;;35759:2;35780:17;35773:47;35834:78;35759:2;35748:9;35744:18;35898:6;35834:78;:::i;:::-;35826:86;;29113:5;35991:2;35980:9;35976:18;29083:37;35730:275;;;;;:::o;36012:416::-;36212:2;36226:47;;;18639:2;36197:18;;;53118:19;18675:32;53158:14;;;18655:53;18727:12;;;36183:245::o;36435:416::-;36635:2;36649:47;;;18978:2;36620:18;;;53118:19;-1:-1;;;53158:14;;;18994:42;19055:12;;;36606:245::o;36858:416::-;37058:2;37072:47;;;19306:2;37043:18;;;53118:19;19342:29;53158:14;;;19322:50;19391:12;;;37029:245::o;37281:416::-;37481:2;37495:47;;;19642:2;37466:18;;;53118:19;-1:-1;;;53158:14;;;19658:45;19722:12;;;37452:245::o;37704:416::-;37904:2;37918:47;;;19973:2;37889:18;;;53118:19;-1:-1;;;53158:14;;;19989:45;20053:12;;;37875:245::o;38127:416::-;38327:2;38341:47;;;20304:2;38312:18;;;53118:19;20340:33;53158:14;;;20320:54;20393:12;;;38298:245::o;38550:416::-;38750:2;38764:47;;;20644:2;38735:18;;;53118:19;20680:26;53158:14;;;20660:47;20726:12;;;38721:245::o;38973:416::-;39173:2;39187:47;;;20977:2;39158:18;;;53118:19;21013:34;53158:14;;;20993:55;-1:-1;;;21068:12;;;21061:41;21121:12;;;39144:245::o;39396:416::-;39596:2;39610:47;;;21372:2;39581:18;;;53118:19;21408:34;53158:14;;;21388:55;-1:-1;;;21463:12;;;21456:27;21502:12;;;39567:245::o;39819:416::-;40019:2;40033:47;;;21753:2;40004:18;;;53118:19;-1:-1;;;53158:14;;;21769:45;21833:12;;;39990:245::o;40242:416::-;40442:2;40456:47;;;22084:2;40427:18;;;53118:19;22120:34;53158:14;;;22100:55;-1:-1;;;22175:12;;;22168:34;22221:12;;;40413:245::o;40665:416::-;40865:2;40879:47;;;22472:2;40850:18;;;53118:19;-1:-1;;;53158:14;;;22488:43;22550:12;;;40836:245::o;41088:416::-;41288:2;41302:47;;;22801:2;41273:18;;;53118:19;-1:-1;;;53158:14;;;22817:38;22874:12;;;41259:245::o;41511:416::-;41711:2;41725:47;;;23125:2;41696:18;;;53118:19;23161:34;53158:14;;;23141:55;-1:-1;;;23216:12;;;23209:25;23253:12;;;41682:245::o;41934:416::-;42134:2;42148:47;;;23504:2;42119:18;;;53118:19;23540:34;53158:14;;;23520:55;-1:-1;;;23595:12;;;23588:25;23632:12;;;42105:245::o;42357:416::-;42557:2;42571:47;;;23883:2;42542:18;;;53118:19;23919:34;53158:14;;;23899:55;23988:34;23974:12;;;23967:56;-1:-1;;;24043:12;;;24036:35;24090:12;;;42528:245::o;42780:416::-;42980:2;42994:47;;;42965:18;;;53118:19;24377:34;53158:14;;;24357:55;24431:12;;;42951:245::o;43203:416::-;43403:2;43417:47;;;24682:2;43388:18;;;53118:19;-1:-1;;;53158:14;;;24698:43;24760:12;;;43374:245::o;43626:416::-;43826:2;43840:47;;;25011:2;43811:18;;;53118:19;25047:31;53158:14;;;25027:52;25098:12;;;43797:245::o;44049:416::-;44249:2;44263:47;;;25349:2;44234:18;;;53118:19;-1:-1;;;53158:14;;;25365:43;25427:12;;;44220:245::o;44472:416::-;44672:2;44686:47;;;25678:2;44657:18;;;53118:19;-1:-1;;;53158:14;;;25694:44;25757:12;;;44643:245::o;44895:416::-;45095:2;45109:47;;;26313:2;45080:18;;;53118:19;26349:33;53158:14;;;26329:54;26402:12;;;45066:245::o;45318:416::-;45518:2;45532:47;;;26653:2;45503:18;;;53118:19;26689:33;53158:14;;;26669:54;26742:12;;;45489:245::o;45741:416::-;45941:2;45955:47;;;26993:2;45926:18;;;53118:19;27029:30;53158:14;;;27009:51;27079:12;;;45912:245::o;46164:416::-;46364:2;46378:47;;;27330:2;46349:18;;;53118:19;-1:-1;;;53158:14;;;27346:44;27409:12;;;46335:245::o;46587:416::-;46787:2;46801:47;;;27660:2;46772:18;;;53118:19;-1:-1;;;53158:14;;;27676:44;27739:12;;;46758:245::o;47010:416::-;47210:2;47224:47;;;27990:2;47195:18;;;53118:19;28026:34;53158:14;;;28006:55;-1:-1;;;28081:12;;;28074:39;28132:12;;;47181:245::o;47433:416::-;47633:2;47647:47;;;28383:2;47618:18;;;53118:19;28419:34;53158:14;;;28399:55;-1:-1;;;28474:12;;;28467:42;28528:12;;;47604:245::o;47856:416::-;48056:2;48070:47;;;48041:18;;;53118:19;28815:34;53158:14;;;28795:55;28869:12;;;48027:245::o;48508:333::-;29083:37;;;48827:2;48812:18;;29083:37;48663:2;48648:18;;48634:207::o;48848:444::-;29083:37;;;49195:2;49180:18;;29083:37;;;;49278:2;49263:18;;29083:37;49031:2;49016:18;;49002:290::o;49299:656::-;29083:37;;;49697:2;49682:18;;29083:37;;;;49780:2;49765:18;;29083:37;;;;49863:2;49848:18;;29083:37;53504:13;53497:21;49940:3;49925:19;;16909:34;49532:3;49517:19;;49503:452::o;49962:1228::-;29083:37;;;50506:2;50491:18;;29083:37;;;;50589:2;50574:18;;29083:37;;;;50672:2;50657:18;;29083:37;;;;50755:3;50740:19;;29083:37;;;;50839:3;50824:19;;29083:37;50923:3;50908:19;;29083:37;51007:3;50992:19;;29083:37;51091:3;51076:19;;29083:37;51175:3;51160:19;;29083:37;50341:3;50326:19;;50312:878::o;51197:256::-;51259:2;51253:9;51285:17;;;51360:18;51345:34;;51381:22;;;51342:62;51339:2;;;51417:1;;51407:12;51339:2;51259;51426:22;51237:216;;-1:-1;51237:216::o;51460:304::-;;51619:18;51611:6;51608:30;51605:2;;;-1:-1;;51641:12;51605:2;-1:-1;51686:4;51674:17;;;51739:15;;51542:222::o;55610:268::-;55675:1;55682:101;55696:6;55693:1;55690:13;55682:101;;;55763:11;;;55757:18;55744:11;;;55737:39;55718:2;55711:10;55682:101;;;55798:6;55795:1;55792:13;55789:2;;;-1:-1;;55675:1;55845:16;;55838:27;55659:219::o;55991:117::-;-1:-1;;;;;53810:54;;56050:35;;56040:2;;56099:1;;56089:12;56115:111;56196:5;53504:13;53497:21;56174:5;56171:32;56161:2;;56217:1;;56207:12;56415:115;53729:6;56500:5;53718:18;56476:5;56473:34;56463:2;;56521:1;;56511:12

Swarm Source

ipfs://1c9680aad6f8ca45225b25bbf11d6a9fc22a61789477d9f2522a05d48b5b9119
Block Transaction Difficulty Gas Used Reward
Block Uncle Number Difficulty Gas Used Reward
Loading