41

In Solidity, is there a way I can convert my int to string ?

Example:

pragma solidity ^0.4.4;

contract someContract {

    uint i;

    function test() pure returns (string) {

      return "Here and Now is Happiness!";

    }

    function love() pure returns(string) {

        i = i +1;

        return "I love " + functionname(i) + " persons" ;
    }



}

What is functionname?Thanks!

SomeDutchGuy
  • 2,249
  • 4
  • 16
  • 42
Bob Zheng
  • 825
  • 4
  • 14
  • 25

8 Answers8

90
solidity ^0.8.0

import "@openzeppelin/contracts/utils/Strings.sol";

Strings.toString(myUINT)

works for me.

https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Strings.sol#L15-L35

JR White
  • 1,001
  • 7
  • 2
39

UPDATE for Solidity 0.8.0:

The uint2str() function from https://github.com/provable-things/ethereum-api/blob/master/provableAPI_0.6.sol is now outdated, and will not work, but here is the updated code, that uses solidity 0.8.0: (there was an Overflow bug in the last version but solidity <0.8.0 ignored that as it did not affect the answer, but that now throws an error) byte was also changed to bytes1 and +,-,* and so on work like they would from the SafeMath library.

function uint2str(uint _i) internal pure returns (string memory _uintAsString) {
        if (_i == 0) {
            return "0";
        }
        uint j = _i;
        uint len;
        while (j != 0) {
            len++;
            j /= 10;
        }
        bytes memory bstr = new bytes(len);
        uint k = len;
        while (_i != 0) {
            k = k-1;
            uint8 temp = (48 + uint8(_i - _i / 10 * 10));
            bytes1 b1 = bytes1(temp);
            bstr[k] = b1;
            _i /= 10;
        }
        return string(bstr);
    }
Barnabas Ujvari
  • 399
  • 3
  • 5
8

The two post here are giving the responses :

https://ethereum.stackexchange.com/questions/10811/solidity-concatenate-uint-into-a-string

https://ethereum.stackexchange.com/questions/10932/how-to-convert-string-to-int

function uintToString(uint v) constant returns (string str) {
        uint maxlength = 100;
        bytes memory reversed = new bytes(maxlength);
        uint i = 0;
        while (v != 0) {
            uint remainder = v % 10;
            v = v / 10;
            reversed[i++] = byte(48 + remainder);
        }
        bytes memory s = new bytes(i + 1);
        for (uint j = 0; j <= i; j++) {
            s[j] = reversed[i - j];
        }
        str = string(s);
    }

Regards

Thogerar
  • 339
  • 1
  • 7
  • 2
    This variant was buggy when I tested it, solution from Oraclize https://github.com/oraclize/ethereum-api/blob/master/oraclizeAPI_0.5.sol may be better: function uint2str(uint i) internal pure returns (string){ if (i == 0) return "0"; uint j = i; uint length; while (j != 0){ length++; j /= 10; } bytes memory bstr = new bytes(length); uint k = length - 1; while (i != 0){ bstr[k--] = byte(48 + i % 10); i /= 10; } return string(bstr); } – Dmitriy Vinokurov Feb 26 '18 at 15:31
  • 1
    Yeah I agree that the version in the answer did not work for me, but the one provided in https://github.com/provable-things/ethereum-api/blob/master/oraclizeAPI_0.5.sol#L1045 did, as pointed out by Dmitriy above here. – Diiaablo Jun 12 '20 at 06:44
  • Also: solc 0.7.0 does not like `byte(48 + remainder)`. Cannot explicitly convert uint256 to bytes1. – Buzz Moschetti Aug 27 '20 at 12:58
5

Concrete_Buddhas answer does not work in solidity 0.8.0. This is a revised version:

 function uint2str(
  uint256 _i
)
  internal
  pure
  returns (string memory str)
{
  if (_i == 0)
  {
    return "0";
  }
  uint256 j = _i;
  uint256 length;
  while (j != 0)
  {
    length++;
    j /= 10;
  }
  bytes memory bstr = new bytes(length);
  uint256 k = length;
  j = _i;
  while (j != 0)
  {
    bstr[--k] = bytes1(uint8(48 + j % 10));
    j /= 10;
  }
  str = string(bstr);
}
Tadej Vengust
  • 1,351
  • 4
  • 18
  • 35
2

If your uint is coming from originally encoding a string into uint

string(abi.encode(myUint))
Elyx0
  • 349
  • 2
  • 10
1

The provable-things code suggested in the comments to the accepted answer worked for me, but my linter threw a warning namely: "uintToStr": Avoid assigning to function parameters. [security/no-assign-params]. The below changes the original code slightly to correct this (reassigning the parameter _i to another variable called number):

    /// @notice converts number to string
    /// @dev source: https://github.com/provable-things/ethereum-api/blob/master/oraclizeAPI_0.5.sol#L1045
    /// @param _i integer to convert
    /// @return _uintAsString
    function uintToStr(uint _i) internal pure returns (string memory _uintAsString) {
        uint number = _i;
        if (number == 0) {
            return "0";
        }
        uint j = number;
        uint len;
        while (j != 0) {
            len++;
            j /= 10;
        }
        bytes memory bstr = new bytes(len);
        uint k = len - 1;
        while (number != 0) {
            bstr[k--] = byte(uint8(48 + number % 10));
            number /= 10;
        }
        return string(bstr);
    }
Concrete_Buddha
  • 556
  • 4
  • 16
0

If you need to optionally convert to scientific notation, for instance for a more compact number representation, here's a modifed version for that purpose:

function uintToString(uint v, bool scientific) public pure returns (string memory str) {

    if (v == 0) {
        return "0";
    }

    uint maxlength = 100;
    bytes memory reversed = new bytes(maxlength);
    uint i = 0;
    
    while (v != 0) {
        uint remainder = v % 10;
        v = v / 10;
        reversed[i++] = byte(uint8(48 + remainder));
    }

    uint zeros = 0;
    if (scientific) {
        for (uint k = 0; k < i; k++) {
            if (reversed[k] == '0') {
                zeros++;
            } else {
                break;
            }
        }
    }

    uint len = i - (zeros > 2 ? zeros : 0);
    bytes memory s = new bytes(len);
    for (uint j = 0; j < len; j++) {
        s[j] = reversed[i - j - 1];
    }

    str = string(s);

    if (scientific && zeros > 2) {
        str = string(abi.encodePacked(s, "e", uintToString(zeros, false)));
    }
}

Some unit tests:

function testUintToString() public {

    Assert.equal(Utils.uintToString(0, true), '0', '0');
    Assert.equal(Utils.uintToString(1, true), '1', '1');
    Assert.equal(Utils.uintToString(123, true), '123', '123');
    Assert.equal(Utils.uintToString(107680546035, true), '107680546035', '107680546035');
    Assert.equal(Utils.uintToString(1e9, true), '1e9', '1e9');
    Assert.equal(Utils.uintToString(1 ether, true), '1e18', '1 ether');
    Assert.equal(Utils.uintToString(550e8, true), '55e9', '55e9');
}

The code snippets above are compatible with solidity 0.6.0.

Thomas C. G. de Vilhena
  • 13,819
  • 3
  • 50
  • 44
0

While the accepted answer seems correct, it is quite inefficient on large numbers. Here is how I would do it:

function itoa32 (uint x) private pure returns (uint y) {
    unchecked {
        require (x < 1e32);
        y = 0x3030303030303030303030303030303030303030303030303030303030303030;
        y += x % 10; x /= 10;
        y += x % 10 << 8; x /= 10;
        y += x % 10 << 16; x /= 10;
        y += x % 10 << 24; x /= 10;
        y += x % 10 << 32; x /= 10;
        y += x % 10 << 40; x /= 10;
        y += x % 10 << 48; x /= 10;
        y += x % 10 << 56; x /= 10;
        y += x % 10 << 64; x /= 10;
        y += x % 10 << 72; x /= 10;
        y += x % 10 << 80; x /= 10;
        y += x % 10 << 88; x /= 10;
        y += x % 10 << 96; x /= 10;
        y += x % 10 << 104; x /= 10;
        y += x % 10 << 112; x /= 10;
        y += x % 10 << 120; x /= 10;
        y += x % 10 << 128; x /= 10;
        y += x % 10 << 136; x /= 10;
        y += x % 10 << 144; x /= 10;
        y += x % 10 << 152; x /= 10;
        y += x % 10 << 160; x /= 10;
        y += x % 10 << 168; x /= 10;
        y += x % 10 << 176; x /= 10;
        y += x % 10 << 184; x /= 10;
        y += x % 10 << 192; x /= 10;
        y += x % 10 << 200; x /= 10;
        y += x % 10 << 208; x /= 10;
        y += x % 10 << 216; x /= 10;
        y += x % 10 << 224; x /= 10;
        y += x % 10 << 232; x /= 10;
        y += x % 10 << 240; x /= 10;
        y += x % 10 << 248;
    }
}

function itoa (uint x) internal pure returns (string memory s) {
    unchecked {
        if (x == 0) return "0";
        else {
            uint c1 = itoa32 (x % 1e32);
            x /= 1e32;
            if (x == 0) s = string (abi.encode (c1));
            else {
                uint c2 = itoa32 (x % 1e32);
                x /= 1e32;
                if (x == 0) {
                    s = string (abi.encode (c2, c1));
                    c1 = c2;
                } else {
                    uint c3 = itoa32 (x);
                    s = string (abi.encode (c3, c2, c1));
                    c1 = c3;
                }
            }
            uint z = 0;
            if (c1 >> 128 == 0x30303030303030303030303030303030) { c1 <<= 128; z += 16; }
            if (c1 >> 192 == 0x3030303030303030) { c1 <<= 64; z += 8; }
            if (c1 >> 224 == 0x30303030) { c1 <<= 32; z += 4; }
            if (c1 >> 240 == 0x3030) { c1 <<= 16; z += 2; }
            if (c1 >> 248 == 0x30) { z += 1; }
            assembly {
                let l := mload (s)
                s := add (s, z)
                mstore (s, sub (l, z))
            }
        }
    }
}

Explanation

The itoa32 function converts a number below 10^32 into exactly 32 digits, padding it with zeros if necessary.

The itoa function calls the itoa32 up to three times to convert an arbitrary 256-bit number, then concatenates the results and removes leading zeros. It uses binary search to find out the exact number of leading zeros to be removed and removes leading zeros from a string in-place.

Mikhail Vladimirov
  • 13,572
  • 1
  • 38
  • 40