Browse Source

Add Strings.toString for signed integers (#3773)

Co-authored-by: Hadrien Croubois <hadrien.croubois@gmail.com>
Co-authored-by: Gbolahan <89295500+GbolahanAnon@users.noreply.github.com>
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
ganone 2 years ago
parent
commit
8335676b0e
4 changed files with 49 additions and 6 deletions
  1. 1 0
      CHANGELOG.md
  2. 4 0
      contracts/mocks/StringsMock.sol
  3. 8 0
      contracts/utils/Strings.sol
  4. 36 6
      test/utils/Strings.test.js

+ 1 - 0
CHANGELOG.md

@@ -8,6 +8,7 @@
  * `Initializable`: optimize `_disableInitializers` by using `!=` instead of `<`. ([#3787](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3787))
  * `Math`: optimize `log256` rounding check. ([#3745](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3745))
  * `Strings`: add `equal` method. ([#3774](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3774))
+ * `Strings`: add `toString` method for signed integers. ([#3773](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3773))
 
 ### Deprecations
 

+ 4 - 0
contracts/mocks/StringsMock.sol

@@ -9,6 +9,10 @@ contract StringsMock {
         return Strings.toString(value);
     }
 
+    function toString(int256 value) public pure returns (string memory) {
+        return Strings.toString(value);
+    }
+
     function toHexString(uint256 value) public pure returns (string memory) {
         return Strings.toHexString(value);
     }

+ 8 - 0
contracts/utils/Strings.sol

@@ -4,6 +4,7 @@
 pragma solidity ^0.8.0;
 
 import "./math/Math.sol";
+import "./math/SignedMath.sol";
 
 /**
  * @dev String operations.
@@ -37,6 +38,13 @@ library Strings {
         }
     }
 
+    /**
+     * @dev Converts a `int256` to its ASCII `string` decimal representation.
+     */
+    function toString(int256 value) internal pure returns (string memory) {
+        return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value))));
+    }
+
     /**
      * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
      */

+ 36 - 6
test/utils/Strings.test.js

@@ -10,7 +10,7 @@ contract('Strings', function (accounts) {
   });
 
   describe('toString', function () {
-    for (const [ key, value ] of Object.entries([
+    const values = [
       '0',
       '7',
       '10',
@@ -29,13 +29,43 @@ contract('Strings', function (accounts) {
       '12345678901234567890123456789012345678901234567890',
       '123456789012345678901234567890123456789012345678901234567890',
       '1234567890123456789012345678901234567890123456789012345678901234567890',
-    ].reduce((acc, value) => Object.assign(acc, { [value]: new BN(value) }), {
-      MAX_UINT256: constants.MAX_UINT256.toString(),
-    }))) {
-      it(`converts ${key}`, async function () {
+    ];
+
+    describe('uint256', function () {
+      it('converts MAX_UINT256', async function () {
+        const value = constants.MAX_UINT256;
         expect(await this.strings.methods['toString(uint256)'](value)).to.equal(value.toString(10));
       });
-    }
+
+      for (const value of values) {
+        it(`converts ${value}`, async function () {
+          expect(await this.strings.methods['toString(uint256)'](value)).to.equal(value);
+        });
+      }
+    });
+
+    describe('int256', function () {
+      it('converts MAX_INT256', async function () {
+        const value = constants.MAX_INT256;
+        expect(await this.strings.methods['toString(int256)'](value)).to.equal(value.toString(10));
+      });
+
+      it('converts MIN_INT256', async function () {
+        const value = constants.MIN_INT256;
+        expect(await this.strings.methods['toString(int256)'](value)).to.equal(value.toString(10));
+      });
+
+      for (const value of values) {
+        it(`convert ${value}`, async function () {
+          expect(await this.strings.methods['toString(int256)'](value)).to.equal(value);
+        });
+
+        it(`convert negative ${value}`, async function () {
+          const negated = new BN(value).neg();
+          expect(await this.strings.methods['toString(int256)'](negated)).to.equal(negated.toString(10));
+        });
+      }
+    });
   });
 
   describe('toHexString', function () {