Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 

Rounding errors

Application developers must take care of correct rounding of numbers, especially if the rounding impacts tokens amounts.

Cosmos-sdk offers two custom types for dealing with numbers:

  • sdk.Int (sdk.UInt) type for integral numbers
  • sdk.Dec type for decimal arithmetic

The sdk.Dec type has problems with precision and does not guarantee associativity, so it must be used carefully. But even if a more robust library for decimal numbers is deployed in the cosmos-sdk, rounding may be unavoidable.

Example

Below we see a simple example demonstrating sdk.Dec type's precision problems.

func TestDec() {
    a := sdk.MustNewDecFromStr("10")
    b := sdk.MustNewDecFromStr("1000000010")
    x := a.Quo(b).Mul(b)
    fmt.Println(x)  // 9.999999999999999000

    q := float32(10)
    w := float32(1000000010)
    y := (q / w) * w
    fmt.Println(y)  // 10
}

Mitigations

  • Ensure that all tokens operations that must round results always benefit the system (application) and not users. In other words, always decide on the correct rounding direction. See Appendix G in the Umee audit report

  • Apply "multiplication before division" pattern. That is, instead of computing (x / y) * z do (x * z) / y

  • Observe issue #11783 for a replacement of the sdk.Dec type

External examples