I agree, a general fixed point math library may have it’s risks, although I’d definitely support some sort of library to support fractions! Like you said there are quite a few ways to go about it but I think that’s something the community would really appreciate
While it is generally a good approach that might be helpful for developers to know, why would you want to use such an approach in the PaymentSplitter? As you said there might easily be a 0.01% remainder which is considerably larger than the remainder that the current implementation of PaymentSplitter has.
I work for CementDAO and we happen to have implemented a fixed point math library for solidity, with support for basic arithmetic including multiplication and division, as well as logarithms. We have implemented it with full protection for overflows, found the numerical limits for safe operation, and tested all functions extensively (probably more than 100% coverage).
We are planning to release this library as open source when we release CementDAO, but if you would be interested in having a look we would be happy to facilitate that. It would be awesome if we could have your feedback and advice on how to make the library more useful for the community.
To be clear, PaymentSplitter doesn't have a remainder that results from numerical error. The only remainder is that which cannot be split between the shareholders. There's very simple scenarios where this happens: if you and me are splitting payments 50-50, and we receive 3 wei, there is 1 wei that we can't split, so it will stay in the contract. It's always very few wei that will remain. Even then, it's possible to "top up" the contract balance so that it is fully emptied.
This is how percentages should be always done IMO, and we should try to give tools for people to replicate that in their contracts. I'm not sure how much this approach can be generalized, though.
Because of that, my main interest in this thread is collecting examples where percentages and/or fixed point were needed, to evaluate how different possible libraries would help.
With each arithmetical operation we made sure it throws on overflow.
Additionally to that we calculated what are the bounds within which an arithmetical operation won’t overflow. For example we know that add will overflow (and throw) if the result is greater than 2**255-1 (we are using int256). From this we can assert that all add operations where both operands are smaller than (2**255-1)/2 will never throw.
We implemented those limits because sometimes you might not want to wait to see if an operation throws and instead stop the user at the frontend when it’s going towards a risky situation so that you have a more predictable experience.
I haven't been following development closely, but seriously doubt this is a pressing concern for them, considering they're working on much more generally useful features.
This would be useful for many projects yes. Rather than using basis points (4 decimal places) using 18 decimal places seems to be the standard for many protocols including Maker and dYdX
There are a number of approaches with regards to how many decimal places. If you are going to do arithmetic with currencies then using as many decimal points as your fractional monetary unit makes sense. That would be 2 decimals for dollars, 18 decimals for bitcoin.
If you are going to do more complex arithmetic (we had to do logarithm curves) then the more decimals you use the more precision you get for iterative methods (log, exp, sqrt). Our initial setup was for 36 decimals to get a really good approximation of the curves.
We only included limited support for operating on fixed point numbers of different decimals, because we didn’t need more, but it would be relatively easy to pack an uint8 denoting the decimals used into a Struct that represents the fixed point value. That way a fixed point library would be flexible enough for applications needing any number of decimals.
We just released Solidity library for signed 64.64-bit fixed point math, i.e. for binary rather than decimal fixed point: https://github.com/abdk-consulting/abdk-libraries-solidity
It has basic arithmetic, exponentiation, logarithm, square root, etc.
Hey,
My team in LimeChain had to implement sqrt/power/ln functions in order to run the Bonding Curve concept.
The problem with these functions in solidity is actually the missing double type (The big pain ) That is why we gave a chance to Vyper.
And here are the results:
SQRT Function:
Vyper already has an integrated sqrt function thanks to @Perseverance(Github name) -> returns up to 10 digits fraction
Library I mentioned in my previous comment is able to calculate sqrt, x^y, and ln x in Solidity with 64-bit precision (about 18 decimals) and uses less gas:
sqrt: less then 2K gas
2^x: less than 2K gas
log2 x: about 10K gas
ln x: about 10K gas
x^y is calculated as 2^(y * log2 x) and thus consumes about 12K gas.
Strictly speaking, ABDKMathQuad is a floating point library rather than fixed point. Anyway, glad to know that you found the library helpful.
The library is being developed by ABDK Consulting using proprietary methodology and tools, those ABDK uses for all its projects, and only the final result is published on GitHub. Tests will not be useful without the tools needed to run them, thus tests are not published.
I’ve recommended using ABDKMath several times, and my clients have always rejected it on the basis of the non-standard license. Have you considered releasing it under MIT or Apache?
This should be enough for most developers out there. Most people in DeFi just want to calculate simple proportions of token amounts. If you need logarithms and things like that there are other options above.
Since I realized that everyone is used to ether and wei (which is a fixed point representation of its own) I made the library consistent with that, so it is harder to misuse.
The whole thing is about 50 lines, there can’t be many bugs in there. It uses SafeMath for overflow, so in a way it is a nice extension of it.
The time has finally come! I created a post on Designing Fixed Point Math in OpenZeppelin Contracts, sharing our thoughts after taking a look at the different libraries out there and asking for feedback from you, their actual users.