<!-- canonical: https://0xsimao.com/findings/m-0-stable-earner-model-precision -->

# Multiplication after division in StableEarnerRateModel leads to loss of precision

Low/Info · Three Sigma · Stablecoin framework · 8th January, 2024

Finding 3S-M^0-L01 of the M^0 Minter Gateway security review.

- Protocol: https://www.m0.org/
- Report: /reports/m-0
- Codebase: https://github.com/0xsimao/ttg/tree/a8127901fa1f24a2e821cf4d9854a1aa6ac8088c
- Source: https://cdn.sanity.io/files/qoqld077/production/1cdafafad874aba76e062ad8c216c98338c096db.pdf

---

### Description

In the [StableEarnerRateModel.getSafeEarnerRate](https://github.com/MZero-Labs/protocol/blob/3499f50ff3382729f3e59565b19386ba61ef8e36/src/rateModels/StableEarnerRateModel.sol#L69-L117) function, there's a log calculation
detailed in a comment:

```solidity
// 6. ln(1 + (totalActive * (delta_minterIndex - 1) / totalEarning)) * SECONDS_PER_YEAR / dt = earnerRate
```

The code implementation of the log argument calculation follows the comment, but using
fixed point arithmetic with 12 decimals. The problem is that a division by 1e12 is immediately
followed by a 1e12 multiplication:
1e12 + ((((uint256(totalActiveOwedM_) * (deltaMinterIndex_ -
1e12)) / 1e12) * 1e12) / totalEarningSupply_)
That division combined with the multiplication should cancel out in real world math. But
because of integer division, this sets the first 12 decimals to zero.

### Recommendation

Remove the division and multiplication by 1e12.

### Status

Addressed in [#cac3c24](https://github.com/MZero-Labs/protocol/commit/cac3c24b038d9d6c71bad1132b9f4617e91ef2f1).

---

Related findings:

- [Precision Loss in `notifyRewardAmount` Function Causes Unclaimable RewardToken](https://0xsimao.com/findings/exactly-protocol-update-staking-contract-ii-precision-notify-reward-unclaimable): Exactly Protocol Update - Staking Contract
