From 7adcf3b154669d9d1a0a66d5e15dabfbf6618180 Mon Sep 17 00:00:00 2001 From: Richard Moore Date: Mon, 31 May 2021 18:16:30 -0400 Subject: [PATCH] Fixed ENS namehash with leading and trailing dots (#1605). --- packages/hash/src.ts/namehash.ts | 12 ++++++--- packages/tests/src.ts/test-utils.ts | 39 ++++++++++++++++++++++++++--- 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/packages/hash/src.ts/namehash.ts b/packages/hash/src.ts/namehash.ts index d4b683bd2a..856a0be5a8 100644 --- a/packages/hash/src.ts/namehash.ts +++ b/packages/hash/src.ts/namehash.ts @@ -27,16 +27,20 @@ export function isValidName(name: string): boolean { export function namehash(name: string): string { /* istanbul ignore if */ if (typeof(name) !== "string") { - logger.throwArgumentError("invalid address - " + String(name), "name", name); + logger.throwArgumentError("invalid ENS name; not a string", "name", name); } + let current = name; let result: string | Uint8Array = Zeros; - while (name.length) { - const partition = name.match(Partition); + while (current.length) { + const partition = current.match(Partition); + if (partition == null || partition[2] === "") { + logger.throwArgumentError("invalid ENS address; missing component", "name", name); + } const label = toUtf8Bytes(nameprep(partition[3])); result = keccak256(concat([result, keccak256(label)])); - name = partition[2] || ""; + current = partition[2] || ""; } return hexlify(result); diff --git a/packages/tests/src.ts/test-utils.ts b/packages/tests/src.ts/test-utils.ts index fe25bcf97a..61adbd955c 100644 --- a/packages/tests/src.ts/test-utils.ts +++ b/packages/tests/src.ts/test-utils.ts @@ -242,11 +242,44 @@ describe('Test Namehash', function() { }); }); - it("isValidName", function() { - assert.ok(ethers.utils.isValidName("ricmoo.eth")); + const goodNames = [ + "ricmoo.eth", + "foo", + "foo.bar", + ]; + + const badNames = [ + ".", + "..", + "ricmoo..eth", + "ricmoo...eth", + ".foo", + "foo.", + ]; + // The empty string is not a valid name, but has the zero hash + // as its namehash, which may be used for recursive purposes + it("empty ENS name", function() { assert.ok(!ethers.utils.isValidName("")); - assert.ok(!ethers.utils.isValidName("ricmoo..eth")); + }); + + goodNames.forEach((name) => { + it(`ENS namehash ok - ${ name }`, function() { + assert.ok(ethers.utils.isValidName(name)); + ethers.utils.namehash(name); + }); + }); + + badNames.forEach((name) => { + it(`ENS namehash fails - ${ name }`, function() { + assert.ok(!ethers.utils.isValidName(name)); + assert.throws(() => { + const namehash = ethers.utils.namehash(name); + console.log(name, namehash); + }, (error: Error) => { + return !!error.message.match(/invalid ENS address/); + }); + }); }); });