Skip to content

Commit

Permalink
Util for removing EIP-191 prefix
Browse files Browse the repository at this point in the history
  • Loading branch information
tolgahan-arikan committed Jun 28, 2023
1 parent 78e71ef commit 67cd68a
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 4 deletions.
4 changes: 3 additions & 1 deletion packages/provider/src/transports/wallet-request-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,9 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P
if (typeof typedDataObject === 'string') {
try {
typedData = JSON.parse(typedDataObject)
} catch (e) {}
} catch (e) {
console.warn('error parsing typedData', e)
}
} else {
typedData = typedDataObject
}
Expand Down
66 changes: 66 additions & 0 deletions packages/provider/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,46 @@ export const prefixEIP191Message = (message: BytesLike): Uint8Array => {
}
}

export const removeEIP191Prefix = (prefixedMessage: Uint8Array): Uint8Array => {
// If the message is not prefixed, we return the message as is.
if (JSON.stringify(prefixedMessage.slice(0, eip191prefix.length)) !== JSON.stringify(eip191prefix)) {
return prefixedMessage
}

// We have two parts to remove.
// First is the EIP-191 prefix.
const ethereumSignedMessagePartSlicedArray = prefixedMessage.slice(eip191prefix.length)

// Second is the digits added which represent length of the message without the prefix
// and we need to find the prefix that will match this.
// Here first we take the max prefix char length, and check if as a number it is bigger
// than the length of the message (since prefix is added to represent length of original message),
// if it is we we remove 1 from char length, if not we keep the max prefix char length.
// As an example for the case where , if the message is 123456789, the expected prefix char is 9, with starting value 9123456789
// the char length of the total message with the prefix is 10, so the max prefix char length we start is 2 from [1,0], and as a number 10, it is longer
// than the length of the message after removing prefix (10 - 2 = 8), so we slice 1 char less, which is 9, and we get the correct prefix.
const maxPrefixCharLength = String(ethereumSignedMessagePartSlicedArray.length).length

let prefixCharLenght: number
let prefixAsNumber: number

try {
prefixAsNumber = Number(ethers.utils.toUtf8String(ethereumSignedMessagePartSlicedArray.slice(0, maxPrefixCharLength)))
} catch {
prefixAsNumber = Number(ethers.utils.hexlify(ethereumSignedMessagePartSlicedArray.slice(0, maxPrefixCharLength)))
}

if (prefixAsNumber > ethereumSignedMessagePartSlicedArray.length) {
prefixCharLenght = maxPrefixCharLength - 1
} else {
prefixCharLenght = maxPrefixCharLength
}

const prefixRevertedMessage = ethereumSignedMessagePartSlicedArray.slice(prefixCharLenght)

return prefixRevertedMessage
}

export const isValidSignature = async (
address: string,
digest: Uint8Array,
Expand All @@ -34,6 +74,7 @@ export const isValidSignature = async (
return reader.isValidSignature(address, digest, sig)
}

<<<<<<< Updated upstream

Check failure on line 77 in packages/provider/src/utils.ts

View workflow job for this annotation

GitHub Actions / Run build

Merge conflict marker encountered.
// export const isValidMessageSignature = async (
// address: string,
// message: string | Uint8Array,
Expand All @@ -57,6 +98,31 @@ export const isValidSignature = async (
// ): Promise<boolean> => {
// return isValidSignature(address, encodeTypedDataDigest(typedData), signature, provider, chainId, walletContext)
// }
=======

Check failure on line 101 in packages/provider/src/utils.ts

View workflow job for this annotation

GitHub Actions / Run build

Merge conflict marker encountered.
export const isValidMessageSignature = async (
address: string,
message: string | Uint8Array,
signature: string,
provider: Web3Provider | ethers.providers.Web3Provider | ethers.providers.Provider,
chainId?: number,
walletContext?: WalletContext
): Promise<boolean> => {
const prefixed = prefixEIP191Message(message)
const digest = encodeMessageDigest(prefixed)
return isValidSignature(address, digest, signature, provider, chainId, walletContext)
}

export const isValidTypedDataSignature = (
address: string,
typedData: TypedData,
signature: string,
provider: Web3Provider | ethers.providers.Web3Provider | ethers.providers.Provider,
chainId?: number,
walletContext?: WalletContext
): Promise<boolean> => {
return isValidSignature(address, encodeTypedDataDigest(typedData), signature, provider, chainId, walletContext)
}
>>>>>>> Stashed changes

Check failure on line 125 in packages/provider/src/utils.ts

View workflow job for this annotation

GitHub Actions / Run build

Merge conflict marker encountered.

// export const recoverWalletConfig = async (
// address: string,
Expand Down
48 changes: 45 additions & 3 deletions packages/provider/tests/messages.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { ethers } from 'ethers'
import { prefixEIP191Message } from '../src/utils'

// Ethereum personal sign: Hello, World!
export const message1 = new Uint8Array([
25, 69, 116, 104, 101, 114, 101, 117, 109, 32, 83, 105, 103, 110, 101, 100, 32, 77, 101, 115, 115, 97, 103, 101, 58, 10, 49, 51,
72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33
])


export const dclLogin = ethers.utils.toUtf8Bytes(`Decentraland Login
const dlcText = `Decentraland Login
Ephemeral address: 0xe1bCF3CAc83534a055f7254C1FD88B21159fCc67
Expiration: 2022-10-27T16:03:29.191Z`)
Expiration: 2022-10-27T16:03:29.191Z`

export const dclLogin = ethers.utils.toUtf8Bytes(dlcText)

// Ethereum personal sign 0x v3 order
export const zeroExV3Order = new Uint8Array([
Expand Down Expand Up @@ -47,3 +49,43 @@ export const zeroExV3Order = new Uint8Array([
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
])

// Messages for testing remove-iep191prefix

export const removeIep191Prefix_test1_raw = `1915 Robert Frost
The Road Not Taken
Two roads diverged in a yellow wood,
And sorry I could not travel both
And be one traveler, long I stood
And looked down one as far as I could
To where it bent in the undergrowth
Then took the other, as just as fair,
And having perhaps the better claim,
Because it was grassy and wanted wear
Though as for that the passing there
Had worn them really about the same,
And both that morning equally lay
In leaves no step had trodden black.
Oh, I kept the first for another day!
Yet knowing how way leads on to way,
I doubted if I should ever come back.
I shall be telling this with a sigh
Somewhere ages and ages hence:
Two roads diverged in a wood, and I—
I took the one less traveled by,
And that has made all the difference.
\u2601 \u2600 \u2602`
export const removeIep191Prefix_test2_raw = dlcText
export const removeIep191Prefix_test3_raw = '1915 Robe' // 9 chars
export const removeIep191Prefix_test4_raw =
'123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789' // 99 chars

export const removeIep191Prefix_test1_prefixed = prefixEIP191Message(removeIep191Prefix_test1_raw)
export const removeIep191Prefix_test2_prefixed = prefixEIP191Message(dlcText)
export const removeIep191Prefix_test3_prefixed = prefixEIP191Message(removeIep191Prefix_test3_raw)
export const removeIep191Prefix_test4_prefixed = prefixEIP191Message(removeIep191Prefix_test4_raw)
31 changes: 31 additions & 0 deletions packages/provider/tests/remove-eip191prefix.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import chaiAsPromised from 'chai-as-promised'
import * as chai from 'chai'

import {
removeIep191Prefix_test1_prefixed,
removeIep191Prefix_test1_raw,
removeIep191Prefix_test2_prefixed,
removeIep191Prefix_test2_raw,
removeIep191Prefix_test3_prefixed,
removeIep191Prefix_test3_raw,
removeIep191Prefix_test4_prefixed,
removeIep191Prefix_test4_raw
} from './messages'
import { removeEIP191Prefix } from '../src/utils'
import { ethers } from 'ethers'
const { expect } = chai.use(chaiAsPromised)

describe('removing eip191prefix', () => {
it('should remove prefix', () => {
expect(ethers.utils.toUtf8String(removeEIP191Prefix(removeIep191Prefix_test1_prefixed))).equal(removeIep191Prefix_test1_raw)
})

it('should handle eip191 exempt messages (by returning early)', () => {
expect(ethers.utils.toUtf8String(removeEIP191Prefix(removeIep191Prefix_test2_prefixed))).equal(removeIep191Prefix_test2_raw)
})

it('should remove prefix for case where max prefix char as number is bigger than the length of the message', () => {
expect(ethers.utils.toUtf8String(removeEIP191Prefix(removeIep191Prefix_test3_prefixed))).equal(removeIep191Prefix_test3_raw)
expect(ethers.utils.toUtf8String(removeEIP191Prefix(removeIep191Prefix_test4_prefixed))).equal(removeIep191Prefix_test4_raw)
})
})

0 comments on commit 67cd68a

Please sign in to comment.