Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean up string handling (and drop openzeppelin dependency) #40

Merged
merged 5 commits into from
Oct 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wut? you maintain a solmate as well?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solmate's toString() had some bugs related to memory management. Showed up in art-gobblers. So you should probably update this.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

He made the fork today just to test this, and it looks like solmate already fixed it I think

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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