Repository: paritytech/substrate
File: frame/contracts/src/migration/v10.rs (Rust)

Code before:
	}
}

#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
#[scale_info(skip_type_params(T))]
pub struct ContractInfo<T: Config> {
	pub trie_id: TrieId,
	deposit_account: DepositAccount<T>,
	pub code_hash: CodeHash<T>,
	storage_bytes: u32,
	storage_items: u32,
	pub storage_byte_deposit: BalanceOf<T>,
	storage_item_deposit: BalanceOf<T>,
	storage_base_deposit: BalanceOf<T>,
}

#[derive(Encode, Decode, MaxEncodedLen, DefaultNoBound)]
pub struct Migration<T: Config> {
	last_key: Option<BoundedVec<u8, ConstU32<256>>>,
	_phantom: PhantomData<T>,
}

#[storage_alias]
type ContractInfoOf<T: Config> =
	StorageMap<Pallet<T>, Twox64Concat, <T as frame_system::Config>::AccountId, ContractInfo<T>>;

impl<T: Config> MigrationStep for Migration<T> {
	const VERSION: u16 = 10;

	fn max_step_weight() -> Weight {
		T::WeightInfo::v10_migration_step()
	}

	fn step(&mut self) -> (IsFinished, Weight) {
		let mut iter = if let Some(last_key) = self.last_key.take() {
			old::ContractInfoOf::<T>::iter_from(last_key.to_vec())
		} else {
			old::ContractInfoOf::<T>::iter()
		};

		if let Some((account, contract)) = iter.next() {
			let min_balance = Pallet::<T>::min_balance();
			log::debug!(target: LOG_TARGET, "Account: 0x{} ", HexDisplay::from(&account.encode()));

			// Store last key for next migration step
			self.last_key = Some(iter.last_raw_key().to_vec().try_into().unwrap());

			// Get the new deposit account address
			let deposit_account: DepositAccount<T> =
				DepositAccount(T::AddressGenerator::deposit_address(&account));


Review comment (suggestion):
Continuing [this](https://github.com/paritytech/substrate/pull/14045#discussion_r1212023689) discourse: 

https://github.com/paritytech/substrate/blob/dbb20d3accc0331eb40af0c842427bfeeb430240/frame/contracts/src/migration/v10.rs#L163-L166

Do we really need to subtract `min_balance` here? Possible arguments versus are:
1. if `old_deposit > reducible_balance` then only `reducible_balance` would be charged here.
2. Looks like we already subtract it when calculate the deposit due:
https://github.com/paritytech/substrate/blob/6a89133090d77002224d3aa865aa85f57e835acd/frame/contracts/src/storage.rs#L120-L124
3. We are transferring from regular (not contract) account here. Tombstone-ing it is not end of the world, as it's holder could top-up it and bring it back to life again.

Code after:
	}
}

#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
#[scale_info(skip_type_params(T))]
pub struct ContractInfo<T: Config> {
	pub trie_id: TrieId,
	deposit_account: DepositAccount<T>,
	pub code_hash: CodeHash<T>,
	storage_bytes: u32,
	storage_items: u32,
	pub storage_byte_deposit: BalanceOf<T>,
	storage_item_deposit: BalanceOf<T>,
	storage_base_deposit: BalanceOf<T>,
}

#[derive(Encode, Decode, MaxEncodedLen, DefaultNoBound)]
pub struct Migration<T: Config> {
	last_account: Option<T::AccountId>,
}

#[storage_alias]
type ContractInfoOf<T: Config> =
	StorageMap<Pallet<T>, Twox64Concat, <T as frame_system::Config>::AccountId, ContractInfo<T>>;

impl<T: Config> MigrationStep for Migration<T> {
	const VERSION: u16 = 10;

	fn max_step_weight() -> Weight {
		T::WeightInfo::v10_migration_step()
	}

	fn step(&mut self) -> (IsFinished, Weight) {
		let mut iter = if let Some(last_account) = self.last_account.take() {
			old::ContractInfoOf::<T>::iter_from(old::ContractInfoOf::<T>::hashed_key_for(
				last_account,
			))
		} else {
			old::ContractInfoOf::<T>::iter()
		};

		if let Some((account, contract)) = iter.next() {
			let min_balance = Pallet::<T>::min_balance();
			log::debug!(target: LOG_TARGET, "Account: 0x{} ", HexDisplay::from(&account.encode()));

			// Get the new deposit account address
			let deposit_account: DepositAccount<T> =
				DepositAccount(T::AddressGenerator::deposit_address(&account));

			// Calculate the existing deposit, that should be reserved on the contract account
			let old_deposit = contract