Fixed Point Types

Since we now have “safe math by default”, one of the next long-standing items to tackle about arithmetic is fixed points. One fundamental drawback mentioned by 3sGgpQ8H on the OZ forum is that most of the time, you would use fixed points not as the main data type but rather as a factor, which does not go well with how Solidity assigns types to expressions:

uint weitAmount;
uint amountIncludingTag = weiAmount * 1.12;

The type of 1.12 is a fixed point type, so the type of weiAmount * 1.12 should also be a fixed point type.

Does anyone see a solution to this problem? Is it not a problem after all because the initial type can also just be a fixed point type?

I would want:

uint256 amount;
fixed128x18 interest = 1.12;
uint256 new_amount = amount * interest;

Under the hood I would expect this to turn into:

uint256 amount;
uint256 new_amount = amount * 1120000000000000000 / 10**18;

All with overflow protection of course. :grinning_face_with_smiling_eyes:

1 Like

Since you mentioned overflow protection, why not the following (under the hood):
uint256 new_amount = amount * 112 / 100;

Or do you specifically want to have overflow checks for amount * 1120000000000000000?

1 Like

If 1.12 was a constant, then I would agree that the compiler should go with 112/100. In my example I meant to imply that the interest value is (e.g., user input).

Unfortunately, I can really see both versions (result being fixed point or result being integer):
We can have amount * interest to compute the amount with interest, but we could also have uint multiplier = 2 and then multiplier * interest to compute “double interest” which would then be expected to be a fixed point number and not an integer.

I think the only real solution is to have the temporary be of a type that is “compatible” with both operand types and then require the user to perform an explicit type conversion (if needed)…

For literals, I think requiring the decimal would solve that problem 2 is a uint and 2.0 is a ufixed. I believe there are other languages that do this (maybe Python?) and if you really want you can always cast your literal before using it.

Edit: I realize I misunderstood what you were saying @chriseth. I still like literals as I described above, but it doesn’t address what you are talking about.