-
Notifications
You must be signed in to change notification settings - Fork 12.4k
Add utility function for converting an address to checksummed string #5067
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
Merged
Merged
Changes from 1 commit
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
215452f
add implementation and tests
cairoeth 3ef22ec
add changeset
cairoeth db76d54
use shared logic with _setHexString
cairoeth e05ab88
add addrValue to simplify
cairoeth b0967a8
use `addrValue`
cairoeth 719978b
Apply PR recommendations
ernestognw f2ce027
rename to HEX_DIGITS_UPPERCASE
cairoeth ac713f0
Improve tests
ernestognw 8f11b32
checksum in place to avoid double allocation + simplification
Amxx File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev
Previous commit
checksum in place to avoid double allocation + simplification
- Loading branch information
commit 8f11b326bdc7bdbbcc82d956fe38d07b820f7906
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,7 +11,6 @@ import {SignedMath} from "./math/SignedMath.sol"; | |
| */ | ||
| library Strings { | ||
| bytes16 private constant HEX_DIGITS = "0123456789abcdef"; | ||
| bytes16 private constant HEX_DIGITS_UPPERCASE = "0123456789ABCDEF"; | ||
| uint8 private constant ADDRESS_LENGTH = 20; | ||
|
|
||
| /** | ||
|
|
@@ -64,15 +63,17 @@ library Strings { | |
| * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. | ||
| */ | ||
| function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { | ||
| if (length < Math.log256(value) + 1) { | ||
| revert StringsInsufficientHexLength(value, length); | ||
| } | ||
|
|
||
| uint256 localValue = value; | ||
| bytes memory buffer = new bytes(2 * length + 2); | ||
| buffer[0] = "0"; | ||
| buffer[1] = "x"; | ||
| _unsafeSetHexString(buffer, 2, value); | ||
|
|
||
| for (uint256 i = 2 * length + 1; i > 1; --i) { | ||
| buffer[i] = HEX_DIGITS[localValue & 0xf]; | ||
| localValue >>= 4; | ||
| } | ||
| if (localValue != 0) { | ||
| revert StringsInsufficientHexLength(value, length); | ||
| } | ||
| return string(buffer); | ||
| } | ||
|
|
||
|
|
@@ -89,22 +90,23 @@ library Strings { | |
| * representation, according to EIP-55. | ||
| */ | ||
| function toChecksumHexString(address addr) internal pure returns (string memory) { | ||
| bytes memory lowercase = new bytes(40); | ||
| uint160 addrValue = uint160(addr); | ||
| _unsafeSetHexString(lowercase, 0, addrValue); | ||
| bytes32 hashedAddr = keccak256(abi.encodePacked(lowercase)); | ||
| bytes memory buffer = bytes(toHexString(addr)); | ||
|
|
||
| // hash the hex part of buffer (skip length + 2 bytes, length 40) | ||
| uint256 hashValue; | ||
| assembly ("memory-safe") { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. note: this is safe because we know buffer is 42 bytes long. |
||
| hashValue := shr(96, keccak256(add(buffer, 0x22), 40)) | ||
| } | ||
|
|
||
| bytes memory buffer = new bytes(42); | ||
| buffer[0] = "0"; | ||
| buffer[1] = "x"; | ||
| uint160 hashValue = uint160(bytes20(hashedAddr)); | ||
| for (uint256 i = 41; i > 1; --i) { | ||
| uint8 digit = uint8(addrValue & 0xf); | ||
| buffer[i] = hashValue & 0xf > 7 ? HEX_DIGITS_UPPERCASE[digit] : HEX_DIGITS[digit]; | ||
| addrValue >>= 4; | ||
| // possible values for buffer[i] are 48 (0) to 57 (9) and 97 (a) to 102 (f) | ||
| if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) { | ||
| // case shift by xoring with 0x20 | ||
| buffer[i] ^= 0x20; | ||
| } | ||
| hashValue >>= 4; | ||
| } | ||
| return string(abi.encodePacked(buffer)); | ||
| return string(buffer); | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -113,17 +115,4 @@ library Strings { | |
| function equal(string memory a, string memory b) internal pure returns (bool) { | ||
| return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b)); | ||
| } | ||
|
|
||
| /** | ||
| * @dev Sets the hexadecimal representation of a value in the specified buffer starting from the given offset. | ||
| * | ||
| * NOTE: This function does not check that the `buffer` can allocate `value` without overflowing. Make sure | ||
| * to check whether `Math.log256(value) + 1` is larger than the specified `length`. | ||
| */ | ||
| function _unsafeSetHexString(bytes memory buffer, uint256 offset, uint256 value) private pure { | ||
| for (uint256 i = buffer.length; i > offset; --i) { | ||
| buffer[i - 1] = HEX_DIGITS[value & 0xf]; | ||
| value >>= 4; | ||
| } | ||
| } | ||
| } | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Redesigned
toChecksumHexStringto avoid double allocation._unsafeSetHexStringHEX_DIGITS_UPPERCASEThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right this is extremely cleaner. Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
great changes, thxs!