From b0cde17bcea7b953f4f5d0c531c7c0998379a2c0 Mon Sep 17 00:00:00 2001 From: William Cory Date: Wed, 8 May 2024 11:56:34 -0700 Subject: [PATCH] feat: Make Address.toString() checksum --- packages/util/src/address.ts | 17 ++++++++++++++++- packages/util/test/address.spec.ts | 11 ++++++----- .../util/test/testdata/eip1014Examples.json | 12 ++++++------ 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/packages/util/src/address.ts b/packages/util/src/address.ts index 5fdf192df4..c1267f32ed 100644 --- a/packages/util/src/address.ts +++ b/packages/util/src/address.ts @@ -1,3 +1,5 @@ +import { keccak256 } from 'ethereum-cryptography/keccak.js' + import { generateAddress, generateAddress2, @@ -129,7 +131,20 @@ export class Address { * Returns hex encoding of address. */ toString(): PrefixedHexString { - return bytesToHex(this.bytes) + const unprefixedString = bytesToHex(this.bytes).substring(2).split('') + + const hash = keccak256(this.bytes) + + for (let i = 0; i < 40; i += 2) { + if (hash[i >> 1] >> 4 >= 8 && unprefixedString[i]) { + unprefixedString[i] = unprefixedString[i].toUpperCase() + } + if ((hash[i >> 1] & 0x0f) >= 8 && unprefixedString[i + 1]) { + unprefixedString[i + 1] = unprefixedString[i + 1].toUpperCase() + } + } + + return `0x${unprefixedString.join('')}` } /** diff --git a/packages/util/test/address.spec.ts b/packages/util/test/address.spec.ts index c0fc0b0e76..58abf28054 100644 --- a/packages/util/test/address.spec.ts +++ b/packages/util/test/address.spec.ts @@ -40,7 +40,7 @@ describe('Address', () => { const pubKey = hexToBytes( '0x3a443d8381a6798a70c6ff9304bdc8cb0163c23211d11628fae52ef9e0dca11a001cf066d56a8156fc201cd5df8a36ef694eecd258903fca7086c1fae7441e1d' ) - const str = '0x2f015c60e0be116b1f0cd534704db9c92118fb6a' + const str = '0x2f015c60E0BE116b1f0cd534704Db9c92118FB6a' const addr = Address.fromPublicKey(pubKey) assert.equal(addr.toString(), str) }) @@ -55,7 +55,7 @@ describe('Address', () => { it('should instantiate from private key', () => { // prettier-ignore const privateKey = Uint8Array.from([234, 84, 189, 197, 45, 22, 63, 136, 201, 58, 176, 97, 87, 130, 207, 113, 138, 46, 251, 158, 81, 167, 152, 154, 171, 27, 8, 6, 126, 156, 28, 95]) - const str = '0x2f015c60e0be116b1f0cd534704db9c92118fb6a' + const str = '0x2f015c60E0BE116b1f0cd534704Db9c92118FB6a' const addr = Address.fromPrivateKey(privateKey) assert.equal(addr.toString(), str) }) @@ -63,10 +63,10 @@ describe('Address', () => { it('should generate address for created contract', () => { const from = Address.fromString('0x990ccf8a0de58091c028d6ff76bb235ee67c1c39') const addr = Address.generate(from, BigInt(14)) - assert.equal(addr.toString(), '0xd658a4b8247c14868f3c512fa5cbb6e458e4a989') + assert.equal(addr.toString(), '0xd658a4b8247C14868F3c512fa5cBB6e458e4A989') const addr2 = Address.generate(from, BigInt(0)) - assert.equal(addr2.toString(), '0xbfa69ba91385206bfdd2d8b9c1a5d6c10097a85b') + assert.equal(addr2.toString(), '0xbFA69bA91385206BFdD2D8B9c1a5d6C10097a85b') }) it('should provide correct precompile check', () => { @@ -94,10 +94,11 @@ describe('Address', () => { it('should provide a Uint8Array that does not mutate the original address', () => { const str = '0x2f015c60e0be116b1f0cd534704db9c92118fb6a' + const checksumStr = '0x2f015c60E0BE116b1f0cd534704Db9c92118FB6a' const address = Address.fromString(str) const addressBytes = address.toBytes() addressBytes.fill(0) - assert.equal(address.toString(), str) + assert.equal(address.toString(), checksumStr) }) it('should compare equality properly', () => { diff --git a/packages/util/test/testdata/eip1014Examples.json b/packages/util/test/testdata/eip1014Examples.json index 18779b0509..d611abcdf0 100644 --- a/packages/util/test/testdata/eip1014Examples.json +++ b/packages/util/test/testdata/eip1014Examples.json @@ -13,7 +13,7 @@ "salt": "0x0000000000000000000000000000000000000000000000000000000000000000", "initCode": "0x00", "gas": "32006", - "result": "0xb928f69bb1d91cd65274e3c79d8986362984fda3" + "result": "0xB928F69Bb1D91cD65274e3C79D8986362984FdA3" }, { "comment": "Example 2", @@ -21,7 +21,7 @@ "salt": "0x000000000000000000000000feed000000000000000000000000000000000000", "initCode": "0x00", "gas": "32006", - "result": "0xd04116cdd17bebe565eb2422f2497e06cc1c9833" + "result": "0xD04116CdD17BEBE565EB2422F2497E06cc1c9833" }, { "comment": "Example 3", @@ -29,7 +29,7 @@ "salt": "0x0000000000000000000000000000000000000000000000000000000000000000", "initCode": "0xdeadbeef", "gas": "32006", - "result": "0x70f2b2914a2a4b783faefb75f459a580616fcb5e" + "result": "0x70f2B2914A2a4b783FAEfb75f459a580616fCb5e" }, { "comment": "Example 4", @@ -37,7 +37,7 @@ "salt": "0x00000000000000000000000000000000000000000000000000000000cafebabe", "initCode": "0xdeadbeef", "gas": "32006", - "result": "0x60f3f640a8508fc6a86d45df051962668e1e8ac7" + "result": "0x60f3F640a8508Fc6a86D45dF051962668e1e8ac7" }, { "comment": "Example 5", @@ -45,7 +45,7 @@ "salt": "0x00000000000000000000000000000000000000000000000000000000cafebabe", "initCode": "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", "gas": "32012", - "result": "0x1d8bfdc5d46dc4f61d6b6115972536ebe6a8854c" + "result": "0x1D8BfDC5d46Dc4f61d6b6115972536ebe6A8854c" }, { "comment": "Example 6", @@ -53,6 +53,6 @@ "salt": "0x0000000000000000000000000000000000000000000000000000000000000000", "initCode": "0x", "gas": "32000", - "result": "0xe33c0c7f7df4809055c3eba6c09cfe4baf1bd9e0" + "result": "0xE33c0c7F7Df4809055C3Eba6c09cfe4baF1BD9E0" } ]