Skip to content

Smart contract implementing fixed point math operations using structs for type checking.

License

Notifications You must be signed in to change notification settings

alcueca/DecimalMath

Folders and files

NameName
Last commit message
Last commit date

Latest commit

4737ebc · Sep 17, 2020

History

26 Commits
Sep 17, 2020
Aug 15, 2020
Aug 28, 2020
Sep 17, 2020
Aug 28, 2020
Aug 15, 2020
Aug 15, 2020
Aug 15, 2020
Aug 28, 2020
Aug 15, 2020
Aug 15, 2020
Aug 15, 2020
Aug 28, 2020
Aug 31, 2020
Aug 28, 2020
Aug 15, 2020
Sep 17, 2020
Aug 15, 2020
Aug 28, 2020
Aug 15, 2020

Repository files navigation

Typed Decimal Math

This project is a strongly typed implementation for fixed point math in solidity.

When working with fixed point math, some numbers should be kept as integers, so this library implements cross-type functions for those cases. Examples of fixed point numbers: Ratios (including exchange ratios), percentages, factors. Examples of integers: Money (wei). Do we do math with anything else here?

This contract uses 27 decimals for fixed point numbers, following the standard from MakerDAO.

It uses the eternally experimental ABIEncoderV2, to allow passing structs as parameters.

Tested using echidna. echidna-test . --contract DecimalMathEchidna --config contracts/mocks/DecimalMathEchidna.yaml

Constants

UNIT: 1e27

Structs

UFixed: A fixed point number. UFixed.value: The raw value of the fixed point number. Note that 1.0 would be toUfixed(1e27).

Functions

Conversion

  • toUFixed(uint x) returns an UFixed created from x. Note that 1.0 would be toUfixed(1e27). Note as well that to retrieve the integer part of an UFixed you can do UFixed.value.div(UNIT), and to get the mantissa you can do UFixed.value.mod(UNIT)

Comparison

Comparison operators accept UFixed and uint as arguments in both positions. At least one argument must be an UFixed. Operators compare the converted UFixed values, not the internal UFixed.value ones, this is accomplished internally by multiplying any uint parameters by UNIT. Example:

  DecimalMath.UFixed ONE_POINT_ZERO = DecimalMath.toUFixed(UNIT);
  uint TWO_INTEGER = 2;
  TWO_INTEGER.gt(ONE_POINT_ZERO) == true
  ONE_POINT_ZERO.gt(TWO_INTEGER) == false
  • gt(x, y) returns bool Returns true if x is greater than y.
  • geq(x, y) returns bool Returns true if x is greater or equal than y.
  • lt(x, y) returns bool Returns true if x is less than y.
  • geq(x, y) returns bool Returns true if x is less or equal than y.
  • eq(x, y) returns bool Returns true if x is equal to y.

Arithmetic

Except for divd(uint, uint) which returns an UFixed, all other functions return the type of the first parameter.

  • muld(uint x, UFixed y) returns uint(x * y). Use this to multiply a money amount by a ratio (wei amount * ETH/DAI)
  • muld(UFixed x, UFixed y) returns UFixed(x * y). Use this to multiply two ratios (DAI/ETH * ETH/MKR)
  • muld(UFixed x, uint y) returns UFixed(x * y). Use this to multiply two ratios by a factor (DAI/ETH * 2)
  • divd(UFixed x, UFixed y) returns UFixed(x / y). Use this to divide two ratios (DAI/ETH / ETH/MKR)
  • divd(uint x, UFixed y) returns uint(x / y). Use this to divide a money amount by a ratio (wei amount / ETH/DAI)
  • divd(UFixed x, uint y) returns uint(x / y). Use this to apply a divisor to a ratio (ETH/DAI / 2)
  • divd(uint x, uint y) returns UFixed(x / y). Use this to divide two integer amounts and derive a ratio (debt / supply)
  • addd(UFixed x, UFixed y) returns UFixed(x + y). Use this to add two ratios
  • addd(UFixed x, UFixed y) returns UFixed(x + y). Use this to add a factor two a ratio (debt ratio + 1)
  • subd(UFixed x, UFixed y) returns UFixed(x - y). Use this to substract two ratios
  • subd(UFixed x, uint y) returns UFixed(x - y). Use this to substract a factor from a ratio (debt ratio - 1)
  • subd(uint x, UFixed y) returns UFixed(x - y). Use this to substract a ratio from a factor (1 - debt ratio)
  • divdrup(uint x, UFixed y) returns uint(x / y), rounding up. Use this and divd to split a money amount into two parts that add up to the original value. x = divd(x, y) + divdrup(x, 1 - y).
  • muldrup(uint x, UFixed y) returns uint(x / y), rounding up. Use this as the reverse of divd. z = divd(x, y), x = muldrup(z, y).

About

Smart contract implementing fixed point math operations using structs for type checking.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published