├── .gitignore ├── .prettierignore ├── LICENSE ├── README.md ├── contracts ├── LibUintToString.sol └── TestUintToString.sol ├── gas_benchmark.txt ├── hardhat.config.js ├── package-lock.json ├── package.json └── test └── sample-test.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | 4 | #Hardhat files 5 | cache 6 | artifacts 7 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | artifacts 3 | cache 4 | coverage* 5 | gasReporterOutput.json 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sol2string 2 | 3 | This repository contains a Solidity library `LibUintToString` for efficiently converting `uint256` values to strings. 4 | 5 | ## Run tests 6 | 7 | ```shell 8 | npm install 9 | npx hardhat compile 10 | npx hardhat test 11 | ``` 12 | 13 | ## Gas benchmark 14 | [Gas benchmark results](gas_benchmark.txt), using [OpenZeppelin's implementation](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/788d338c9b53d57f7229f79815573dcb91ecede1/contracts/utils/Strings.sol#L14) as a benchmark. -------------------------------------------------------------------------------- /contracts/LibUintToString.sol: -------------------------------------------------------------------------------- 1 | //SPDX-License-Identifier: Unlicense 2 | pragma solidity ^0.8.0; 3 | 4 | library LibUintToString { 5 | uint256 private constant MAX_UINT256_STRING_LENGTH = 78; 6 | uint8 private constant ASCII_DIGIT_OFFSET = 48; 7 | 8 | /// @dev Converts a `uint256` value to a string. 9 | /// @param n The integer to convert. 10 | /// @return nstr `n` as a decimal string. 11 | function toString(uint256 n) 12 | internal 13 | pure 14 | returns (string memory nstr) 15 | { 16 | if (n == 0) { 17 | return "0"; 18 | } 19 | // Overallocate memory 20 | nstr = new string(MAX_UINT256_STRING_LENGTH); 21 | uint256 k = MAX_UINT256_STRING_LENGTH; 22 | // Populate string from right to left (lsb to msb). 23 | while (n != 0) { 24 | assembly { 25 | let char := add( 26 | ASCII_DIGIT_OFFSET, 27 | mod(n, 10) 28 | ) 29 | mstore(add(nstr, k), char) 30 | k := sub(k, 1) 31 | n := div(n, 10) 32 | } 33 | } 34 | assembly { 35 | // Shift pointer over to actual start of string. 36 | nstr := add(nstr, k) 37 | // Store actual string length. 38 | mstore(nstr, sub(MAX_UINT256_STRING_LENGTH, k)) 39 | } 40 | return nstr; 41 | } 42 | } -------------------------------------------------------------------------------- /contracts/TestUintToString.sol: -------------------------------------------------------------------------------- 1 | //SPDX-License-Identifier: Unlicense 2 | pragma solidity ^0.8.0; 3 | 4 | import "hardhat/console.sol"; 5 | import "./LibUintToString.sol"; 6 | 7 | contract TestUintToString { 8 | using LibUintToString for uint256; 9 | 10 | /// @dev Converts `n` to a string using LibUintToString and 11 | /// measures the gas cost. 12 | /// @param n The integer to convert. 13 | /// @return str `n` as a decimal string. 14 | /// @return gasCost The gas cost of the conversion. 15 | function testToString(uint256 n) 16 | public 17 | view 18 | returns (string memory str, uint256 gasCost) 19 | { 20 | uint256 g0 = gasleft(); 21 | str = n.toString(); 22 | gasCost = g0 - gasleft(); 23 | } 24 | 25 | /// @dev Converts `n` to a string using the baseline implementation 26 | /// (`uint2str`) and measures the gas cost. 27 | /// @param n The integer to convert. 28 | /// @return str `n` as a decimal string. 29 | /// @return gasCost The gas cost of the conversion. 30 | function baselineToString(uint256 n) 31 | public 32 | view 33 | returns (string memory str, uint256 gasCost) 34 | { 35 | uint256 g0 = gasleft(); 36 | str = toStringOZ(n); 37 | gasCost = g0 - gasleft(); 38 | } 39 | 40 | 41 | /// @dev Baseline uint256 to string implementation, from OpenZeppelin 42 | /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/788d338c9b53d57f7229f79815573dcb91ecede1/contracts/utils/Strings.sol#L14 43 | /// @param value The integer to convert. 44 | /// @return str The `value` as a decimal string. 45 | function toStringOZ(uint256 value) 46 | internal 47 | pure 48 | returns (string memory str) 49 | { 50 | // Inspired by OraclizeAPI's implementation - MIT licence 51 | // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol 52 | 53 | if (value == 0) { 54 | return "0"; 55 | } 56 | uint256 temp = value; 57 | uint256 digits; 58 | while (temp != 0) { 59 | digits++; 60 | temp /= 10; 61 | } 62 | bytes memory buffer = new bytes(digits); 63 | while (value != 0) { 64 | digits -= 1; 65 | buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); 66 | value /= 10; 67 | } 68 | return string(buffer); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /gas_benchmark.txt: -------------------------------------------------------------------------------- 1 | ================== 1 digit integers ================== 2 | sol2string average: 404.92 gas 3 | OpenZeppelin average: 1457.4 gas 4 | -72.21627555921503% 5 | ================== 2 digit integers ================== 6 | sol2string average: 514.22 gas 7 | OpenZeppelin average: 2675.49 gas 8 | -80.7803430399665% 9 | ================== 3 digit integers ================== 10 | sol2string average: 612.22 gas 11 | OpenZeppelin average: 3916.49 gas 12 | -84.36814596743511% 13 | ================== 4 digit integers ================== 14 | sol2string average: 713.16 gas 15 | OpenZeppelin average: 5194.72 gas 16 | -86.27144485169556% 17 | ================== 5 digit integers ================== 18 | sol2string average: 802.34 gas 19 | OpenZeppelin average: 6324.03 gas 20 | -87.31283690937582% 21 | ================== 6 digit integers ================== 22 | sol2string average: 903.28 gas 23 | OpenZeppelin average: 7602.26 gas 24 | -88.11827009336697% 25 | ================== 7 digit integers ================== 26 | sol2string average: 1008.14 gas 27 | OpenZeppelin average: 8930.13 gas 28 | -88.71080264229076% 29 | ================== 8 digit integers ================== 30 | sol2string average: 1105.16 gas 31 | OpenZeppelin average: 10158.72 gas 32 | -89.12107037107037% 33 | ================== 9 digit integers ================== 34 | sol2string average: 1203.16 gas 35 | OpenZeppelin average: 11399.72 gas 36 | -89.44570568399925% 37 | ================== 10 digit integers ================== 38 | sol2string average: 1300.18 gas 39 | OpenZeppelin average: 12628.31 gas 40 | -89.70424387744677% 41 | ================== 11 digit integers ================== 42 | sol2string average: 1397.2 gas 43 | OpenZeppelin average: 13856.9 gas 44 | -89.91693668858115% 45 | ================== 12 digit integers ================== 46 | sol2string average: 1498.14 gas 47 | OpenZeppelin average: 15135.13 gas 48 | -90.10157164160468% 49 | ================== 13 digit integers ================== 50 | sol2string average: 1597.12 gas 51 | OpenZeppelin average: 16388.54 gas 52 | -90.25465355669267% 53 | ================== 14 digit integers ================== 54 | sol2string average: 1693.16 gas 55 | OpenZeppelin average: 17604.72 gas 56 | -90.3823520055985% 57 | ================== 15 digit integers ================== 58 | sol2string average: 1795.08 gas 59 | OpenZeppelin average: 18895.36 gas 60 | -90.49988992006503% 61 | ================== 16 digit integers ================== 62 | sol2string average: 1884.26 gas 63 | OpenZeppelin average: 20024.67 gas 64 | -90.59030685649252% 65 | ================== 17 digit integers ================== 66 | sol2string average: 1979.32 gas 67 | OpenZeppelin average: 21228.44 gas 68 | -90.67609301484235% 69 | ================== 18 digit integers ================== 70 | sol2string average: 2085.16 gas 71 | OpenZeppelin average: 22568.72 gas 72 | -90.76084066796876% 73 | ================== 19 digit integers ================== 74 | sol2string average: 2173.36 gas 75 | OpenZeppelin average: 23685.62 gas 76 | -90.82413717690312% 77 | ================== 20 digit integers ================== 78 | sol2string average: 2273.32 gas 79 | OpenZeppelin average: 24951.44 gas 80 | -90.88902283796045% 81 | ================== 21 digit integers ================== 82 | sol2string average: 2370.34 gas 83 | OpenZeppelin average: 26180.03 gas 84 | -90.9459996799087% 85 | ================== 22 digit integers ================== 86 | sol2string average: 2471.28 gas 87 | OpenZeppelin average: 27458.26 gas 88 | -90.99986670677603% 89 | ================== 23 digit integers ================== 90 | sol2string average: 2572.22 gas 91 | OpenZeppelin average: 28736.49 gas 92 | -91.04894160699514% 93 | ================== 24 digit integers ================== 94 | sol2string average: 2671.2 gas 95 | OpenZeppelin average: 29989.9 gas 96 | -91.09300131044118% 97 | ================== 25 digit integers ================== 98 | sol2string average: 2768.22 gas 99 | OpenZeppelin average: 31218.49 gas 100 | -91.13275497950093% 101 | ================== 26 digit integers ================== 102 | sol2string average: 2863.28 gas 103 | OpenZeppelin average: 32422.26 gas 104 | -91.16878342225372% 105 | ================== 27 digit integers ================== 106 | sol2string average: 2963.24 gas 107 | OpenZeppelin average: 33688.08 gas 108 | -91.20389170294064% 109 | ================== 28 digit integers ================== 110 | sol2string average: 3062.22 gas 111 | OpenZeppelin average: 34941.49 gas 112 | -91.23614934566328% 113 | ================== 29 digit integers ================== 114 | sol2string average: 3161.2 gas 115 | OpenZeppelin average: 36194.9 gas 116 | -91.26617285860716% 117 | ================== 30 digit integers ================== 118 | sol2string average: 3255.28 gas 119 | OpenZeppelin average: 37386.26 gas 120 | -91.29284394855223% 121 | ================== 31 digit integers ================== 122 | sol2string average: 3356.22 gas 123 | OpenZeppelin average: 38664.49 gas 124 | -91.3196320448039% 125 | ================== 32 digit integers ================== 126 | sol2string average: 3453.24 gas 127 | OpenZeppelin average: 39893.08 gas 128 | -91.3437618754932% 129 | ================== 33 digit integers ================== 130 | sol2string average: 3555.16 gas 131 | OpenZeppelin average: 41189.3 gas 132 | -91.36872925735567% 133 | ================== 34 digit integers ================== 134 | sol2string average: 3651.2 gas 135 | OpenZeppelin average: 42405.78 gas 136 | -91.38985298702205% 137 | ================== 35 digit integers ================== 138 | sol2string average: 3749.2 gas 139 | OpenZeppelin average: 43646.9 gas 140 | -91.41015742240572% 141 | ================== 36 digit integers ================== 142 | sol2string average: 3842.3 gas 143 | OpenZeppelin average: 44825.85 gas 144 | -91.42838339931089% 145 | ================== 37 digit integers ================== 146 | sol2string average: 3945.2 gas 147 | OpenZeppelin average: 46128.9 gas 148 | -91.44744401015417% 149 | ================== 38 digit integers ================== 150 | sol2string average: 4040.26 gas 151 | OpenZeppelin average: 47332.67 gas 152 | -91.46411981407344% 153 | ================== 39 digit integers ================== 154 | sol2string average: 4133.36 gas 155 | OpenZeppelin average: 48511.62 gas 156 | -91.47964961796782% 157 | ================== 40 digit integers ================== 158 | sol2string average: 4242.14 gas 159 | OpenZeppelin average: 49889.13 gas 160 | -91.4968651487809% 161 | ================== 41 digit integers ================== 162 | sol2string average: 4338.18 gas 163 | OpenZeppelin average: 51105.31 gas 164 | -91.5112930535007% 165 | ================== 42 digit integers ================== 166 | sol2string average: 4438.14 gas 167 | OpenZeppelin average: 52371.13 gas 168 | -91.5255981683038% 169 | ================== 43 digit integers ================== 170 | sol2string average: 4526.34 gas 171 | OpenZeppelin average: 53488.03 gas 172 | -91.53765805171737% 173 | ================== 44 digit integers ================== 174 | sol2string average: 4629.24 gas 175 | OpenZeppelin average: 54791.08 gas 176 | -91.55110649397676% 177 | ================== 45 digit integers ================== 178 | sol2string average: 4725.28 gas 179 | OpenZeppelin average: 56007.26 gas 180 | -91.56309378462721% 181 | ================== 46 digit integers ================== 182 | sol2string average: 4824.26 gas 183 | OpenZeppelin average: 57260.67 gas 184 | -91.5749152079429% 185 | ================== 47 digit integers ================== 186 | sol2string average: 4919.32 gas 187 | OpenZeppelin average: 58464.44 gas 188 | -91.58579129467417% 189 | ================== 48 digit integers ================== 190 | sol2string average: 5023.2 gas 191 | OpenZeppelin average: 59779.9 gas 192 | -91.59717563930352% 193 | ================== 49 digit integers ================== 194 | sol2string average: 5119.24 gas 195 | OpenZeppelin average: 60996.08 gas 196 | -91.60726394220744% 197 | ================== 50 digit integers ================== 198 | sol2string average: 5221.16 gas 199 | OpenZeppelin average: 62286.72 gas 200 | -91.61753901955343% 201 | ================== 51 digit integers ================== 202 | sol2string average: 5322.1 gas 203 | OpenZeppelin average: 63564.95 gas 204 | -91.62730404098485% 205 | ================== 52 digit integers ================== 206 | sol2string average: 5412.26 gas 207 | OpenZeppelin average: 64706.67 gas 208 | -91.63569999816093% 209 | ================== 53 digit integers ================== 210 | sol2string average: 5514.18 gas 211 | OpenZeppelin average: 65997.31 gas 212 | -91.6448412821674% 213 | ================== 54 digit integers ================== 214 | sol2string average: 5614.14 gas 215 | OpenZeppelin average: 67263.13 gas 216 | -91.65346602217292% 217 | ================== 55 digit integers ================== 218 | sol2string average: 5711.16 gas 219 | OpenZeppelin average: 68491.72 gas 220 | -91.66153222608513% 221 | ================== 56 digit integers ================== 222 | sol2string average: 5803.28 gas 223 | OpenZeppelin average: 69658.26 gas 224 | -91.66892770505608% 225 | ================== 57 digit integers ================== 226 | sol2string average: 5901.28 gas 227 | OpenZeppelin average: 70899.26 gas 228 | -91.67652807659769% 229 | ================== 58 digit integers ================== 230 | sol2string average: 6004.18 gas 231 | OpenZeppelin average: 72202.31 gas 232 | -91.68422727749294% 233 | ================== 59 digit integers ================== 234 | sol2string average: 6096.3 gas 235 | OpenZeppelin average: 73368.85 gas 236 | -91.69088789043306% 237 | ================== 60 digit integers ================== 238 | sol2string average: 6198.22 gas 239 | OpenZeppelin average: 74659.49 gas 240 | -91.69801454577308% 241 | ================== 61 digit integers ================== 242 | sol2string average: 6292.3 gas 243 | OpenZeppelin average: 75850.85 gas 244 | -91.70437773604382% 245 | ================== 62 digit integers ================== 246 | sol2string average: 6397.16 gas 247 | OpenZeppelin average: 77178.72 gas 248 | -91.71123853829138% 249 | ================== 63 digit integers ================== 250 | sol2string average: 6489.28 gas 251 | OpenZeppelin average: 78345.26 gas 252 | -91.7170738855165% 253 | ================== 64 digit integers ================== 254 | sol2string average: 6593.16 gas 255 | OpenZeppelin average: 79660.72 gas 256 | -91.72344914783596% 257 | ================== 65 digit integers ================== 258 | sol2string average: 6689.2 gas 259 | OpenZeppelin average: 80882.36 gas 260 | -91.72971708540652% 261 | ================== 66 digit integers ================== 262 | sol2string average: 6787.2 gas 263 | OpenZeppelin average: 82123.9 gas 264 | -91.73541441650968% 265 | ================== 67 digit integers ================== 266 | sol2string average: 6888.14 gas 267 | OpenZeppelin average: 83402.13 gas 268 | -91.74105025854855% 269 | ================== 68 digit integers ================== 270 | sol2string average: 6982.22 gas 271 | OpenZeppelin average: 84593.49 gas 272 | -91.74614973327144% 273 | ================== 69 digit integers ================== 274 | sol2string average: 7075.32 gas 275 | OpenZeppelin average: 85772.44 gas 276 | -91.75105663310966% 277 | ================== 70 digit integers ================== 278 | sol2string average: 7174.3 gas 279 | OpenZeppelin average: 87025.85 gas 280 | -91.75612763334112% 281 | ================== 71 digit integers ================== 282 | sol2string average: 7272.3 gas 283 | OpenZeppelin average: 88266.85 gas 284 | -91.76100653869487% 285 | ================== 72 digit integers ================== 286 | sol2string average: 7375.2 gas 287 | OpenZeppelin average: 89569.9 gas 288 | -91.76598388521144% 289 | ================== 73 digit integers ================== 290 | sol2string average: 7467.32 gas 291 | OpenZeppelin average: 90736.44 gas 292 | -91.77031851811685% 293 | ================== 74 digit integers ================== 294 | sol2string average: 7572.18 gas 295 | OpenZeppelin average: 92064.31 gas 296 | -91.77511893588299% 297 | ================== 75 digit integers ================== 298 | sol2string average: 7674.1 gas 299 | OpenZeppelin average: 93354.95 gas 300 | -91.77965389087562% 301 | ================== 76 digit integers ================== 302 | sol2string average: 7766.22 gas 303 | OpenZeppelin average: 94521.49 gas 304 | -91.78364623748524% 305 | ================== 77 digit integers ================== 306 | sol2string average: 7869.12 gas 307 | OpenZeppelin average: 95824.54 gas 308 | -91.7879908424293% -------------------------------------------------------------------------------- /hardhat.config.js: -------------------------------------------------------------------------------- 1 | require('@nomiclabs/hardhat-waffle'); 2 | 3 | // This is a sample Hardhat task. To learn how to create your own go to 4 | // https://hardhat.org/guides/create-task.html 5 | task('accounts', 'Prints the list of accounts', async (taskArgs, hre) => { 6 | const accounts = await hre.ethers.getSigners(); 7 | 8 | for (const account of accounts) { 9 | console.log(account.address); 10 | } 11 | }); 12 | 13 | // You need to export an object to set up your config 14 | // Go to https://hardhat.org/config/ to learn more 15 | 16 | /** 17 | * @type import('hardhat/config').HardhatUserConfig 18 | */ 19 | module.exports = { 20 | solidity: '0.8.4', 21 | }; 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sol2string", 3 | "version": "1.0.0", 4 | "description": "A gas-efficient Solidity library for converting uints to strings.", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "test", 8 | "prettier": "prettier --write \"**/*.{ts,js,json,yml,md}\"" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/mzhu25/sol2string.git" 13 | }, 14 | "author": "Michael Zhu", 15 | "license": "ISC", 16 | "bugs": { 17 | "url": "https://github.com/mzhu25/sol2string/issues" 18 | }, 19 | "homepage": "https://github.com/mzhu25/sol2string#readme", 20 | "devDependencies": { 21 | "@nomiclabs/hardhat-ethers": "^2.0.2", 22 | "@nomiclabs/hardhat-waffle": "^2.0.1", 23 | "chai": "^4.3.4", 24 | "ethereum-waffle": "^3.4.0", 25 | "ethers": "^5.4.6", 26 | "hardhat": "^2.6.2", 27 | "prettier": "^2.3.2" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /test/sample-test.js: -------------------------------------------------------------------------------- 1 | const { expect } = require('chai'); 2 | const { Contract } = require('ethers'); 3 | const { ethers } = require('hardhat'); 4 | 5 | const MAX_UINT256_STRING_LENGTH = 78; 6 | function randomUint(digits) { 7 | if (!digits) { 8 | digits = Math.floor(Math.random() * (MAX_UINT256_STRING_LENGTH - 1)); 9 | } 10 | return BigInt( 11 | Array(digits) 12 | .fill() 13 | .map(() => Math.floor(Math.random() * 10).toString()) 14 | .join(''), 15 | ).toString(); 16 | } 17 | 18 | const NUM_SAMPLES = Number.parseInt(process.env.NUM_SAMPLES || '100'); 19 | 20 | describe('LibUintToString.toString', function () { 21 | let testContract; 22 | before(async function () { 23 | const TestUintToString = await ethers.getContractFactory('TestUintToString'); 24 | testContract = await TestUintToString.deploy(); 25 | await testContract.deployed(); 26 | }); 27 | it('Should convert 0 to "0"', async function () { 28 | const result = await testContract.testToString(0); 29 | // console.log(`gas cost: ${result.gasCost}`); 30 | expect(result.str).to.equal('0'); 31 | }); 32 | it('Should correctly convert type(uint256).max', async function () { 33 | const maxUint256 = 2n ** 256n - 1n; 34 | const result = await testContract.testToString(maxUint256.toString()); 35 | // console.log(`gas cost: ${result.gasCost}`); 36 | expect(result.str).to.equal(maxUint256.toString()); 37 | }); 38 | it('Should correctly convert a random uint256 to a string', async function () { 39 | for (let i = 0; i < NUM_SAMPLES; i++) { 40 | const uint = randomUint(); 41 | const result = await testContract.testToString(uint); 42 | // console.log(uint); 43 | // console.log(`gas cost: ${result.gasCost}`); 44 | expect(result.str).to.equal(uint); 45 | } 46 | }); 47 | it.skip('Gas benchmark', async function () { 48 | for (let digits = 1; digits < MAX_UINT256_STRING_LENGTH; digits++) { 49 | console.log(`================== ${digits} digit integers ==================`); 50 | let testAverage = 0; 51 | let baselineAverage = 0; 52 | for (let i = 0; i < NUM_SAMPLES; i++) { 53 | const uint = randomUint(digits); 54 | const testResult = await testContract.testToString(uint); 55 | expect(testResult.str).to.equal(uint); 56 | testAverage += testResult.gasCost.toNumber(); 57 | const baselineResult = await testContract.baselineToString(uint); 58 | baselineAverage += baselineResult.gasCost.toNumber(); 59 | } 60 | testAverage /= NUM_SAMPLES; 61 | baselineAverage /= NUM_SAMPLES; 62 | console.log(`sol2string average: ${testAverage} gas`); 63 | console.log(`OpenZeppelin average: ${baselineAverage} gas`); 64 | console.log( 65 | ` ${testAverage < baselineAverage ? '-' : '+'}${ 66 | (Math.abs(baselineAverage - testAverage) / baselineAverage) * 100 67 | }%`, 68 | ); 69 | } 70 | }); 71 | }); 72 | --------------------------------------------------------------------------------