Add multiple base support to DecimalMath.sol
alcueca opened this issue · comments
Implement a variation of DecimalMath with a variable base. It probably goes like this:
/// @dev Multiplies x and y, assuming they are both fixed point with `decimals` decimals.
function muld(uint256 x, uint256 y, uint8 decimals) internal pure returns (uint256) {
return x.mul(y).div(10**decimals);
}
/// @dev Divides x between y, assuming they are both fixed point with `decimals` decimals.
function divd(uint256 x, uint256 y, uint8 decimals) internal pure returns (uint256) {
return x.mul(10**decimals).div(y);
}
Then make decimalOne
return 10 ** decimals
. (Maybe call it unit instead of decimalOne
).
Maintain the original muld
and divd
functions, which call to muld(x, y, 18)
and divd(x, y, 18)
.
Then please do a gas comparison between the original DecimalMath, and the new one.
Here's the gas comparison:
Before,
muld: ~23000 gas
divd: ~23000 gas
After,
muld: ~23000
divd: ~23000
Seemingly, there's no much difference.
However, there is a small issue with the approach you suggested: typechain does not support function overloading (sometimes it works, sometimes it doesn't). Therefore, testing the new DecimalMath was deficient. It works, for sure, but we won't have the complete tests.
The gas costs you are seeing there are mostly the base transaction costs, which I guess is storing one word to memory.
To get a true comparison of the costs please code in the mock contract a loop to execute each operation 10000 times. If possible do the transaction so that nothing is saved into storage.
I'm surprised function overloading doesn't work in typechain. You can always code different function names in the contract proxy to test, though.
Please move the DecimalMath.sol
changes to its own PR branching from master
, so that it can be considered in isolation.
Alright, so the loop with 10000
iterations went on and on, so I put a loop with just 1000
. Here are the results:
Before,
muld: 501977
divd: 504870
After,
muld: 621074
muld with decimals: 572150
divd: 613001
divd with decimals: 575196
Cool, so we know that the change adds about a 17% gas to each operation (from about 500 gas to 572 gas).
A regular addition uses about 10 gas, and an addition using SafeMath uses about 90.
I'll review the code on the PR, thank you 👍