From 2033c7a6d15eba1f2818ccb8a4ab4e7329088864 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Sun, 9 Oct 2022 23:54:09 +0100 Subject: [PATCH 1/5] Split off HexString from NFTSVG --- src/HexString.sol | 28 ++++++++++++++++++++++++++++ src/NFTSVG.sol | 26 ++------------------------ src/OptimizorNFT.sol | 4 ++-- 3 files changed, 32 insertions(+), 26 deletions(-) create mode 100644 src/HexString.sol diff --git a/src/HexString.sol b/src/HexString.sol new file mode 100644 index 0000000..817e128 --- /dev/null +++ b/src/HexString.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity ^0.8.15; + +library HexString { + bytes16 constant ALPHABET = '0123456789abcdef'; + + function toHexStringNoPrefix(uint256 value, uint256 length) internal pure returns (string memory) { + bytes memory buffer = new bytes(2 * length); + for (uint256 i = buffer.length; i > 0; i--) { + buffer[i - 1] = ALPHABET[value & 0xf]; + value >>= 4; + } + return string(buffer); + } + + function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { + bytes memory buffer = new bytes(2 * length + 2); + buffer[0] = '0'; + buffer[1] = 'x'; + for (uint256 i = 2 * length + 1; i > 1; --i) { + buffer[i] = ALPHABET[value & 0xf]; + value >>= 4; + } + require(value == 0, 'Strings: hex length insufficient'); + return string(buffer); + } + +} diff --git a/src/NFTSVG.sol b/src/NFTSVG.sol index 2368cd6..35f53c0 100644 --- a/src/NFTSVG.sol +++ b/src/NFTSVG.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.15; import '@openzeppelin/contracts/utils/Strings.sol'; +import './HexString.sol'; import './base64.sol'; /// @title NFTSVG @@ -278,16 +279,7 @@ library NFTSVG { } function tokenToColorHex(uint256 token, uint256 offset) internal pure returns (string memory str) { - return string(toHexStringNoPrefix((token >> offset), 3)); - } - - function toHexStringNoPrefix(uint256 value, uint256 length) internal pure returns (string memory) { - bytes memory buffer = new bytes(2 * length); - for (uint256 i = buffer.length; i > 0; i--) { - buffer[i - 1] = ALPHABET[value & 0xf]; - value >>= 4; - } - return string(buffer); + return string(HexString.toHexStringNoPrefix((token >> offset), 3)); } function scale( @@ -311,18 +303,4 @@ library NFTSVG { function sliceTokenHex(uint256 token, uint256 offset) internal pure returns (uint256) { return uint256(uint8(token >> offset)); } - - function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { - bytes memory buffer = new bytes(2 * length + 2); - buffer[0] = '0'; - buffer[1] = 'x'; - for (uint256 i = 2 * length + 1; i > 1; --i) { - buffer[i] = ALPHABET[value & 0xf]; - value >>= 4; - } - require(value == 0, 'Strings: hex length insufficient'); - return string(buffer); - } - - bytes16 constant ALPHABET = '0123456789abcdef'; } diff --git a/src/OptimizorNFT.sol b/src/OptimizorNFT.sol index afa4154..1f67df0 100644 --- a/src/OptimizorNFT.sol +++ b/src/OptimizorNFT.sol @@ -279,8 +279,8 @@ contract Optimizor is Owned, ERC721 { projectName: "Optimizor", challengeName: name, // TODO should \/ be details.owner or details.recordHolder? - holderAddr: NFTSVG.toHexString(uint(uint160(address(details.owner))), 20), - challengeAddr: NFTSVG.toHexString(uint(uint160(address(details.challenge))), 20), + holderAddr: Strings.toHexString(uint(uint160(address(details.owner))), 20), + challengeAddr: Strings.toHexString(uint(uint160(address(details.challenge))), 20), gasUsed: details.gas, gasOpti: gasOptiPercentage(tokenId, details), overRange: int8(int256(uint256(keccak256(abi.encodePacked(tokenId))))) % 3, From e3aaf931c8f59b6f99fa0172ede52af5cc1f99f5 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Sun, 9 Oct 2022 23:55:43 +0100 Subject: [PATCH 2/5] Use unified Strings.toString syntax --- src/NFTSVG.sol | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/NFTSVG.sol b/src/NFTSVG.sol index 35f53c0..36df3aa 100644 --- a/src/NFTSVG.sol +++ b/src/NFTSVG.sol @@ -8,8 +8,6 @@ import './base64.sol'; /// @title NFTSVG /// @notice Provides a function for generating an SVG associated with a Uniswap NFT library NFTSVG { - using Strings for uint256; - struct SVGParams { string projectName; string challengeName; @@ -56,7 +54,7 @@ library NFTSVG { generateSVGCardMantle(params.challengeName, params.challengeAddr, params.rank, params.participants), generateSvgCurve(params.overRange, challengeSVG), generateSVGPositionDataAndLocationCurve( - params.tokenId.toString(), + Strings.toString(params.tokenId), params.gasUsed, params.gasOpti ), @@ -238,21 +236,21 @@ library NFTSVG { abi.encodePacked( ' ', '', 'ID: ', tokenId, '', ' ', '', 'Gas used: ', gasUsedStr, '', ' ', '', 'Gas opti: ', gasOptiStr, From 014352a96d46f6b0058b7cd94b7b8d6ffcf5bcf4 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Sun, 9 Oct 2022 23:57:10 +0100 Subject: [PATCH 3/5] Replace OpenZeppelin/Strings wih solmate/LibString --- src/NFTSVG.sol | 21 +++++++++++---------- src/OptimizorNFT.sol | 11 ++++++----- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/NFTSVG.sol b/src/NFTSVG.sol index 36df3aa..45c4aef 100644 --- a/src/NFTSVG.sol +++ b/src/NFTSVG.sol @@ -1,10 +1,11 @@ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.15; -import '@openzeppelin/contracts/utils/Strings.sol'; import './HexString.sol'; import './base64.sol'; +import "solmate/utils/LibString.sol"; + /// @title NFTSVG /// @notice Provides a function for generating an SVG associated with a Uniswap NFT library NFTSVG { @@ -54,7 +55,7 @@ library NFTSVG { generateSVGCardMantle(params.challengeName, params.challengeAddr, params.rank, params.participants), generateSvgCurve(params.overRange, challengeSVG), generateSVGPositionDataAndLocationCurve( - Strings.toString(params.tokenId), + LibString.toString(params.tokenId), params.gasUsed, params.gasOpti ), @@ -195,9 +196,9 @@ library NFTSVG { '', string.concat( "Rank #", - Strings.toString(rank), + LibString.toString(rank), "/", - Strings.toString(participants) + LibString.toString(participants) ), '', '' @@ -227,8 +228,8 @@ library NFTSVG { uint gasUsed, uint gasOpti ) private pure returns (string memory svg) { - string memory gasUsedStr = Strings.toString(gasUsed); - string memory gasOptiStr = Strings.toString(gasOpti); + string memory gasUsedStr = LibString.toString(gasUsed); + string memory gasOptiStr = LibString.toString(gasOpti); uint256 str1length = bytes(tokenId).length + 4; uint256 str2length = bytes(gasUsedStr).length + 10; uint256 str3length = bytes(gasOptiStr).length + 10; @@ -236,21 +237,21 @@ library NFTSVG { abi.encodePacked( ' ', '', 'ID: ', tokenId, '', ' ', '', 'Gas used: ', gasUsedStr, '', ' ', '', 'Gas opti: ', gasOptiStr, @@ -287,7 +288,7 @@ library NFTSVG { uint256 outMn, uint256 outMx ) internal pure returns (string memory) { - return Strings.toString(((n - inMn) * (outMx - outMn)) / (inMx - inMn) + outMn); + return LibString.toString(((n - inMn) * (outMx - outMn)) / (inMx - inMn) + outMn); } function getCircleCoord( diff --git a/src/OptimizorNFT.sol b/src/OptimizorNFT.sol index 1f67df0..20d7f64 100644 --- a/src/OptimizorNFT.sol +++ b/src/OptimizorNFT.sol @@ -8,10 +8,11 @@ import "./NFTSVG.sol"; import "./IPurityChecker.sol"; import "./IAttribute.sol"; import "./TokenDetails.sol"; +import "./HexString.sol"; import "solmate/auth/Owned.sol"; import "solmate/tokens/ERC721.sol"; -import '@openzeppelin/contracts/utils/Strings.sol'; +import "solmate/utils/LibString.sol"; uint constant EPOCH = 256; @@ -223,9 +224,9 @@ contract Optimizor is Owned, ERC721 { for (uint i = 0; i < leaders.length; ++i) { leadersStr = string.concat( "\\n", - Strings.toString(lIdx), + LibString.toString(lIdx), ". ", - Strings.toHexString(uint(uint160(leaders[i])), 20), + HexString.toHexString(uint(uint160(leaders[i])), 20), leadersStr ); --lIdx; @@ -279,8 +280,8 @@ contract Optimizor is Owned, ERC721 { projectName: "Optimizor", challengeName: name, // TODO should \/ be details.owner or details.recordHolder? - holderAddr: Strings.toHexString(uint(uint160(address(details.owner))), 20), - challengeAddr: Strings.toHexString(uint(uint160(address(details.challenge))), 20), + holderAddr: HexString.toHexString(uint(uint160(address(details.owner))), 20), + challengeAddr: HexString.toHexString(uint(uint160(address(details.challenge))), 20), gasUsed: details.gas, gasOpti: gasOptiPercentage(tokenId, details), overRange: int8(int256(uint256(keccak256(abi.encodePacked(tokenId))))) % 3, From 38d17e61a77002b03b42723646d2052baca4ccf2 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Sun, 9 Oct 2022 23:57:37 +0100 Subject: [PATCH 4/5] Drop OpenZeppelin --- .gitmodules | 3 --- foundry.toml | 1 - lib/openzeppelin-contracts | 1 - 3 files changed, 5 deletions(-) delete mode 160000 lib/openzeppelin-contracts diff --git a/.gitmodules b/.gitmodules index dd31873..d25992c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,9 +4,6 @@ [submodule "lib/solmate"] path = lib/solmate url = https://github.com/rari-capital/solmate -[submodule "lib/openzeppelin-contracts"] - path = lib/openzeppelin-contracts - url = https://github.com/OpenZeppelin/openzeppelin-contracts [submodule "lib/puretea"] path = lib/puretea url = https://github.com/axic/puretea diff --git a/foundry.toml b/foundry.toml index 639c068..9db8d8c 100644 --- a/foundry.toml +++ b/foundry.toml @@ -9,7 +9,6 @@ cbor_metadata = false # See more config options https://github.com/gakonst/foundry/tree/master/config remappings = [ - '@openzeppelin=lib/openzeppelin-contracts/', 'forge-std=lib/forge-std/src/', ] diff --git a/lib/openzeppelin-contracts b/lib/openzeppelin-contracts deleted file mode 160000 index 83277ff..0000000 --- a/lib/openzeppelin-contracts +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 83277ff916ac4f58fec072b8f28a252c1245c2f1 From 36d8b9ea9a227ec00821feef3b41e6927eb2b09c Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Mon, 10 Oct 2022 00:02:04 +0100 Subject: [PATCH 5/5] Update solmate to fork with memory-safe annotation --- .gitmodules | 2 +- lib/solmate | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index d25992c..2c70be7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,7 +3,7 @@ url = https://github.com/foundry-rs/forge-std [submodule "lib/solmate"] path = lib/solmate - url = https://github.com/rari-capital/solmate + url = https://github.com/axic/solmate [submodule "lib/puretea"] path = lib/puretea url = https://github.com/axic/puretea diff --git a/lib/solmate b/lib/solmate index eaaccf8..6fa069d 160000 --- a/lib/solmate +++ b/lib/solmate @@ -1 +1 @@ -Subproject commit eaaccf88ac5290299884437e1aee098a96583d54 +Subproject commit 6fa069dcdbf3b4f7d9017e81b36223091d3d79bd