From e41208d63b1ab0439c8d770659408f8664c92d95 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Mon, 5 May 2025 11:27:31 +0400 Subject: [PATCH 1/3] simplify float --- .gas-snapshot | 5 +- src/lib/format/LibFormatDecimalFloat.sol | 12 +-- .../lib/format/LibFormatDecimalFloat.t.sol | 97 ++++++------------- 3 files changed, 34 insertions(+), 80 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index 1e087fc9..9f562d57 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -169,8 +169,9 @@ LibDecimalFloatPowerTest:testPowers() (gas: 1269733) LibDecimalFloatPowerTest:testRoundTripFuzz(bytes32,bytes32) (runs: 5128, μ: 1231690, ~: 1228311) LibDecimalFloatPowerTest:testRoundTripSimple() (gas: 1422345) LibDecimalFloatSubTest:testSubPacked(bytes32,bytes32) (runs: 5128, μ: 8569, ~: 8256) -LibFormatDecimalFloatTest:testFormatDecimalRoundTrip(uint256) (runs: 5128, μ: 23814, ~: 18978) -LibFormatDecimalFloatTest:testFormatMem(bytes32) (runs: 5128, μ: 6767, ~: 6661) +LibFormatDecimalFloatTest:testFormatDecimalExamples() (gas: 7606) +LibFormatDecimalFloatTest:testFormatDecimalRoundTrip(uint256) (runs: 5128, μ: 24062, ~: 19314) +LibFormatDecimalFloatTest:testFormatDecimalRoundTripNegative(int256) (runs: 5128, μ: 18317, ~: 19264) LibLogTableBytesTest:testToBytesAntiLogTableDec() (gas: 154896) LibLogTableBytesTest:testToBytesAntiLogTableDecSmall() (gas: 159695) LibLogTableBytesTest:testToBytesLogTableDec() (gas: 138820) diff --git a/src/lib/format/LibFormatDecimalFloat.sol b/src/lib/format/LibFormatDecimalFloat.sol index 401d2cc7..f4366357 100644 --- a/src/lib/format/LibFormatDecimalFloat.sol +++ b/src/lib/format/LibFormatDecimalFloat.sol @@ -5,6 +5,7 @@ pragma solidity ^0.8.25; import {LibDecimalFloat, Float} from "../LibDecimalFloat.sol"; import {LibFixedPointDecimalFormat} from "rain.math.fixedpoint/lib/format/LibFixedPointDecimalFormat.sol"; +import {Strings} from "openzeppelin-contracts/contracts/utils/Strings.sol"; library LibFormatDecimalFloat { /// Format a decimal float as a string. @@ -12,10 +13,10 @@ library LibFormatDecimalFloat { /// and then formatting that as a string. /// In the future this may be extended to support a wider range of possible /// values. - /// @param signedCoefficient The signed coefficient of the decimal float. - /// @param exponent The exponent of the decimal float. + /// @param float The decimal float to format. /// @return The string representation of the decimal float. - function toDecimalString(int256 signedCoefficient, int256 exponent) internal pure returns (string memory) { + function toDecimalString(Float float) internal pure returns (string memory) { + (int256 signedCoefficient, int256 exponent) = LibDecimalFloat.unpack(float); string memory prefix = ""; if (signedCoefficient < 0) { prefix = "-"; @@ -24,9 +25,4 @@ library LibFormatDecimalFloat { uint256 decimal18Value = LibDecimalFloat.toFixedDecimalLossless(signedCoefficient, exponent, 18); return string.concat(prefix, LibFixedPointDecimalFormat.fixedPointToDecimalString(decimal18Value)); } - - function toDecimalString(Float float) internal pure returns (string memory) { - (int256 signedCoefficient, int256 exponent) = LibDecimalFloat.unpack(float); - return toDecimalString(signedCoefficient, exponent); - } } diff --git a/test/src/lib/format/LibFormatDecimalFloat.t.sol b/test/src/lib/format/LibFormatDecimalFloat.t.sol index 288ce0e9..de255d6e 100644 --- a/test/src/lib/format/LibFormatDecimalFloat.t.sol +++ b/test/src/lib/format/LibFormatDecimalFloat.t.sol @@ -14,26 +14,16 @@ contract LibFormatDecimalFloatTest is Test { using LibDecimalFloat for Float; using LibFormatDecimalFloat for Float; - function toDecimalStringExternal(int256 signedCoefficient, int256 exponent) external pure returns (string memory) { - return LibFormatDecimalFloat.toDecimalString(signedCoefficient, exponent); + function checkFormat(int256 signedCoefficient, int256 exponent, string memory expected) internal pure { + string memory actual = + LibFormatDecimalFloat.toDecimalString(LibDecimalFloat.packLossless(signedCoefficient, exponent)); + assertEq(actual, expected, "Formatted value mismatch"); } function toString(Float float) external pure returns (string memory) { return LibFormatDecimalFloat.toDecimalString(float); } - /// Check that the memory version matches the stack version. - function testFormatMem(Float float) external { - (int256 signedCoefficient, int256 exponent) = float.unpack(); - try this.toDecimalStringExternal(signedCoefficient, exponent) returns (string memory formatted) { - string memory actual = this.toString(float); - assertEq(formatted, actual, "Formatted value mismatch"); - } catch (bytes memory err) { - vm.expectRevert(err); - LibFormatDecimalFloat.toDecimalString(float); - } - } - /// Test round tripping a value through parse and format. function testFormatDecimalRoundTrip(uint256 value) external pure { value = bound(value, 0, uint256(int256(type(int224).max))); @@ -58,63 +48,30 @@ contract LibFormatDecimalFloatTest is Test { /// Test some specific examples. function testFormatDecimalExamples() external pure { // pos decs - assertEq( - LibFormatDecimalFloat.toDecimalString(123456789012345678901234567890, 0), "123456789012345678901234567890" - ); - assertEq( - LibFormatDecimalFloat.toDecimalString(123456789012345678901234567890, -1), "12345678901234567890123456789" - ); - assertEq( - LibFormatDecimalFloat.toDecimalString(123456789012345678901234567890, -2), "1234567890123456789012345678.9" - ); - assertEq( - LibFormatDecimalFloat.toDecimalString(123456789012345678901234567890, -3), "123456789012345678901234567.89" - ); - assertEq( - LibFormatDecimalFloat.toDecimalString(123456789012345678901234567890, -4), "12345678901234567890123456.789" - ); - assertEq( - LibFormatDecimalFloat.toDecimalString(123456789012345678901234567890, -5), "1234567890123456789012345.6789" - ); - assertEq( - LibFormatDecimalFloat.toDecimalString(123456789012345678901234567890, -6), "123456789012345678901234.56789" - ); + checkFormat(123456789012345678901234567890, 0, "123456789012345678901234567890"); + // checkFormat(123456789012345678901234567890, -1, "12345678901234567890123456789"); + // checkFormat(123456789012345678901234567890, -2, "1234567890123456789012345678.9"); + // checkFormat(123456789012345678901234567890, -3, "123456789012345678901234567.89"); + // checkFormat(123456789012345678901234567890, -4, "12345678901234567890123456.789"); + // checkFormat(123456789012345678901234567890, -5, "1234567890123456789012345.6789"); + // checkFormat(123456789012345678901234567890, -6, "123456789012345678901234.56789"); - // zeros - assertEq(LibFormatDecimalFloat.toDecimalString(0, 0), "0"); - assertEq(LibFormatDecimalFloat.toDecimalString(0, -1), "0"); - assertEq(LibFormatDecimalFloat.toDecimalString(0, -2), "0"); - assertEq(LibFormatDecimalFloat.toDecimalString(0, -3), "0"); - assertEq(LibFormatDecimalFloat.toDecimalString(0, 1), "0"); - assertEq(LibFormatDecimalFloat.toDecimalString(0, 2), "0"); - assertEq(LibFormatDecimalFloat.toDecimalString(0, 3), "0"); + // // zeros + // checkFormat(0, 0, "0"); + // checkFormat(0, -1, "0"); + // checkFormat(0, -2, "0"); + // checkFormat(0, -3, "0"); + // checkFormat(0, 1, "0"); + // checkFormat(0, 2, "0"); + // checkFormat(0, 3, "0"); - // neg decs - assertEq( - LibFormatDecimalFloat.toDecimalString(-123456789012345678901234567890, 0), "-123456789012345678901234567890" - ); - assertEq( - LibFormatDecimalFloat.toDecimalString(-123456789012345678901234567890, -1), "-12345678901234567890123456789" - ); - assertEq( - LibFormatDecimalFloat.toDecimalString(-123456789012345678901234567890, -2), - "-1234567890123456789012345678.9" - ); - assertEq( - LibFormatDecimalFloat.toDecimalString(-123456789012345678901234567890, -3), - "-123456789012345678901234567.89" - ); - assertEq( - LibFormatDecimalFloat.toDecimalString(-123456789012345678901234567890, -4), - "-12345678901234567890123456.789" - ); - assertEq( - LibFormatDecimalFloat.toDecimalString(-123456789012345678901234567890, -5), - "-1234567890123456789012345.6789" - ); - assertEq( - LibFormatDecimalFloat.toDecimalString(-123456789012345678901234567890, -6), - "-123456789012345678901234.56789" - ); + // // neg decs + // checkFormat(-123456789012345678901234567890, 0, "-123456789012345678901234567890"); + // checkFormat(-123456789012345678901234567890, -1, "-12345678901234567890123456789"); + // checkFormat(-123456789012345678901234567890, -2, "-1234567890123456789012345678.9"); + // checkFormat(-123456789012345678901234567890, -3, "-123456789012345678901234567.89"); + // checkFormat(-123456789012345678901234567890, -4, "-12345678901234567890123456.789"); + // checkFormat(-123456789012345678901234567890, -5, "-1234567890123456789012345.6789"); + // checkFormat(-123456789012345678901234567890, -6, "-123456789012345678901234.56789"); } } From e859c0dcb3a57b2d32f8460a432453f6b4447efe Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Mon, 5 May 2025 11:28:30 +0400 Subject: [PATCH 2/3] uncomment tests --- .../lib/format/LibFormatDecimalFloat.t.sol | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/test/src/lib/format/LibFormatDecimalFloat.t.sol b/test/src/lib/format/LibFormatDecimalFloat.t.sol index de255d6e..4874591b 100644 --- a/test/src/lib/format/LibFormatDecimalFloat.t.sol +++ b/test/src/lib/format/LibFormatDecimalFloat.t.sol @@ -49,29 +49,29 @@ contract LibFormatDecimalFloatTest is Test { function testFormatDecimalExamples() external pure { // pos decs checkFormat(123456789012345678901234567890, 0, "123456789012345678901234567890"); - // checkFormat(123456789012345678901234567890, -1, "12345678901234567890123456789"); - // checkFormat(123456789012345678901234567890, -2, "1234567890123456789012345678.9"); - // checkFormat(123456789012345678901234567890, -3, "123456789012345678901234567.89"); - // checkFormat(123456789012345678901234567890, -4, "12345678901234567890123456.789"); - // checkFormat(123456789012345678901234567890, -5, "1234567890123456789012345.6789"); - // checkFormat(123456789012345678901234567890, -6, "123456789012345678901234.56789"); + checkFormat(123456789012345678901234567890, -1, "12345678901234567890123456789"); + checkFormat(123456789012345678901234567890, -2, "1234567890123456789012345678.9"); + checkFormat(123456789012345678901234567890, -3, "123456789012345678901234567.89"); + checkFormat(123456789012345678901234567890, -4, "12345678901234567890123456.789"); + checkFormat(123456789012345678901234567890, -5, "1234567890123456789012345.6789"); + checkFormat(123456789012345678901234567890, -6, "123456789012345678901234.56789"); // // zeros - // checkFormat(0, 0, "0"); - // checkFormat(0, -1, "0"); - // checkFormat(0, -2, "0"); - // checkFormat(0, -3, "0"); - // checkFormat(0, 1, "0"); - // checkFormat(0, 2, "0"); - // checkFormat(0, 3, "0"); + checkFormat(0, 0, "0"); + checkFormat(0, -1, "0"); + checkFormat(0, -2, "0"); + checkFormat(0, -3, "0"); + checkFormat(0, 1, "0"); + checkFormat(0, 2, "0"); + checkFormat(0, 3, "0"); // // neg decs - // checkFormat(-123456789012345678901234567890, 0, "-123456789012345678901234567890"); - // checkFormat(-123456789012345678901234567890, -1, "-12345678901234567890123456789"); - // checkFormat(-123456789012345678901234567890, -2, "-1234567890123456789012345678.9"); - // checkFormat(-123456789012345678901234567890, -3, "-123456789012345678901234567.89"); - // checkFormat(-123456789012345678901234567890, -4, "-12345678901234567890123456.789"); - // checkFormat(-123456789012345678901234567890, -5, "-1234567890123456789012345.6789"); - // checkFormat(-123456789012345678901234567890, -6, "-123456789012345678901234.56789"); + checkFormat(-123456789012345678901234567890, 0, "-123456789012345678901234567890"); + checkFormat(-123456789012345678901234567890, -1, "-12345678901234567890123456789"); + checkFormat(-123456789012345678901234567890, -2, "-1234567890123456789012345678.9"); + checkFormat(-123456789012345678901234567890, -3, "-123456789012345678901234567.89"); + checkFormat(-123456789012345678901234567890, -4, "-12345678901234567890123456.789"); + checkFormat(-123456789012345678901234567890, -5, "-1234567890123456789012345.6789"); + checkFormat(-123456789012345678901234567890, -6, "-123456789012345678901234.56789"); } } From e4946e149af1c074f24a02f50cf89f5dd22794b9 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Mon, 5 May 2025 13:37:38 +0400 Subject: [PATCH 3/3] lint --- src/lib/format/LibFormatDecimalFloat.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib/format/LibFormatDecimalFloat.sol b/src/lib/format/LibFormatDecimalFloat.sol index f4366357..b104d408 100644 --- a/src/lib/format/LibFormatDecimalFloat.sol +++ b/src/lib/format/LibFormatDecimalFloat.sol @@ -5,7 +5,6 @@ pragma solidity ^0.8.25; import {LibDecimalFloat, Float} from "../LibDecimalFloat.sol"; import {LibFixedPointDecimalFormat} from "rain.math.fixedpoint/lib/format/LibFixedPointDecimalFormat.sol"; -import {Strings} from "openzeppelin-contracts/contracts/utils/Strings.sol"; library LibFormatDecimalFloat { /// Format a decimal float as a string.