From c814ebae24d54577910e2e46a09d190c1632da56 Mon Sep 17 00:00:00 2001 From: Alex Miller Date: Wed, 5 May 2021 16:50:31 -0500 Subject: [PATCH] Adds support for EIP712 edge cases --- package.json | 2 +- src/ethereum.js | 13 +++++++++++-- test/testEthMsg.js | 41 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index be5b65bf..0e7b16d3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gridplus-sdk", - "version": "0.7.12", + "version": "0.7.13", "description": "SDK to interact with GridPlus Lattice1 device", "scripts": { "commit": "git-cz", diff --git a/src/ethereum.js b/src/ethereum.js index f9f61fd8..78bb1ca2 100644 --- a/src/ethereum.js +++ b/src/ethereum.js @@ -606,6 +606,10 @@ function parseEIP712Item(data, type, isEthers=false) { } else if (type === 'address') { // Address must be a 20 byte buffer data = ensureHexBuffer(data); + // Edge case to handle the 0-address + if (data.length === 0) { + data = Buffer.alloc(20); + } if (data.length !== 20) throw new Error(`Address type must be 20 bytes, but got ${data.length} bytes`); // Ethers wants addresses as hex strings @@ -615,10 +619,15 @@ function parseEIP712Item(data, type, isEthers=false) { } else if (type === 'uint8' || type === 'uint16' || type === 'uint32' || type === 'uint64') { data = parseInt(ensureHexBuffer(data).toString('hex'), 16) } else if (type === 'uint256') { + let b = ensureHexBuffer(data); + // Edge case to handle 0-value bignums + if (b.length === 0) { + b = Buffer.from('00', 'hex'); + } // Uint256s should be encoded as bignums. if (isEthers === true) { // `ethers` uses their own BigNumber lib - data = ethers.BigNumber.from(`0x${ensureHexBuffer(data).toString('hex')}`) + data = ethers.BigNumber.from(`0x${b.toString('hex')}`) } else { // `bignumber.js` is needed for `cbor` encoding, which gets sent to the Lattice and plays // nicely with its firmware cbor lib. @@ -628,7 +637,7 @@ function parseEIP712Item(data, type, isEthers=false) { // TODO: Find another cbor lib that is compataible with the firmware's lib in a browser // context. This is surprisingly difficult - I tried several libs and only cbor/borc have // worked (borc is a supposedly "browser compatible" version of cbor) - data = new cbor.Encoder().semanticTypes[1][0](ensureHexBuffer(data).toString('hex'), 16) + data = new cbor.Encoder().semanticTypes[1][0](b.toString('hex'), 16) } } else if (type === 'bool') { // Booleans need to be cast to a u8 diff --git a/test/testEthMsg.js b/test/testEthMsg.js index 08ca31e1..4bcca45e 100644 --- a/test/testEthMsg.js +++ b/test/testEthMsg.js @@ -248,6 +248,47 @@ describe('Test ETH EIP712', function() { } }) + it('Should test an example with 0 values', async () => { + const msg = { + 'types': { + 'EIP712Domain': [ + { name: 'name', type: 'string' }, + { name: 'host', type: 'string'}, + { name: 'version', type: 'string' }, + { name: 'chainId', type: 'uint256' }, + { name: 'verifyingContract', type: 'address' }, + ], + 'Test': [ + { name: 'owner', type: 'string' }, + ] + }, + 'domain':{ + name: 'Opensea on Matic', + verifyingContract: '0x0', + version: '1', + chainId: '', + host: '', + }, + 'primaryType': 'Test', + 'message': { + 'owner': '0x56626bd0d646ce9da4a12403b2c1ba00fb9e1c43', + } + } + const req = { + currency: 'ETH_MSG', + data: { + signerPath: [helpers.BTC_LEGACY_PURPOSE, helpers.ETH_COIN, HARDENED_OFFSET, 0, 0], + protocol: 'eip712', + payload: msg, + } + } + try { + await helpers.sign(client, req); + } catch (err) { + expect(err).to.equal(null) + } + }) + it('Should test canonical EIP712 example', async () => { const msg = { types: {