fn process_insolvent_loans() -> Result<(), OffchainErr> {
		// Get available assets list
		let mut underlying_assets: Vec<CurrencyId> = CurrencyId::get_enabled_tokens_in_protocol(UnderlyingAsset)
			.into_iter()
			.filter(|&underlying_id| T::LiquidityPoolsManager::pool_exists(&underlying_id))
			.collect();
		if underlying_assets.is_empty() {
			return Ok(());
		}

		// acquire offchain worker lock
		let lock_expiration = Duration::from_millis(T::OffchainWorkerMaxDurationMs::get());
		let mut lock = StorageLock::<'_, Time>::with_deadline(&OFFCHAIN_WORKER_LOCK, lock_expiration);
		let mut guard = lock.try_lock().map_err(|_| OffchainErr::OffchainLock)?;

		let start_pool_index = match StorageValueRef::persistent(&OFFCHAIN_WORKER_LATEST_POOL_INDEX).get::<u32>() {
			Some(Some(index)) => {
				// Assume that count of enbled tokens can be changed. So make sure that index is not out of
				// bounds
				index as usize % underlying_assets.len()
			}
			_ => usize::zero(),
		};
		StorageValueRef::persistent(&OFFCHAIN_WORKER_LATEST_POOL_INDEX).clear();

		// Start iteration from the pool where we finished. Otherwise, take first pool.
		underlying_assets.rotate_left(start_pool_index);
		let mut loans_checked_count = 0;
		let mut loans_liquidated_count = 0;
		let working_start_time = sp_io::offchain::timestamp();

		for (pos, currency_id) in underlying_assets.iter().enumerate() {
			log::info!("RiskManager starts processing loans for {:?}", currency_id);
			<T as module::Config>::ControllerManager::accrue_interest_rate(*currency_id)
				.map_err(|_| OffchainErr::CheckFail)?;
			let pool_members =
				<LiquidityPools<T>>::get_pool_members_with_loans(*currency_id).map_err(|_| OffchainErr::CheckFail)?;
			for member in pool_members.into_iter() {
				// We check if the user has the collateral so as not to start the liquidation process
				// for users who have collateral = 0 and borrow > 0.
				let user_has_collateral = <LiquidityPools<T>>::check_user_has_collateral(&member);

				// Checks if the liquidation should be allowed to occur.
				if user_has_collateral {
					let (_, shortfall) = <T as module::Config>::ControllerManager::get_hypothetical_account_liquidity(
						&member,
						*currency_id,
						0,
						0,
					)
					.map_err(|_| OffchainErr::CheckFail)?;
					if !shortfall.is_zero() {
						Self::submit_unsigned_liquidation(member, *currency_id);
						loans_liquidated_count += 1;
					}
				} else {
					//TODO It is place for handle the case when collateral = 0, borrow > 0
					continue;
				}

				loans_checked_count += 1;

				if guard.extend_lock().is_err() {
					// The lock's deadline is happened
					log::warn!(
						"Risk Manager offchain worker hasn't(!) processed all pools. \
						MAX duration time is expired. Loans checked count: {:?}, \
						loans liquidated count: {:?}",
						loans_checked_count,
						loans_liquidated_count
					);
					StorageValueRef::persistent(&OFFCHAIN_WORKER_LATEST_POOL_INDEX).set(&(pos as u32));
					return Ok(());
				}
			}
			log::info!("RiskManager finished processing loans for {:?}", currency_id);
		}

		let working_time = sp_io::offchain::timestamp().diff(&working_start_time);
		log::info!(
			"Risk Manager offchain worker has processed all pools. Loans checked count {:?}, \
			loans liquidated count: {:?}, execution time(ms): {:?}",
			loans_checked_count,
			loans_liquidated_count,
			working_time.millis()
		);

		Ok(())
	}
/// Checks insolvent loans and liquidate them if it required.
Checks insolvent loans and liquidate them if it required.
Checks insolvent loans and liquidate them if it required .
fn process_insolvent_loans() -> Result<(), OffchainErr> {
		// Get available assets list
		let mut underlying_assets: Vec<CurrencyId> = CurrencyId::get_enabled_tokens_in_protocol(UnderlyingAsset)
			.into_iter()
			.filter(|&underlying_id| T::LiquidityPoolsManager::pool_exists(&underlying_id))
			.collect();
		if underlying_assets.is_empty() {
			return Ok(());
		}
		// acquire offchain worker lock
		let lock_expiration = Duration::from_millis(T::OffchainWorkerMaxDurationMs::get());
		let mut lock = StorageLock::<'_, Time>::with_deadline(&OFFCHAIN_WORKER_LOCK, lock_expiration);
		let mut guard = lock.try_lock().map_err(|_| OffchainErr::OffchainLock)?;
		let start_pool_index = match StorageValueRef::persistent(&OFFCHAIN_WORKER_LATEST_POOL_INDEX).get::<u32>() {
			Some(Some(index)) => {
				// Assume that count of enbled tokens can be changed. So make sure that index is not out of
				// bounds
				index as usize % underlying_assets.len()
			}
			_ => usize::zero(),
		};
		StorageValueRef::persistent(&OFFCHAIN_WORKER_LATEST_POOL_INDEX).clear();
		// Start iteration from the pool where we finished. Otherwise, take first pool.
		underlying_assets.rotate_left(start_pool_index);
		let mut loans_checked_count = 0;
		let mut loans_liquidated_count = 0;
		let working_start_time = sp_io::offchain::timestamp();
		for (pos, currency_id) in underlying_assets.iter().enumerate() {
			log::info!("RiskManager starts processing loans for {:?}", currency_id);
			<T as module::Config>::ControllerManager::accrue_interest_rate(*currency_id)
				.map_err(|_| OffchainErr::CheckFail)?;
			let pool_members =
				<LiquidityPools<T>>::get_pool_members_with_loans(*currency_id).map_err(|_| OffchainErr::CheckFail)?;
			for member in pool_members.into_iter() {
				// We check if the user has the collateral so as not to start the liquidation process
				// for users who have collateral = 0 and borrow > 0.
				let user_has_collateral = <LiquidityPools<T>>::check_user_has_collateral(&member);
				// Checks if the liquidation should be allowed to occur.
				if user_has_collateral {
					let (_, shortfall) = <T as module::Config>::ControllerManager::get_hypothetical_account_liquidity(
						&member,
						*currency_id,
						0,
						0,
					)
					.map_err(|_| OffchainErr::CheckFail)?;
					if !shortfall.is_zero() {
						Self::submit_unsigned_liquidation(member, *currency_id);
						loans_liquidated_count += 1;
					}
				} else {
					//TODO It is place for handle the case when collateral = 0, borrow > 0
					continue;
				}
				loans_checked_count += 1;
				if guard.extend_lock().is_err() {
					// The lock's deadline is happened
					log::warn!(
						"Risk Manager offchain worker hasn't(!) processed all pools. \
						MAX duration time is expired. Loans checked count: {:?}, \
						loans liquidated count: {:?}",
						loans_checked_count,
						loans_liquidated_count
					);
					StorageValueRef::persistent(&OFFCHAIN_WORKER_LATEST_POOL_INDEX).set(&(pos as u32));
					return Ok(());
				}
			}
			log::info!("RiskManager finished processing loans for {:?}", currency_id);
		}
		let working_time = sp_io::offchain::timestamp().diff(&working_start_time);
		log::info!(
			"Risk Manager offchain worker has processed all pools. Loans checked count {:?}, \
			loans liquidated count: {:?}, execution time(ms): {:?}",
			loans_checked_count,
			loans_liquidated_count,
			working_time.millis()
		);
		Ok(())
	}
fn process_insolvent_loans ( ) -> Result < ( ) , OffchainErr > { // Get available assets list let mut underlying_assets : Vec < CurrencyId > = CurrencyId :: get_enabled_tokens_in_protocol ( UnderlyingAsset ) . into_iter ( ) . filter ( | & underlying_id | T :: LiquidityPoolsManager :: pool_exists ( & underlying_id ) ) . collect ( ) ; if underlying_assets . is_empty ( ) { return Ok ( ( ) ) ; } // acquire offchain worker lock let lock_expiration = Duration :: from_millis ( T :: OffchainWorkerMaxDurationMs :: get ( ) ) ; let mut lock = StorageLock :: < ' _ , Time > :: with_deadline ( & OFFCHAIN_WORKER_LOCK , lock_expiration ) ; let mut guard = lock . try_lock ( ) . map_err ( | _ | OffchainErr :: OffchainLock ) ? ; let start_pool_index = match StorageValueRef :: persistent ( & OFFCHAIN_WORKER_LATEST_POOL_INDEX ) . get :: < u32 > ( ) { Some ( Some ( index ) ) => { // Assume that count of enbled tokens can be changed. So make sure that index is not out of // bounds index as usize % underlying_assets . len ( ) } _ => usize :: zero ( ) , } ; StorageValueRef :: persistent ( & OFFCHAIN_WORKER_LATEST_POOL_INDEX ) . clear ( ) ; // Start iteration from the pool where we finished. Otherwise, take first pool. underlying_assets . rotate_left ( start_pool_index ) ; let mut loans_checked_count = 0 ; let mut loans_liquidated_count = 0 ; let working_start_time = sp_io :: offchain :: timestamp ( ) ; for ( pos , currency_id ) in underlying_assets . iter ( ) . enumerate ( ) { log :: info ! ( " " currency_id ) ; < T as module :: Config > :: ControllerManager :: accrue_interest_rate ( * currency_id ) . map_err ( | _ | OffchainErr :: CheckFail ) ? ; let pool_members = < LiquidityPools < T > > :: get_pool_members_with_loans ( * currency_id ) . map_err ( | _ | OffchainErr :: CheckFail ) ? ; for member in pool_members . into_iter ( ) { // We check if the user has the collateral so as not to start the liquidation process // for users who have collateral = 0 and borrow > 0. let user_has_collateral = < LiquidityPools < T > > :: check_user_has_collateral ( & member ) ; // Checks if the liquidation should be allowed to occur. if user_has_collateral { let ( _ , shortfall ) = < T as module :: Config > :: ControllerManager :: get_hypothetical_account_liquidity ( & member , * currency_id , 0 , 0 , ) . map_err ( | _ | OffchainErr :: CheckFail ) ? ; if ! shortfall . is_zero ( ) { Self :: submit_unsigned_liquidation ( member , * currency_id ) ; loans_liquidated_count += 1 ; } } else { //TODO It is place for handle the case when collateral = 0, borrow > 0 continue ; } loans_checked_count += 1 ; if guard . extend_lock ( ) . is_err ( ) { // The lock's deadline is happened log :: warn ! ( " \
 \
 " loans_checked_count loans_liquidated_count ) ; StorageValueRef :: persistent ( & OFFCHAIN_WORKER_LATEST_POOL_INDEX ) . set ( & ( pos as u32 ) ) ; return Ok ( ( ) ) ; } } log :: info ! ( " " currency_id ) ; } let working_time = sp_io :: offchain :: timestamp ( ) . diff ( & working_start_time ) ; log :: info ! ( " \
 " loans_checked_count loans_liquidated_count working_time millis ( ) ) ; Ok ( ( ) ) }
Checks insolvent loans and liquidate them if it required.
Checks insolvent loans and liquidate them if it required .