Skip to content

Commit

Permalink
Merge pull request #40 from OptimizorClub/strings
Browse files Browse the repository at this point in the history
Clean up string handling (and drop openzeppelin dependency)
  • Loading branch information
Leo authored Oct 21, 2022
2 parents bdd8987 + 36d8b9e commit 90869be
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 48 deletions.
5 changes: 1 addition & 4 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@
url = https://github.com/foundry-rs/forge-std
[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
url = https://github.com/axic/solmate
[submodule "lib/puretea"]
path = lib/puretea
url = https://github.com/axic/puretea
1 change: 0 additions & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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/',
]

Expand Down
1 change: 0 additions & 1 deletion lib/openzeppelin-contracts
Submodule openzeppelin-contracts deleted from 83277f
2 changes: 1 addition & 1 deletion lib/solmate
Submodule solmate updated 47 files
+294 −60 .gas-snapshot
+1 −1 .vscode/settings.json
+7 −4 README.md
+4 −4 foundry.toml
+1 −1 lib/ds-test
+2 −2 package-lock.json
+3 −3 package.json
+2 −2 src/auth/Auth.sol
+1 −1 src/auth/Owned.sol
+1 −1 src/auth/authorities/MultiRolesAuthority.sol
+1 −1 src/auth/authorities/RolesAuthority.sol
+1 −1 src/mixins/ERC4626.sol
+1 −1 src/test/Auth.t.sol
+1 −1 src/test/Bytes32AddressLib.t.sol
+1 −1 src/test/CREATE3.t.sol
+1 −1 src/test/DSTestPlus.t.sol
+8 −4 src/test/ERC1155.t.sol
+1 −1 src/test/ERC20.t.sol
+1 −1 src/test/ERC4626.t.sol
+1 −1 src/test/ERC721.t.sol
+84 −1 src/test/FixedPointMathLib.t.sol
+107 −0 src/test/LibString.t.sol
+50 −0 src/test/MerkleProofLib.t.sol
+1 −1 src/test/MultiRolesAuthority.t.sol
+1 −1 src/test/Owned.t.sol
+1 −1 src/test/ReentrancyGuard.t.sol
+1 −1 src/test/RolesAuthority.t.sol
+1 −1 src/test/SSTORE2.t.sol
+33 −1 src/test/SafeCastLib.t.sol
+1 −1 src/test/SafeTransferLib.t.sol
+60 −0 src/test/SignedWadMath.t.sol
+5 −5 src/test/WETH.t.sol
+2 −2 src/test/utils/DSTestPlus.sol
+2 −2 src/tokens/ERC1155.sol
+1 −1 src/tokens/ERC20.sol
+2 −2 src/tokens/ERC721.sol
+1 −1 src/tokens/WETH.sol
+1 −1 src/utils/Bytes32AddressLib.sol
+1 −1 src/utils/CREATE3.sol
+68 −37 src/utils/FixedPointMathLib.sol
+55 −0 src/utils/LibString.sol
+47 −0 src/utils/MerkleProofLib.sol
+1 −1 src/utils/ReentrancyGuard.sol
+1 −1 src/utils/SSTORE2.sol
+13 −1 src/utils/SafeCastLib.sol
+1 −1 src/utils/SafeTransferLib.sol
+218 −0 src/utils/SignedWadMath.sol
28 changes: 28 additions & 0 deletions src/HexString.sol
Original file line number Diff line number Diff line change
@@ -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);
}

}
49 changes: 13 additions & 36 deletions src/NFTSVG.sol
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
// 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 {
using Strings for uint256;

struct SVGParams {
string projectName;
string challengeName;
Expand Down Expand Up @@ -55,7 +55,7 @@ library NFTSVG {
generateSVGCardMantle(params.challengeName, params.challengeAddr, params.rank, params.participants),
generateSvgCurve(params.overRange, challengeSVG),
generateSVGPositionDataAndLocationCurve(
params.tokenId.toString(),
LibString.toString(params.tokenId),
params.gasUsed,
params.gasOpti
),
Expand Down Expand Up @@ -196,9 +196,9 @@ library NFTSVG {
'</text><text y="115px" x="32px" fill="white" font-family="\'Courier New\', monospace" font-weight="200" font-size="20px">',
string.concat(
"Rank #",
Strings.toString(rank),
LibString.toString(rank),
"/",
Strings.toString(participants)
LibString.toString(participants)
),
'</text></g>',
'<rect x="16" y="16" width="258" height="468" rx="26" ry="26" fill="rgba(0,0,0,0)" stroke="rgba(255,255,255,0.2)" />'
Expand Down Expand Up @@ -228,30 +228,30 @@ 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;
svg = string(
abi.encodePacked(
' <g style="transform:translate(29px, 384px)">',
'<rect width="',
uint256(7 * (str1length + 4)).toString(),
LibString.toString(uint256(7 * (str1length + 4))),
'px" height="26px" rx="8px" ry="8px" fill="rgba(0,0,0,0.6)" />',
'<text x="12px" y="17px" font-family="\'Courier New\', monospace" font-size="12px" fill="white"><tspan fill="rgba(255,255,255,0.6)">ID: </tspan>',
tokenId,
'</text></g>',
' <g style="transform:translate(29px, 414px)">',
'<rect width="',
uint256(7 * (str2length + 4)).toString(),
LibString.toString(uint256(7 * (str2length + 4))),
'px" height="26px" rx="8px" ry="8px" fill="rgba(0,0,0,0.6)" />',
'<text x="12px" y="17px" font-family="\'Courier New\', monospace" font-size="12px" fill="white"><tspan fill="rgba(255,255,255,0.6)">Gas used: </tspan>',
gasUsedStr,
'</text></g>',
' <g style="transform:translate(29px, 444px)">',
'<rect width="',
uint256(7 * (str3length + 4)).toString(),
LibString.toString(uint256(7 * (str3length + 4))),
'px" height="26px" rx="8px" ry="8px" fill="rgba(0,0,0,0.6)" />',
'<text x="12px" y="17px" font-family="\'Courier New\', monospace" font-size="12px" fill="white"><tspan fill="rgba(255,255,255,0.6)">Gas opti: </tspan>',
gasOptiStr,
Expand All @@ -278,16 +278,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(
Expand All @@ -297,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(
Expand All @@ -311,18 +302,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';
}
11 changes: 6 additions & 5 deletions src/OptimizorNFT.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -279,8 +280,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: 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,
Expand Down

0 comments on commit 90869be

Please sign in to comment.