lib.rs 36.5 KiB
Newer Older
Gavin Wood's avatar
Gavin Wood committed
				)?;
				self.take_fee(fee, FeeReason::Export { network, destination })?;
Gavin Wood's avatar
Gavin Wood committed
				Config::MessageExporter::deliver(ticket)?;
				Ok(())
			},
			LockAsset { asset, unlocker } => {
				let origin = *self.origin_ref().ok_or(XcmError::BadOrigin)?;
				let (remote_asset, context) = Self::try_reanchor(asset.clone(), &unlocker)?;
				let lock_ticket = Config::AssetLocker::prepare_lock(unlocker, asset, origin)?;
				let owner =
					origin.reanchored(&unlocker, context).map_err(|_| XcmError::ReanchorFailed)?;
				let msg = Xcm::<()>(vec![NoteUnlockable { asset: remote_asset, owner }]);
				let (ticket, price) = validate_send::<Config::XcmSender>(unlocker, msg)?;
				self.take_fee(price, FeeReason::LockAsset)?;
				lock_ticket.enact()?;
				Config::XcmSender::deliver(ticket)?;
				Ok(())
			},
			UnlockAsset { asset, target } => {
				let origin = *self.origin_ref().ok_or(XcmError::BadOrigin)?;
				Config::AssetLocker::prepare_unlock(origin, asset, target)?.enact()?;
				Ok(())
			},
			NoteUnlockable { asset, owner } => {
				let origin = *self.origin_ref().ok_or(XcmError::BadOrigin)?;
				Config::AssetLocker::note_unlockable(origin, asset, owner)?;
				Ok(())
			},
			RequestUnlock { asset, locker } => {
				let origin = *self.origin_ref().ok_or(XcmError::BadOrigin)?;
				let remote_asset = Self::try_reanchor(asset.clone(), &locker)?.0;
				let remote_target = Self::try_reanchor_multilocation(origin, &locker)?.0;
Gavin Wood's avatar
Gavin Wood committed
				let reduce_ticket =
					Config::AssetLocker::prepare_reduce_unlockable(locker, asset, origin)?;
				let msg =
					Xcm::<()>(vec![UnlockAsset { asset: remote_asset, target: remote_target }]);
Gavin Wood's avatar
Gavin Wood committed
				let (ticket, price) = validate_send::<Config::XcmSender>(locker, msg)?;
				self.take_fee(price, FeeReason::RequestUnlock)?;
				reduce_ticket.enact()?;
				Config::XcmSender::deliver(ticket)?;
				Ok(())
			},
			ExchangeAsset { give, want, maximal } => {
				let give = self.holding.saturating_take(give);
				let r =
					Config::AssetExchanger::exchange_asset(self.origin_ref(), give, &want, maximal);
				let completed = r.is_ok();
				let received = r.unwrap_or_else(|a| a);
				for asset in received.into_assets_iter() {
					self.holding.subsume(asset);
				}
				if completed {
					Ok(())
				} else {
					Err(XcmError::NoDeal)
				}
			},
			SetFeesMode { jit_withdraw } => {
				self.fees_mode = FeesMode { jit_withdraw };
				Ok(())
			},
			SetTopic(topic) => {
				self.context.topic = Some(topic);
				Ok(())
			},
			ClearTopic => {
				self.context.topic = None;
				Ok(())
			},
			AliasOrigin(target) => {
				let origin = self.origin_ref().ok_or(XcmError::BadOrigin)?;
				if Config::Aliasers::contains(origin, &target) {
					self.context.origin = Some(target);
					Ok(())
				} else {
					Err(XcmError::NoPermission)
				}
			},
Gavin Wood's avatar
Gavin Wood committed
			UnpaidExecution { check_origin, .. } => {
				ensure!(
					check_origin.is_none() || self.context.origin == check_origin,
					XcmError::BadOrigin
				);
				Ok(())
			HrmpNewChannelOpenRequest { .. } => Err(XcmError::Unimplemented),
			HrmpChannelAccepted { .. } => Err(XcmError::Unimplemented),
			HrmpChannelClosing { .. } => Err(XcmError::Unimplemented),