10x Better Fixed Point Math in Solidity

Use this library to spend a tenth of the gas on your fixed point math.

Save time and money for your users.

“Technology is nothing. What’s important is that you have a faith in people, that they’re basically good and smart, and if you give them tools, they’ll do wonderful things with them. “— Steve Jobs

Introduction

Recently we published a fixed point math library for ethereum smart contracts. We were very proud of pushing the boundaries of smart contract development and we were featured in the Medium frontpage for the blockchain and cryptocurrency topics.

Well, this fixed point math library for solidity smart contracts from ABDK consulting is even better. It uses a fraction of the gas to run most methods, as well as supporting more functions such as square roots and exponentials.

The code itself is also cleaner, thanks to a number representation that allows to detect overflows with less effort. In comparison, our implementation now feels quite heavy handed.

Code Analysis

The main difference is that the ABDK library represents fixed point numbers in a 64.64-bit format stored in an int128. This number representation is explained in the code itself.

/**

* Smart contract library of mathematical functions operating with

* signed 64.64-bit fixed point numbers. Signed 64.64-bit fixed point

* number is basically a simple fraction whose numerator is signed

* 128-bit integer and denominator is 2**64. As long as denominator

* is always the same, there is no need to store it, thus in Solidity

* signed 64.64-bit fixed point numbers are represented by int128

* type holding only the numerator.

*/

This allows to add or multiply two int128 fixed point numbers storing the result into an int256, making an intermediate overflow impossible. Once the multiplication is complete if the resulting number is beyond ± 2**128 we will know that it won’t fit again in our 64.64 bit representation and we just revert.

Using a binary representation also allows using bit shift operators, which I assume must be much cheaper to use than decimal operators.

How gorgeous is this implementation of an overflow-protected multiplication:

function mul (int128 x, int128 y) internal pure returns (int128) {

int256 result = int256(x) * y >> 64;

require (result >= MIN_64x64 && result <= MAX_64x64);

return int128 (result);

}

The only limitation is that ABDK can’t represent values above 2⁶⁴ as-is. In the cryptocurrency world than means that it can’t process token operations* with more than 19 digits, and that it can’t represent amounts above 18.4 billion tokens either. Tweaking the 64.64 representation can increase the limit of the integer part by reducing the fractional part and viceversa.

* Edit: Not true, the limits in ABDK.Math have no impact on which tokens can be processed by the library. See comments.

Performance Testing

Being clever pays off. Below there is a comparison of the gas required to run additions, multiplications and logarithms in both Fixidity and ABDK. To find these values I wrapped the calls to the library in a contract that would return the result as an event. This includes library calls in a transaction so that they have a gas cost.

pragma solidity ^0.5.0;

import “../ABDKMath64x64.sol”; contract ABDKMathMock {

event ValueCalculated(int256 output); … function add (int128 x, int128 y) public {

emit ValueCalculated(ABDKMath64x64.add(x, y));

} … }

To arrive to the actual method cost I had to adjust the values returned by eth-gas reporter, subtracting 21000 gas for the base transaction cost and 2000 gas for the event. Below there is the report from eth-gas-reporter:

Gas use comparison between ABDK and Fixidity.

On average, all operations with ABDK are a 10% of the gas cost of using Fixidity and I assume that the computational performance is also better. For iterative methods and high values the differences are even larger.

Conclusion

There are genuine uses for fixed point math in smart contracts, despite the increased complexity and cost. Mikhail Vladimirov implemented for ABDK a very clever and efficient library that dramatically reduces the cost of using fixed point math in smart contracts.

One of the concerns we had when implementing CementDAO was that calculating the stability was slow and expensive. Other competing stablecoins had stability mechanisms that were less advanced, but at the same time that gave them better performance.

In our next product iteration we will have a better stability mechanism at a dramatically cheaper cost. Don’t you love open source?