## Invariant may sometimes be calculated incorrectly

### Description

The `_tweakPrice`

function adjusts the `priceOracle`

, `lastPrices`

and `priceScale`

variables, used in the calculation of the prices within the pool. This function is an essential component of the pool, and is called whenever there is an inbalance during any of the liquidity operations, such as swap, mint or burn.

In `_tweakPrice`

, the Vyper code calculates `D_unadjusted`

:

```
# ------------------ If new_D is set to 0, calculate it ------------------
D_unadjusted: uint256 = new_D
if new_D == 0: # <--------------------------- _exchange sets new_D to 0.
D_unadjusted = MATH.newton_D(A_gamma[0], A_gamma[1], _xp, K0_prev)
```

The corresponding Solidity code-names this value `newInvariant`

:

```
// ---------------- If `newInvariant` is 0, calculate it -----------------
if (newInvariant == 0) {
newInvariant = MATH.computeD(a, gamma, xp0, xp1, _k0_prev);
}
```

The invariant that this pool uses is essentially somewhere between the constant-product invariant(like in Uniswap, Balancer, etc.) and the StableSwap(which is essentially Curve v1).

Further down the function, Vyper calculates a value and stores to a new variable `D`

this time (not `D_unadjusted`

):

```
# ------------------------------------------ Update D with new xp.
D: uint256 = MATH.newton_D(A_gamma[0], A_gamma[1], xp, 0)
```

However, Solidity overwrites `newInvariant`

(which was `D_unadjusted`

) with this value instead of defining a new variable too:

```
// ------------------------------------------ Update D with new xp.
// Calculate "extended constant product" invariant xCP and virtual price.
newInvariant = MATH.computeD(a, gamma, _xp0, _xp1, 0);
```

Finally, at the end of the function, Vyper stores `D_unadjusted`

to `self.D`

. Solidity stores `newInvariant`

(which is not `D_unadjusted`

but `D`

in Vyper) to `invariantLast`

(i.e., the equivalent of `self.D`

in Vyper).

### Impact

For any cases in the Vyper code where `D != D_unadjusted`

at the end of the function, the Solidity code will store the wrong value. Per SyncSwap Labs,

This can cause wrong value to be updated to

`invariantLast`

/`D`

if the pool didn't got enough profit to rebalance.

### Recommendations

Use an ephemeral variable when determining whether or not to rebalance profits.

### Remediation

This issue has been acknowledged by SyncSwap Labs, and a fix was implemented in commit ff28d01a↗.