Repository: paritytech/substrate
File: frame/society/src/migrations.rs (Rust)

Code before:
		);
	}

	// Migrate Members from old::Members old::Strikes old::Vouching
	let mut member_count = 0;
	for member in old::Members::<T, I>::take() {
		let strikes = old::Strikes::<T, I>::take(&member);
		let vouching = old::Vouching::<T, I>::take(&member);
		let record = MemberRecord { index: member_count, rank: 0, strikes, vouching };
		Members::<T, I>::insert(&member, record);
		MemberByIndex::<T, I>::insert(member_count, &member);

		// The founder must be the first member in Society V2. If we find the founder not in index
		// zero, we swap it with the first member.
		if member == Founder::<T, I>::get().expect("founder is always set; qed") && member_count > 0
		{
			let member_to_swap = MemberByIndex::<T, I>::get(0)
				.expect("member_count > 0, we must have at least 1 member; qed");
			// Swap the founder with the first member in MemberByIndex.
			MemberByIndex::<T, I>::swap(0, member_count);
			// Update the indicies of the swapped member MemberRecords.
			Members::<T, I>::mutate(&member, |m| {
				if let Some(member) = m {
					member.index = 0;
				} else {
					log::error!("Member somehow disapeared from storage after it was inserted")
				}
			});
			Members::<T, I>::mutate(&member_to_swap, |m| {
				if let Some(member) = m {
					member.index = member_count;
				} else {
					log::error!("Member somehow disapeared from storage after it was queried")
				}
			});
		}
		member_count.saturating_inc();
	}
	MemberCount::<T, I>::put(member_count);

	// Migrate Payouts from: old::Payouts and raw info (needed since we can't query old chain
	// state).
	past_payouts.sort();
	for (who, mut payouts) in old::Payouts::<T, I>::iter() {
		payouts.truncate(T::MaxPayouts::get() as usize);
		// ^^ Safe since we already truncated.
		let paid = past_payouts
			.binary_search_by_key(&&who, |x| &x.0)
			.ok()
			.map(|p| past_payouts[p].1)
			.unwrap_or(Zero::zero());

Review comment (suggestion):

```suggestion
					defensive!("Member somehow disapeared from storage after it was inserted")
```

Code after:
				.defensive_ok_or("member_count > 0, we must have at least 1 member")?;
			// Swap the founder with the first member in MemberByIndex.
			MemberByIndex::<T, I>::swap(0, member_count);
			// Update the indicies of the swapped member MemberRecords.
			Members::<T, I>::mutate(&member, |m| {
				if let Some(member) = m {
					member.index = 0;
				} else {
					frame_support::defensive!(
						"Member somehow disapeared from storage after it was inserted"
					);
				}
			});
			Members::<T, I>::mutate(&member_to_swap, |m| {
				if let Some(member) = m {
					member.index = member_count;
				} else {
					frame_support::defensive!(
						"Member somehow disapeared from storage after it was queried"
					);
				}
			});
		}
		member_count.saturating_inc();
	}
	MemberCount::<T, I>::put(member_count);

	// Migrate Payouts from: old::Payouts and raw info (needed since we can't query old chain
	// state).
	past_payouts.sort();
	for (who, mut payouts) in old::Payouts::<T, I>::iter() {
		payouts.truncate(T::MaxPayouts::get() as usize);
		// ^^ Safe since we already truncated.
		let paid = past_payouts
			.binary_search_by_key(&&who, |x| &x.0)
			.ok()
			.map(|p| past_payouts[p].1)
			.unwrap_or(Zero::zero());
		match BoundedVec::try_from(payouts) {
			Ok(payouts) => Payouts::<T, I>::insert(who, PayoutRecord { paid, payouts }),
			Err(_) => debug_assert!(false, "Truncation of Payouts ineffective??"),
		}
	}

	// Migrate SuspendedMembers from old::SuspendedMembers old::Strikes old::Vouching.
	for who in old::SuspendedMembers::<T, I>::iter_keys() {
		let strikes = old::Strikes::<T, I>::take(&who);
		let vouching = old::Vouching::<T, I>::take(&who);
		let record = MemberRecord { index: 0, rank: 0, strikes, vouching };
		SuspendedMembers::<T, I>::insert(&who, record);
	}