The mismatch between the lengths of `updated_trove_yang_balances` and `new_yang_totals` in function `redistribute_helper()` results in incorrect accounting for the trove's yang balance
Audit: 2024-01-opus-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-01-opus/blob/4720e9481a4fb20f4ab4140f9cc391a23ede3817/src/core/shrine.cairo#L2018-L2033
https://github.com/code-423n4/2024-01-opus/blob/4720e9481a4fb20f4ab4140f9cc391a23ede3817/src/core/shrine.cairo#L1746-L1755


# Vulnerability details

## Description
The `shrine::redistribute_helper()` function is employed to reallocate the debt and yang from a redistributed trove to other troves within the shrine. This function iterates through all the yangs associated with the given `trove_id`, redistributes the trove's yang and debts, and stores the updated state of the contract's STORAGE in two arrays: `new_yang_totals` and `updated_trove_yang_balances`.

Upon completion, the function utilizes these two calculated arrays to update the corresponding STORAGE values, namely `self.yang_total` and `self.deposits` of the trove.

https://github.com/code-423n4/2024-01-opus/blob/4720e9481a4fb20f4ab4140f9cc391a23ede3817/src/core/shrine.cairo#L2018-L2033
```rust=
let mut new_yang_totals: Span<YangBalance> = new_yang_totals.span();
let mut updated_trove_yang_balances: Span<YangBalance> = updated_trove_yang_balances.span();
loop {
    match new_yang_totals.pop_front() {
        Option::Some(total_yang_balance) => {
            let updated_trove_yang_balance: YangBalance = *updated_trove_yang_balances.pop_front().unwrap();
            self
                .deposits
                .write((updated_trove_yang_balance.yang_id, trove_id), updated_trove_yang_balance.amount);


            self.yang_total.write(*total_yang_balance.yang_id, *total_yang_balance.amount);
        },
        Option::None => { break; },
    };
};
```

It's noteworthy that a single loop is employed instead of separate loops for each array, implying that the function assumes equal lengths for the two arrays, `new_yang_totals` and `updated_trove_yang_balances`.

However, a potential flaw arises when exploiting the invariant above by utilizing zero amount yang. If the yang value of the distributed trove is zero, the outermost loop merely updates the `updated_trove_yang_balances` for that yang to the old value and skips the iteration. Nevertheless, the `new_yang_totals` array remains unchanged during this iteration, causing its length to be less than that of `updated_trove_yang_balances`. Consequently, certain yang balances of the `trove_id` remain unaltered, potentially benefiting the user.

https://github.com/code-423n4/2024-01-opus/blob/4720e9481a4fb20f4ab4140f9cc391a23ede3817/src/core/shrine.cairo#L1746-L1755
```rust=
loop {
    match trove_yang_balances_copy.pop_front() {
        Option::Some(yang_balance) => {
            let trove_yang_amt: Wad = (*yang_balance).amount;
            let yang_id_to_redistribute = (*yang_balance).yang_id;
            // Skip over this yang if it has not been deposited in the trove
            if trove_yang_amt.is_zero() {
                updated_trove_yang_balances.append(*yang_balance);
                continue;