Skip to content

Commit

Permalink
Merge pull request #403 from ensdomains/fix/fixed-case-hex
Browse files Browse the repository at this point in the history
fix: single case hex address validation
  • Loading branch information
TateB committed May 20, 2024
2 parents 4bb847b + 14f66fa commit 3dd92e1
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 7 deletions.
29 changes: 23 additions & 6 deletions src/coin/eth.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,32 @@ import { hexToBytes } from "@noble/hashes/utils";
import { describe, expect, test } from "bun:test";
import { decodeEthAddress, encodeEthAddress } from "./eth.js";

const prefixlessAddress = "314159265dD8dbb310642f98f50C066173C1259b";
const hex = "314159265dd8dbb310642f98f50c066173c1259b";

test(`eth address: encode 0x${prefixlessAddress}`, () => {
expect(encodeEthAddress(hexToBytes(hex))).toEqual(`0x${prefixlessAddress}`);
});
test("eth address: invalid checksum", () => {
expect(() =>
decodeEthAddress("0x314159265Dd8Dbb310642f98F50C066173C1259b")
).toThrow();
});

describe.each([
{
text: "0x314159265dD8dbb310642f98f50C066173C1259b",
hex: "314159265dd8dbb310642f98f50c066173c1259b",
// checksummed address
text: `0x${prefixlessAddress}`,
},
])("eth address", ({ text, hex }) => {
test(`encode: ${text}`, () => {
expect(encodeEthAddress(hexToBytes(hex))).toEqual(text);
});
{
// all lowercased address
text: `0x${prefixlessAddress.toLowerCase()}`,
},
{
// all uppercased address
text: `0x${prefixlessAddress.toUpperCase()}`,
},
])("eth address", ({ text }) => {
test(`decode: ${text}`, () => {
expect(decodeEthAddress(text)).toEqual(hexToBytes(hex));
});
Expand Down
30 changes: 30 additions & 0 deletions src/utils/hex.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { describe, expect, test } from "bun:test";
import { isValidChecksumAddress } from "./hex.js";

const prefixlessAddress = "314159265dD8dbb310642f98f50C066173C1259b";

describe("isValidChecksumAddress()", () => {
test("valid checksum address", () => {
expect(isValidChecksumAddress(`0x${prefixlessAddress}`)).toBeTrue();
});
test("all lowercased address", () => {
expect(
isValidChecksumAddress(`0x${prefixlessAddress.toLowerCase()}`)
).toBeTrue();
});
test("all uppercased address", () => {
expect(
isValidChecksumAddress(`0x${prefixlessAddress.toUpperCase()}`)
).toBeTrue();
});
test("invalid checksum address", () => {
expect(
isValidChecksumAddress("0x314159265Dd8Dbb310642f98F50C066173C1259b")
).toBeFalse();
});
test("non-hex", () => {
expect(
isValidChecksumAddress("0x1234567890abcdefghijklmnopqrstuvwxyz0123")
).toBeFalse();
});
});
12 changes: 11 additions & 1 deletion src/utils/hex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,17 @@ export function isValidChecksumAddress(
address: string,
chainId?: number
): boolean {
return isAddress(address) && checksumAddress(address, chainId) === address;
if (!isAddress(address)) return false;

if (address === checksumAddress(address, chainId)) return true;

const prefixlessAddress = stripHexPrefix(address);
// all lowercase
if (prefixlessAddress.toLowerCase() === prefixlessAddress) return true;
// all uppercase
if (prefixlessAddress.toUpperCase() === prefixlessAddress) return true;

return false;
}

export const createHexChecksummedEncoder =
Expand Down
9 changes: 9 additions & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@ export {
isEvmCoinType,
} from "./evm.js";
export { validateFlowAddress } from "./flow.js";
export {
checksumAddress,
createHexChecksummedDecoder,
createHexChecksummedEncoder,
isAddress,
isValidChecksumAddress,
rawChecksumAddress,
stripHexPrefix,
} from "./hex.js";
export { decodeLeb128, encodeLeb128 } from "./leb128.js";
export { validateNearAddress } from "./near.js";
export { createZcashDecoder, createZcashEncoder } from "./zcash.js";

0 comments on commit 3dd92e1

Please sign in to comment.