Repository: 0xs34n/starknet.js
Pull request #279 (2022-08-03 12:52:50)

feat: change checksum address hashing algorithm
changes the hashing algo for checksum addresses from pedersen to keccak
this enables more efficient address checksum computation on x86


Patch:
diff --git a/src/utils/address.ts b/src/utils/address.ts
index 425ab2c4..4e76b5d7 100644
--- a/src/utils/address.ts
+++ b/src/utils/address.ts
@@ -3,7 +3,7 @@ import { arrayify } from '@ethersproject/bytes';
 
 import { MASK_251, ZERO } from '../constants';
 import { addHexPrefix, removeHexPrefix } from './encode';
-import { pedersen } from './hash';
+import { keccakBn } from './hash';
 import { BigNumberish, assertInRange, toBN, toHex } from './number';
 
 export function addAddressPadding(address: BigNumberish): string {
@@ -25,7 +25,7 @@ export function validateAndParseAddress(address: BigNumberish): string {
 // from https://github.com/ethers-io/ethers.js/blob/fc1e006575d59792fa97b4efb9ea2f8cca1944cf/packages/address/src.ts/index.ts#L12
 export function getChecksumAddress(address: BigNumberish): string {
   const chars = removeHexPrefix(validateAndParseAddress(address)).toLowerCase().split('');
-  const hashed = arrayify(pedersen([0, address]), { hexPad: 'left' }); // as the hash will be 251 bits (63 chars) we need to pad it to 64 chars without changing the number value ("left")
+  const hashed = arrayify(keccakBn(address), { hexPad: 'left' }); // in case the hash is 251 bits (63 chars) we need to pad it to 64 chars without changing the number value ("left")
 
   for (let i = 0; i < chars.length; i += 2) {
     if (hashed[i >> 1] >> 4 >= 8) {
diff --git a/src/utils/hash.ts b/src/utils/hash.ts
index 5bcf02c6..3c604137 100644
--- a/src/utils/hash.ts
+++ b/src/utils/hash.ts
@@ -1,5 +1,6 @@
 import BN from 'bn.js';
 import { keccak256 } from 'ethereum-cryptography/keccak';
+import { hexToBytes } from 'ethereum-cryptography/utils';
 import assert from 'minimalistic-assert';
 
 import {
@@ -13,12 +14,18 @@ import {
 } from '../constants';
 import { RawCalldata } from '../types/lib';
 import { ec } from './ellipticCurve';
-import { addHexPrefix, buf2hex, utf8ToArray } from './encode';
+import { addHexPrefix, buf2hex, removeHexPrefix, utf8ToArray } from './encode';
 import { BigNumberish, toBN, toFelt, toHex } from './number';
 
 export const transactionVersion = 0;
 export const feeTransactionVersion = toBN(2).pow(toBN(128)).add(toBN(transactionVersion));
 
+export function keccakBn(value: BigNumberish): string {
+  const hexWithoutPrefix = removeHexPrefix(toHex(toBN(value)));
+  const evenHex = hexWithoutPrefix.length % 2 === 0 ? hexWithoutPrefix : `0${hexWithoutPrefix}`;
+  return addHexPrefix(buf2hex(keccak256(hexToBytes(evenHex))));
+}
+
 function keccakHex(value: string): string {
   return addHexPrefix(buf2hex(keccak256(utf8ToArray(value))));
 }


Test patch:
diff --git a/__tests__/utils/address.test.ts b/__tests__/utils/address.test.ts
index b7d0b2b1..df8c48db 100644
--- a/__tests__/utils/address.test.ts
+++ b/__tests__/utils/address.test.ts
@@ -26,12 +26,12 @@ describe('address checksums', () => {
       '0x2fd23d9182193775423497fc0c472e156c57c69e4089a1967fb288a2d84e914'
     );
     expect(checksumAddress).toEqual(
-      '0x02FD23D9182193775423497Fc0c472E156C57C69E4089a1967fb288a2D84e914'
+      '0x02Fd23d9182193775423497fc0c472E156C57C69E4089A1967fb288A2d84e914'
     );
   });
   test('should be able to verify checksum address', () => {
     const isValid = validateChecksumAddress(
-      '0x02FD23D9182193775423497Fc0c472E156C57C69E4089a1967fb288a2D84e914'
+      '0x02Fd23d9182193775423497fc0c472E156C57C69E4089A1967fb288A2d84e914'
     );
     expect(isValid).toEqual(true);
   });