Strings.sol 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. // SPDX-License-Identifier: MIT
  2. // OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)
  3. pragma solidity ^0.8.0;
  4. /**
  5. * @dev String operations.
  6. */
  7. library Strings {
  8. bytes16 private constant _SYMBOLS = "0123456789abcdef";
  9. uint8 private constant _ADDRESS_LENGTH = 20;
  10. /**
  11. * @dev Converts a `uint256` to its ASCII `string` decimal representation.
  12. */
  13. function toString(uint256 value) internal pure returns (string memory) {
  14. unchecked {
  15. uint256 length = 1;
  16. // compute log10(value), and add it to length
  17. uint256 valueCopy = value;
  18. if (valueCopy >= 10**64) {
  19. valueCopy /= 10**64;
  20. length += 64;
  21. }
  22. if (valueCopy >= 10**32) {
  23. valueCopy /= 10**32;
  24. length += 32;
  25. }
  26. if (valueCopy >= 10**16) {
  27. valueCopy /= 10**16;
  28. length += 16;
  29. }
  30. if (valueCopy >= 10**8) {
  31. valueCopy /= 10**8;
  32. length += 8;
  33. }
  34. if (valueCopy >= 10**4) {
  35. valueCopy /= 10**4;
  36. length += 4;
  37. }
  38. if (valueCopy >= 10**2) {
  39. valueCopy /= 10**2;
  40. length += 2;
  41. }
  42. if (valueCopy >= 10**1) {
  43. length += 1;
  44. }
  45. // now, length is log10(value) + 1
  46. string memory buffer = new string(length);
  47. uint256 ptr;
  48. /// @solidity memory-safe-assembly
  49. assembly {
  50. ptr := add(buffer, add(32, length))
  51. }
  52. while (true) {
  53. ptr--;
  54. /// @solidity memory-safe-assembly
  55. assembly {
  56. mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
  57. }
  58. value /= 10;
  59. if (value == 0) break;
  60. }
  61. return buffer;
  62. }
  63. }
  64. /**
  65. * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
  66. */
  67. function toHexString(uint256 value) internal pure returns (string memory) {
  68. unchecked {
  69. uint256 length = 1;
  70. // compute log256(value), and add it to length
  71. uint256 valueCopy = value;
  72. if (valueCopy >= 1 << 128) {
  73. valueCopy >>= 128;
  74. length += 16;
  75. }
  76. if (valueCopy >= 1 << 64) {
  77. valueCopy >>= 64;
  78. length += 8;
  79. }
  80. if (valueCopy >= 1 << 32) {
  81. valueCopy >>= 32;
  82. length += 4;
  83. }
  84. if (valueCopy >= 1 << 16) {
  85. valueCopy >>= 16;
  86. length += 2;
  87. }
  88. if (valueCopy >= 1 << 8) {
  89. valueCopy >>= 8;
  90. length += 1;
  91. }
  92. // now, length is log256(value) + 1
  93. return toHexString(value, length);
  94. }
  95. }
  96. /**
  97. * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
  98. */
  99. function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
  100. bytes memory buffer = new bytes(2 * length + 2);
  101. buffer[0] = "0";
  102. buffer[1] = "x";
  103. for (uint256 i = 2 * length + 1; i > 1; --i) {
  104. buffer[i] = _SYMBOLS[value & 0xf];
  105. value >>= 4;
  106. }
  107. require(value == 0, "Strings: hex length insufficient");
  108. return string(buffer);
  109. }
  110. /**
  111. * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
  112. */
  113. function toHexString(address addr) internal pure returns (string memory) {
  114. return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
  115. }
  116. }