paint-brush
How to Bypass the Integer Division Error in Smart Contracts by@dansierrasam79
1,822 reads
1,822 reads

How to Bypass the Integer Division Error in Smart Contracts

by Daniel ChakrabortyFebruary 20th, 2023
Read on Terminal Reader
Read this story w/o Javascript

Too Long; Didn't Read

When you begin learning Python or Java, you will use the float data type. In Solidity, you’d be using numbers of either the signed or unsigned integer type. The result that you obtain will not be the same, since Solidity does not support the floatData type.
featured image - How to Bypass the Integer Division Error in Smart Contracts
Daniel Chakraborty HackerNoon profile picture

We’ve all learned about floating point numbers in school. As opposed to integers that have no decimal points.


One does not need to be a math whiz to know that the number five is an integer while 5.43 is a floating point number. Clearly, we’re all familiar with the decimal point that is a clear point of differentiation between the two.


Of course, it’s no surprise that floats are used in programming languages and are even classified as a distinct primitive data type because of how necessary it is to daily computation.

Using Floating Point Numbers in Programming Languages

When you begin learning Python or Java, you will use the float data type. Particularly, when you carry out the division operation between two floating point numbers themselves.


In Python, even if you do not have to declare a floating point number, dividing two of these numbers can result in a number of the same data type, as shown below:


Python program to divide two floating point numbers


We can produce the same result in Java too, even if we have to explicitly declare the ‘float’ primitive data type for all variables used.


Java program to divide two floating point numbers


As one can tell, this kind of computation is necessary for a number of applications, and which is precisely why operations with floating point numbers are available as a feature in both these programming languages.


Quite differently, if you’ve been learning Solidity, you should have noticed that it does not include the floating point number data type.

How Solidity Performs Transactions without Floating Point Numbers

Instead, if you’ve written any code in Solidity, you’d be using numbers of either the signed or unsigned integer type.


So, if you want to perform the same computation - five divided by two - as shown in the previous section, here’s how it will look, as part of a smart contract:


Integer Division Error - Smart Contract in Solidity


However, the result that you obtain will not be the same, since Solidity does not support the float data type. At least, not just yet.


getResult function


Specifically, Solidity will round the result towards zero. Which, in this case, and as shown above, will result in a value of two. Think of this as the modulo operation on both numbers.


While in normal circumstances, this shouldn’t matter much, there are times when the result can lead to an error in computation. Which is why it is recommended to avoid or postpone the division operation as much as possible.

Your First Look at the Integer Division Error

Even if the BODMAS rule in school has required all math students to perform the division computation before multiplication, this isn’t recommended if you have to perform integer division in Solidity.


Let’s find out why, with this simple example, that carries out multiplication and division with three numbers:


Multiply and divide Three Numbers - Smart Contract in Solidity


If you enter the numbers one, three and five when deploying the smart contract, you should get the same value for the getResult and getResult2 functions, right?


If you use a simple calculator, you should get a float value of 1.666, which translates to one in Solidity, thanks to the absence of the float values.


Unfortunately, this isn’t what happens, when you check the results of the getResult and getResult2 functions, as shown below:


getResult & getResult2 results


If we perform the division first, we get a final result of zero. As opposed to the expected value of one, when you postpone that operation to the end in getResult function.


As you can tell, even if we’ve computed this value by anticipating the absence of float values, there’s still an error that crops up that can cause a loss in precision. Which, in turn, can translate to an economic loss that can be bypassed easily.


So, how do we prevent the integer division error? More importantly, how do we increase precision for our computation? Let’s find out the three most common ways to do this.

3 Ways to Prevent the Integer Division Error

Given that there are a number of approaches to circumventing this error, let’s begin with the simplest fix, and look at a couple more before calling it a day.


Method #1: Use a multiplier

Now, along with placing the division operation last, one way of ensuring that you do not end up with errors or imprecise values is by using a multiplier. In the example below, we will use a multiplier of 100 along with the same three numbers used earlier.


Using a multiplier - Smart Contract in Solidity


Now, when you deploy the contract with the following code and call both functions, this is the output:

Using a multiplier - getResult and getResult2 values


Since the desired output is 1.666 or 166/100, we can see that getResult2 value provides us with the necessary accuracy when the multiplier works in conjunction with the three numbers. Of course, if you do not use the multiplier as in the getResult function, you will obtain 1.


Where 0.666 is truncated from the result, as expected by default when you use Solidity. So, to retrieve this value, all you have to do is divide the result by the multiplier.


As you might know, Solidity moves towards zero when it comes to rounding off in the case of both signed and unsigned integers, so this fix works in the case of signed integers too, once you deploy and run the code below with the arguments minus one, three and five:


Using a multiplier for signed integers - Smart Contract in Solidity


When it comes to the values generated by the functions for signed integers, here they are:


Using a multiplier for signed integers - Smart Contract in Solidity


Clearly, we are able to maintain precision for signed integers as well, using a multiplier. Although, there’s a precise way to round off signed integers that we will look at next.


Method #2: Use floor division for signed integers

Now, if one looks at the number line below, the result of performing integer division between two unsigned integers is rounded closer to zero. As in the case of obtaining 1.666, Solidity rounds it off to 1, which is a smaller number.


The number line


However, when it comes to signed integers, a result of -1.6666 will be rounded off to -1, which is the larger of the two numbers. So, floor division must be applied here as opposed to rounded-to-zero division that is implemented in Solidity by default. For the sake of precision, of course.


Performing floor division for signed integers


If the float data type was available, the value of -1.666 would be computed. While Solidity would round this down to -1, applying floor division to signed integers will reduce it to -2.


When you call the getResult and getResult2 functions, we obtain the value as shown below for the arguments minus one, three & five:


getResult2 gives the right floor division results


As you can tell, getResult computes the value using the rounded-towards-zero approach while getResult2 rounds it off to the smallest integer here, by virtue of floor division.


Method #3: Use the ABDKMath64x64 library

Now, for the final method, we will use the ABDKMath64x64 library, which converts the result of the division operations into fixed point numbers.


Yet again, using this library is said to improve accuracy as opposed to the rounding towards zero method that is available by default in Solidity. In order to understand the output, let us compare the results of the add with the div function, as shown below:


Using the ABDK library


When you add the arguments 1, 1 and 1 when deploying the smart contract, you obtain the values, as shown below:

Using the ABDK library - Output


It should come as no surprise that the add function returns an integer value of two, with the three arguments adding up to that much. As for the div function, an int 128 value is returned that represents a signed 64.64-bit fixed point number and that you can perform the usual number operations with.

Other Integer Division Libraries to Consider

Of course, the ABDKMath64x64 library isn’t the only one that can be used to improve accuracy apart from preventing the integer division error.


There are several others with a few examples being Fixidity, DSMath and the BANKEX libraries that use different number formats. Number formats that are different from the 64.64-bit fixed point number format used in the example above. So, while these libraries might seem useful to explore, please remember that their number formats will not work with any of the other libraries available.