From b41746fc27577a7e486e20fab9cb4768f5b6da14 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Thu, 22 Jul 2021 17:31:02 -0230 Subject: [PATCH] Add unit tests for `encodeData` The function `TypedDataUtils.encodeData` has been thoroughly tested with all novel inputs I could think of. Each supported version (V3 and V4) have been tested independently with each input. There are also tests for each input that should have an identical encoding between V3 and V4, and each that should have non-matching signatures.. The `encodeData` assertions that accompanied the signature tests have been deleted, as they're now redundant. --- src/__snapshots__/index.test.ts.snap | 305 +++++ src/index.test.ts | 1639 ++++++++++++++++++++++---- 2 files changed, 1730 insertions(+), 214 deletions(-) create mode 100644 src/__snapshots__/index.test.ts.snap diff --git a/src/__snapshots__/index.test.ts.snap b/src/__snapshots__/index.test.ts.snap new file mode 100644 index 00000000..fb8c5b00 --- /dev/null +++ b/src/__snapshots__/index.test.ts.snap @@ -0,0 +1,305 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`TypedDataUtils.encodeData V3 example data type "address" should encode "0x0" (type "string") 1`] = `"c92db6bca97089c40b3f6512400e065cf2c27db90a50ce13440d951b13ada2990000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "address" should encode "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" (type "string") 1`] = `"c92db6bca97089c40b3f6512400e065cf2c27db90a50ce13440d951b13ada299000000000000000000000000bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"`; + +exports[`TypedDataUtils.encodeData V3 example data type "address" should encode "10" (type "number") 1`] = `"c92db6bca97089c40b3f6512400e065cf2c27db90a50ce13440d951b13ada299000000000000000000000000000000000000000000000000000000000000000a"`; + +exports[`TypedDataUtils.encodeData V3 example data type "address" should encode "9007199254740991" (type "number") 1`] = `"c92db6bca97089c40b3f6512400e065cf2c27db90a50ce13440d951b13ada299000000000000000000000000000000000000000000000000001fffffffffffff"`; + +exports[`TypedDataUtils.encodeData V3 example data type "address" should encode "bBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" (type "string") 1`] = `"c92db6bca97089c40b3f6512400e065cf2c27db90a50ce13440d951b13ada29900000000000000000000000000000023eafa60608dacea43aa64cbe38e38e38d"`; + +exports[`TypedDataUtils.encodeData V3 example data type "bool" should encode "-1" (type "number") 1`] = `"83478c46da931c2f6871fdb6febd69a27b0ebc8c91f3e2cf580c3bd8777690060000000000000000000000000000000000000000000000000000000000000001"`; + +exports[`TypedDataUtils.encodeData V3 example data type "bool" should encode "0" (type "number") 1`] = `"83478c46da931c2f6871fdb6febd69a27b0ebc8c91f3e2cf580c3bd8777690060000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "bool" should encode "1" (type "number") 1`] = `"83478c46da931c2f6871fdb6febd69a27b0ebc8c91f3e2cf580c3bd8777690060000000000000000000000000000000000000000000000000000000000000001"`; + +exports[`TypedDataUtils.encodeData V3 example data type "bool" should encode "9007199254740991" (type "number") 1`] = `"83478c46da931c2f6871fdb6febd69a27b0ebc8c91f3e2cf580c3bd8777690060000000000000000000000000000000000000000000000000000000000000001"`; + +exports[`TypedDataUtils.encodeData V3 example data type "bool" should encode "false" (type "boolean") 1`] = `"83478c46da931c2f6871fdb6febd69a27b0ebc8c91f3e2cf580c3bd8777690060000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "bool" should encode "false" (type "string") 1`] = `"83478c46da931c2f6871fdb6febd69a27b0ebc8c91f3e2cf580c3bd8777690060000000000000000000000000000000000000000000000000000000000000001"`; + +exports[`TypedDataUtils.encodeData V3 example data type "bool" should encode "true" (type "boolean") 1`] = `"83478c46da931c2f6871fdb6febd69a27b0ebc8c91f3e2cf580c3bd8777690060000000000000000000000000000000000000000000000000000000000000001"`; + +exports[`TypedDataUtils.encodeData V3 example data type "bool" should encode "true" (type "string") 1`] = `"83478c46da931c2f6871fdb6febd69a27b0ebc8c91f3e2cf580c3bd8777690060000000000000000000000000000000000000000000000000000000000000001"`; + +exports[`TypedDataUtils.encodeData V3 example data type "bytes" should encode "0x10" (type "string") 1`] = `"fe4e90aeb2dead25fb44e8b67b2f9cdb3cabea1f7555b81fcc61f7103acf5d50967f2a2c7f3d22f9278175c1e6aa39cf9171db91dceacd5ee0f37c2e507b5abe"`; + +exports[`TypedDataUtils.encodeData V3 example data type "bytes" should encode "10" (type "Buffer") 1`] = `"fe4e90aeb2dead25fb44e8b67b2f9cdb3cabea1f7555b81fcc61f7103acf5d501a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac"`; + +exports[`TypedDataUtils.encodeData V3 example data type "bytes" should encode "10" (type "number") 1`] = `"fe4e90aeb2dead25fb44e8b67b2f9cdb3cabea1f7555b81fcc61f7103acf5d500ef9d8f8804d174666011a394cab7901679a8944d24249fd148a6a36071151f8"`; + +exports[`TypedDataUtils.encodeData V3 example data type "bytes" should encode "10" (type "string") 1`] = `"fe4e90aeb2dead25fb44e8b67b2f9cdb3cabea1f7555b81fcc61f7103acf5d501a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac"`; + +exports[`TypedDataUtils.encodeData V3 example data type "bytes1" should encode "-1" (type "number") 1`] = `"d8a209ce0fa251cc20dc51c9e2a6f02972a597da1b7ad07b3f2d6c1072f947d40000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "bytes1" should encode "0" (type "number") 1`] = `"d8a209ce0fa251cc20dc51c9e2a6f02972a597da1b7ad07b3f2d6c1072f947d40000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "bytes1" should encode "0x10" (type "string") 1`] = `"d8a209ce0fa251cc20dc51c9e2a6f02972a597da1b7ad07b3f2d6c1072f947d41000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "bytes1" should encode "1" (type "number") 1`] = `"d8a209ce0fa251cc20dc51c9e2a6f02972a597da1b7ad07b3f2d6c1072f947d40100000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "bytes1" should encode "10" (type "Buffer") 1`] = `"d8a209ce0fa251cc20dc51c9e2a6f02972a597da1b7ad07b3f2d6c1072f947d43130000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "bytes1" should encode "10" (type "number") 1`] = `"d8a209ce0fa251cc20dc51c9e2a6f02972a597da1b7ad07b3f2d6c1072f947d40a00000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "bytes1" should encode "9007199254740991" (type "number") 1`] = `"d8a209ce0fa251cc20dc51c9e2a6f02972a597da1b7ad07b3f2d6c1072f947d41fffffffffffff00000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "bytes32" should encode "-1" (type "number") 1`] = `"52655953990606cd6b4a6e2c47eaca3268e30dcbd0cd930457e9877b65b4457b0000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "bytes32" should encode "0" (type "number") 1`] = `"52655953990606cd6b4a6e2c47eaca3268e30dcbd0cd930457e9877b65b4457b0000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "bytes32" should encode "0x10" (type "string") 1`] = `"52655953990606cd6b4a6e2c47eaca3268e30dcbd0cd930457e9877b65b4457b1000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "bytes32" should encode "1" (type "number") 1`] = `"52655953990606cd6b4a6e2c47eaca3268e30dcbd0cd930457e9877b65b4457b0100000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "bytes32" should encode "10" (type "Buffer") 1`] = `"52655953990606cd6b4a6e2c47eaca3268e30dcbd0cd930457e9877b65b4457b3130000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "bytes32" should encode "10" (type "number") 1`] = `"52655953990606cd6b4a6e2c47eaca3268e30dcbd0cd930457e9877b65b4457b0a00000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "bytes32" should encode "9007199254740991" (type "number") 1`] = `"52655953990606cd6b4a6e2c47eaca3268e30dcbd0cd930457e9877b65b4457b1fffffffffffff00000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "int" should encode "-9007199254740991" (type "number") 1`] = `"eb542693947f45083bc98c9628ebab536657139910ee549407af31fe8f8fe49cffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000001"`; + +exports[`TypedDataUtils.encodeData V3 example data type "int" should encode "0" (type "number") 1`] = `"eb542693947f45083bc98c9628ebab536657139910ee549407af31fe8f8fe49c0000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "int" should encode "0" (type "string") 1`] = `"eb542693947f45083bc98c9628ebab536657139910ee549407af31fe8f8fe49c0000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "int" should encode "0x0" (type "string") 1`] = `"eb542693947f45083bc98c9628ebab536657139910ee549407af31fe8f8fe49c0000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "int" should encode "9007199254740991" (type "number") 1`] = `"eb542693947f45083bc98c9628ebab536657139910ee549407af31fe8f8fe49c000000000000000000000000000000000000000000000000001fffffffffffff"`; + +exports[`TypedDataUtils.encodeData V3 example data type "int8" should encode "-255" (type "number") 1`] = `"4aef32d02ba398126fc35c6d9a88d8d3aed515b289c8f93cb3dd13c0dcce59fbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01"`; + +exports[`TypedDataUtils.encodeData V3 example data type "int8" should encode "0" (type "number") 1`] = `"4aef32d02ba398126fc35c6d9a88d8d3aed515b289c8f93cb3dd13c0dcce59fb0000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "int8" should encode "0" (type "string") 1`] = `"4aef32d02ba398126fc35c6d9a88d8d3aed515b289c8f93cb3dd13c0dcce59fb0000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "int8" should encode "0x0" (type "string") 1`] = `"4aef32d02ba398126fc35c6d9a88d8d3aed515b289c8f93cb3dd13c0dcce59fb0000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "int8" should encode "255" (type "number") 1`] = `"4aef32d02ba398126fc35c6d9a88d8d3aed515b289c8f93cb3dd13c0dcce59fb00000000000000000000000000000000000000000000000000000000000000ff"`; + +exports[`TypedDataUtils.encodeData V3 example data type "int256" should encode "-9007199254740991" (type "number") 1`] = `"92df05a78cb59efa9932e6f413a3ac303b2277ff40968e8a21bd96c6e085f729ffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000001"`; + +exports[`TypedDataUtils.encodeData V3 example data type "int256" should encode "0" (type "number") 1`] = `"92df05a78cb59efa9932e6f413a3ac303b2277ff40968e8a21bd96c6e085f7290000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "int256" should encode "0" (type "string") 1`] = `"92df05a78cb59efa9932e6f413a3ac303b2277ff40968e8a21bd96c6e085f7290000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "int256" should encode "0x0" (type "string") 1`] = `"92df05a78cb59efa9932e6f413a3ac303b2277ff40968e8a21bd96c6e085f7290000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "int256" should encode "9007199254740991" (type "number") 1`] = `"92df05a78cb59efa9932e6f413a3ac303b2277ff40968e8a21bd96c6e085f729000000000000000000000000000000000000000000000000001fffffffffffff"`; + +exports[`TypedDataUtils.encodeData V3 example data type "string" should encode "0xabcd" (type "string") 1`] = `"cddf41b07426e1a761f3da57e35474ae3deaa5b596306531f651c6dc1321e4fd77b446f7f7431b79d3ee0ee3faafefd90f1f8cc91b5c88cf21bac16ac0c8590b"`; + +exports[`TypedDataUtils.encodeData V3 example data type "string" should encode "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" (type "string") 1`] = `"cddf41b07426e1a761f3da57e35474ae3deaa5b596306531f651c6dc1321e4fd27aef794f1afdd9a6773306ef8f29c344d0552ebe46aae1268c55a683c37e68e"`; + +exports[`TypedDataUtils.encodeData V3 example data type "string" should encode "10" (type "number") 1`] = `"cddf41b07426e1a761f3da57e35474ae3deaa5b596306531f651c6dc1321e4fd0ef9d8f8804d174666011a394cab7901679a8944d24249fd148a6a36071151f8"`; + +exports[`TypedDataUtils.encodeData V3 example data type "string" should encode "Hello!" (type "string") 1`] = `"cddf41b07426e1a761f3da57e35474ae3deaa5b596306531f651c6dc1321e4fd6cdba77591a790691c694fa0be937f835b8a589095e427022aa1035e579ee596"`; + +exports[`TypedDataUtils.encodeData V3 example data type "string" should encode "😁" (type "string") 1`] = `"cddf41b07426e1a761f3da57e35474ae3deaa5b596306531f651c6dc1321e4fdefd5e893bdf9a51aa4d52297a64d0f7b1091407c347ca2eb8c02657e50717843"`; + +exports[`TypedDataUtils.encodeData V3 example data type "uint" should encode "0" (type "number") 1`] = `"8648acc768404f6d212f46260e326812d31b253b3963e2482f8bba6a0ca7fef10000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "uint" should encode "0" (type "string") 1`] = `"8648acc768404f6d212f46260e326812d31b253b3963e2482f8bba6a0ca7fef10000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "uint" should encode "0x0" (type "string") 1`] = `"8648acc768404f6d212f46260e326812d31b253b3963e2482f8bba6a0ca7fef10000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "uint" should encode "9007199254740991" (type "number") 1`] = `"8648acc768404f6d212f46260e326812d31b253b3963e2482f8bba6a0ca7fef1000000000000000000000000000000000000000000000000001fffffffffffff"`; + +exports[`TypedDataUtils.encodeData V3 example data type "uint8" should encode "0" (type "number") 1`] = `"997a0c895f7d046e9d4bcfa5de41b03f33ca7fa213cb1325edd0cad1e9c3864c0000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "uint8" should encode "0" (type "string") 1`] = `"997a0c895f7d046e9d4bcfa5de41b03f33ca7fa213cb1325edd0cad1e9c3864c0000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "uint8" should encode "0x0" (type "string") 1`] = `"997a0c895f7d046e9d4bcfa5de41b03f33ca7fa213cb1325edd0cad1e9c3864c0000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "uint8" should encode "255" (type "number") 1`] = `"997a0c895f7d046e9d4bcfa5de41b03f33ca7fa213cb1325edd0cad1e9c3864c00000000000000000000000000000000000000000000000000000000000000ff"`; + +exports[`TypedDataUtils.encodeData V3 example data type "uint256" should encode "0" (type "number") 1`] = `"313eafedfe20c8366f87086b9ac5b8b0ad47b49842a8eb76a8a746dfea3ff8d10000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "uint256" should encode "0" (type "string") 1`] = `"313eafedfe20c8366f87086b9ac5b8b0ad47b49842a8eb76a8a746dfea3ff8d10000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "uint256" should encode "0x0" (type "string") 1`] = `"313eafedfe20c8366f87086b9ac5b8b0ad47b49842a8eb76a8a746dfea3ff8d10000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V3 example data type "uint256" should encode "9007199254740991" (type "number") 1`] = `"313eafedfe20c8366f87086b9ac5b8b0ad47b49842a8eb76a8a746dfea3ff8d1000000000000000000000000000000000000000000000000001fffffffffffff"`; + +exports[`TypedDataUtils.encodeData V3 should encode data when given extraneous types 1`] = `"cddf41b07426e1a761f3da57e35474ae3deaa5b596306531f651c6dc1321e4fd6cdba77591a790691c694fa0be937f835b8a589095e427022aa1035e579ee596"`; + +exports[`TypedDataUtils.encodeData V3 should encode data with a custom type property set to undefined 1`] = `"a0cedeb2dc280ba39b857546d74f5549c3a1d7bdc2dd96bf881f76108e23dac2fc71e5fa27ff56c350aa531bc129ebdf613b772b6604664f5d8dbe21b85eb0c8b5aadf3154a261abdd9086fc627b61efca26ae5702701d05cd2305f7c52a2fc8"`; + +exports[`TypedDataUtils.encodeData V3 should encode data with a dynamic property set to null 1`] = `"a0cedeb2dc280ba39b857546d74f5549c3a1d7bdc2dd96bf881f76108e23dac2fc71e5fa27ff56c350aa531bc129ebdf613b772b6604664f5d8dbe21b85eb0c8cd54f074a4af31b4411ff6a60c9719dbd559c221c8ac3492d9d872b041d703d1c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"`; + +exports[`TypedDataUtils.encodeData V3 should encode data with a dynamic property set to undefined 1`] = `"a0cedeb2dc280ba39b857546d74f5549c3a1d7bdc2dd96bf881f76108e23dac2fc71e5fa27ff56c350aa531bc129ebdf613b772b6604664f5d8dbe21b85eb0c8cd54f074a4af31b4411ff6a60c9719dbd559c221c8ac3492d9d872b041d703d1"`; + +exports[`TypedDataUtils.encodeData V3 should encode data with a recursive data type 1`] = `"66658e9662034bcd21df657297dab8ba47f0ae05dd8aa253cc935d9aacfd9d10fc71e5fa27ff56c350aa531bc129ebdf613b772b6604664f5d8dbe21b85eb0c8cd54f074a4af31b4411ff6a60c9719dbd559c221c8ac3492d9d872b041d703d1b5aadf3154a261abdd9086fc627b61efca26ae5702701d05cd2305f7c52a2fc8585a30736f22452235ee25aabb6e4c2a6a22c8cf007855687a076a95d15f00c0"`; + +exports[`TypedDataUtils.encodeData V3 should encode data with an atomic property set to undefined 1`] = `"2445b23f0dc0a35bae9b7bd2bd12c89a2db0f66a4a73c8e8b95df6729c227c43fc71e5fa27ff56c350aa531bc129ebdf613b772b6604664f5d8dbe21b85eb0c8cd54f074a4af31b4411ff6a60c9719dbd559c221c8ac3492d9d872b041d703d16cdba77591a790691c694fa0be937f835b8a589095e427022aa1035e579ee596"`; + +exports[`TypedDataUtils.encodeData V3 should encode data with custom type 1`] = `"a0cedeb2dc280ba39b857546d74f5549c3a1d7bdc2dd96bf881f76108e23dac2fc71e5fa27ff56c350aa531bc129ebdf613b772b6604664f5d8dbe21b85eb0c8cd54f074a4af31b4411ff6a60c9719dbd559c221c8ac3492d9d872b041d703d1b5aadf3154a261abdd9086fc627b61efca26ae5702701d05cd2305f7c52a2fc8"`; + +exports[`TypedDataUtils.encodeData V4 example data type "address" should encode "0x0" (type "string") 1`] = `"c92db6bca97089c40b3f6512400e065cf2c27db90a50ce13440d951b13ada2990000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "address" should encode "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" (type "string") 1`] = `"c92db6bca97089c40b3f6512400e065cf2c27db90a50ce13440d951b13ada299000000000000000000000000bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"`; + +exports[`TypedDataUtils.encodeData V4 example data type "address" should encode "10" (type "number") 1`] = `"c92db6bca97089c40b3f6512400e065cf2c27db90a50ce13440d951b13ada299000000000000000000000000000000000000000000000000000000000000000a"`; + +exports[`TypedDataUtils.encodeData V4 example data type "address" should encode "9007199254740991" (type "number") 1`] = `"c92db6bca97089c40b3f6512400e065cf2c27db90a50ce13440d951b13ada299000000000000000000000000000000000000000000000000001fffffffffffff"`; + +exports[`TypedDataUtils.encodeData V4 example data type "address" should encode "bBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" (type "string") 1`] = `"c92db6bca97089c40b3f6512400e065cf2c27db90a50ce13440d951b13ada29900000000000000000000000000000023eafa60608dacea43aa64cbe38e38e38d"`; + +exports[`TypedDataUtils.encodeData V4 example data type "address" should encode array of all address example data 1`] = `"1cf487eff7ac1d95e8069104ae1f91e4ecc076c3a5c23645a8b93a413d1bc711fa75cd6a6143b2ef96f5b20e286458c4c04dbfc80f6ea0eef003042890658d63"`; + +exports[`TypedDataUtils.encodeData V4 example data type "bool" should encode "-1" (type "number") 1`] = `"83478c46da931c2f6871fdb6febd69a27b0ebc8c91f3e2cf580c3bd8777690060000000000000000000000000000000000000000000000000000000000000001"`; + +exports[`TypedDataUtils.encodeData V4 example data type "bool" should encode "0" (type "number") 1`] = `"83478c46da931c2f6871fdb6febd69a27b0ebc8c91f3e2cf580c3bd8777690060000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "bool" should encode "1" (type "number") 1`] = `"83478c46da931c2f6871fdb6febd69a27b0ebc8c91f3e2cf580c3bd8777690060000000000000000000000000000000000000000000000000000000000000001"`; + +exports[`TypedDataUtils.encodeData V4 example data type "bool" should encode "9007199254740991" (type "number") 1`] = `"83478c46da931c2f6871fdb6febd69a27b0ebc8c91f3e2cf580c3bd8777690060000000000000000000000000000000000000000000000000000000000000001"`; + +exports[`TypedDataUtils.encodeData V4 example data type "bool" should encode "false" (type "boolean") 1`] = `"83478c46da931c2f6871fdb6febd69a27b0ebc8c91f3e2cf580c3bd8777690060000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "bool" should encode "false" (type "string") 1`] = `"83478c46da931c2f6871fdb6febd69a27b0ebc8c91f3e2cf580c3bd8777690060000000000000000000000000000000000000000000000000000000000000001"`; + +exports[`TypedDataUtils.encodeData V4 example data type "bool" should encode "true" (type "boolean") 1`] = `"83478c46da931c2f6871fdb6febd69a27b0ebc8c91f3e2cf580c3bd8777690060000000000000000000000000000000000000000000000000000000000000001"`; + +exports[`TypedDataUtils.encodeData V4 example data type "bool" should encode "true" (type "string") 1`] = `"83478c46da931c2f6871fdb6febd69a27b0ebc8c91f3e2cf580c3bd8777690060000000000000000000000000000000000000000000000000000000000000001"`; + +exports[`TypedDataUtils.encodeData V4 example data type "bool" should encode array of all bool example data 1`] = `"f2b07a6e9f364e1284b89fa1c7ea1c89520fd1eb16169108f5c86e3ff94a80ab67ab9e81b4411ccf66289482fc98cdf324bcadcc0e113aa64abf6c115dda652d"`; + +exports[`TypedDataUtils.encodeData V4 example data type "bytes" should encode "0x10" (type "string") 1`] = `"fe4e90aeb2dead25fb44e8b67b2f9cdb3cabea1f7555b81fcc61f7103acf5d50967f2a2c7f3d22f9278175c1e6aa39cf9171db91dceacd5ee0f37c2e507b5abe"`; + +exports[`TypedDataUtils.encodeData V4 example data type "bytes" should encode "10" (type "Buffer") 1`] = `"fe4e90aeb2dead25fb44e8b67b2f9cdb3cabea1f7555b81fcc61f7103acf5d501a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac"`; + +exports[`TypedDataUtils.encodeData V4 example data type "bytes" should encode "10" (type "number") 1`] = `"fe4e90aeb2dead25fb44e8b67b2f9cdb3cabea1f7555b81fcc61f7103acf5d500ef9d8f8804d174666011a394cab7901679a8944d24249fd148a6a36071151f8"`; + +exports[`TypedDataUtils.encodeData V4 example data type "bytes" should encode "10" (type "string") 1`] = `"fe4e90aeb2dead25fb44e8b67b2f9cdb3cabea1f7555b81fcc61f7103acf5d501a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac"`; + +exports[`TypedDataUtils.encodeData V4 example data type "bytes" should encode array of all bytes example data 1`] = `"93f286650d21b73fafa0cf1f6da3997b287c960d06b6f072958b05a5502e54fec964742242e21f8943cc82ff74617f3ed0cf245665fe94771f7370376eefb3e4"`; + +exports[`TypedDataUtils.encodeData V4 example data type "bytes1" should encode "-1" (type "number") 1`] = `"d8a209ce0fa251cc20dc51c9e2a6f02972a597da1b7ad07b3f2d6c1072f947d40000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "bytes1" should encode "0" (type "number") 1`] = `"d8a209ce0fa251cc20dc51c9e2a6f02972a597da1b7ad07b3f2d6c1072f947d40000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "bytes1" should encode "0x10" (type "string") 1`] = `"d8a209ce0fa251cc20dc51c9e2a6f02972a597da1b7ad07b3f2d6c1072f947d41000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "bytes1" should encode "1" (type "number") 1`] = `"d8a209ce0fa251cc20dc51c9e2a6f02972a597da1b7ad07b3f2d6c1072f947d40100000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "bytes1" should encode "10" (type "Buffer") 1`] = `"d8a209ce0fa251cc20dc51c9e2a6f02972a597da1b7ad07b3f2d6c1072f947d43130000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "bytes1" should encode "10" (type "number") 1`] = `"d8a209ce0fa251cc20dc51c9e2a6f02972a597da1b7ad07b3f2d6c1072f947d40a00000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "bytes1" should encode "9007199254740991" (type "number") 1`] = `"d8a209ce0fa251cc20dc51c9e2a6f02972a597da1b7ad07b3f2d6c1072f947d41fffffffffffff00000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "bytes1" should encode array of all bytes1 example data 1`] = `"1e57d55fc891c8f082cff324b667e4ed7e807773f2dcbe0d0c7a74e4556bf8e5db853c63de26376b9da8f3d0b6d6a2baea1220764ac348253dd51d741deb5664"`; + +exports[`TypedDataUtils.encodeData V4 example data type "bytes32" should encode "-1" (type "number") 1`] = `"52655953990606cd6b4a6e2c47eaca3268e30dcbd0cd930457e9877b65b4457b0000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "bytes32" should encode "0" (type "number") 1`] = `"52655953990606cd6b4a6e2c47eaca3268e30dcbd0cd930457e9877b65b4457b0000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "bytes32" should encode "0x10" (type "string") 1`] = `"52655953990606cd6b4a6e2c47eaca3268e30dcbd0cd930457e9877b65b4457b1000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "bytes32" should encode "1" (type "number") 1`] = `"52655953990606cd6b4a6e2c47eaca3268e30dcbd0cd930457e9877b65b4457b0100000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "bytes32" should encode "10" (type "Buffer") 1`] = `"52655953990606cd6b4a6e2c47eaca3268e30dcbd0cd930457e9877b65b4457b3130000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "bytes32" should encode "10" (type "number") 1`] = `"52655953990606cd6b4a6e2c47eaca3268e30dcbd0cd930457e9877b65b4457b0a00000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "bytes32" should encode "9007199254740991" (type "number") 1`] = `"52655953990606cd6b4a6e2c47eaca3268e30dcbd0cd930457e9877b65b4457b1fffffffffffff00000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "bytes32" should encode array of all bytes32 example data 1`] = `"75cc52002948d7a0f70c257e540f4687c12b56e30b3a0ee3e5e6f71e1f76ec13db853c63de26376b9da8f3d0b6d6a2baea1220764ac348253dd51d741deb5664"`; + +exports[`TypedDataUtils.encodeData V4 example data type "int" should encode "-9007199254740991" (type "number") 1`] = `"eb542693947f45083bc98c9628ebab536657139910ee549407af31fe8f8fe49cffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000001"`; + +exports[`TypedDataUtils.encodeData V4 example data type "int" should encode "0" (type "number") 1`] = `"eb542693947f45083bc98c9628ebab536657139910ee549407af31fe8f8fe49c0000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "int" should encode "0" (type "string") 1`] = `"eb542693947f45083bc98c9628ebab536657139910ee549407af31fe8f8fe49c0000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "int" should encode "0x0" (type "string") 1`] = `"eb542693947f45083bc98c9628ebab536657139910ee549407af31fe8f8fe49c0000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "int" should encode "9007199254740991" (type "number") 1`] = `"eb542693947f45083bc98c9628ebab536657139910ee549407af31fe8f8fe49c000000000000000000000000000000000000000000000000001fffffffffffff"`; + +exports[`TypedDataUtils.encodeData V4 example data type "int" should encode array of all int example data 1`] = `"f1e952da5f44a2503d1cc29bec179593cf7f5b7e05b1aedfa8fbb97ec1cf944ddb561d5e1d1b52adaa4c13e82c4cf8eb7b434f9cdf00afca99876cdb9a41fd8b"`; + +exports[`TypedDataUtils.encodeData V4 example data type "int8" should encode "-255" (type "number") 1`] = `"4aef32d02ba398126fc35c6d9a88d8d3aed515b289c8f93cb3dd13c0dcce59fbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01"`; + +exports[`TypedDataUtils.encodeData V4 example data type "int8" should encode "0" (type "number") 1`] = `"4aef32d02ba398126fc35c6d9a88d8d3aed515b289c8f93cb3dd13c0dcce59fb0000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "int8" should encode "0" (type "string") 1`] = `"4aef32d02ba398126fc35c6d9a88d8d3aed515b289c8f93cb3dd13c0dcce59fb0000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "int8" should encode "0x0" (type "string") 1`] = `"4aef32d02ba398126fc35c6d9a88d8d3aed515b289c8f93cb3dd13c0dcce59fb0000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "int8" should encode "255" (type "number") 1`] = `"4aef32d02ba398126fc35c6d9a88d8d3aed515b289c8f93cb3dd13c0dcce59fb00000000000000000000000000000000000000000000000000000000000000ff"`; + +exports[`TypedDataUtils.encodeData V4 example data type "int8" should encode array of all int8 example data 1`] = `"91759f19c54cc4a4d7476b7d4cd66f7b7d5d3fa0a4d6c16a2b0d700eae493a76bd5c1899378bae107a8d8dbdf757cce31cd3bac12b7b30ef2b1f4d623f92e4c3"`; + +exports[`TypedDataUtils.encodeData V4 example data type "int256" should encode "-9007199254740991" (type "number") 1`] = `"92df05a78cb59efa9932e6f413a3ac303b2277ff40968e8a21bd96c6e085f729ffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000001"`; + +exports[`TypedDataUtils.encodeData V4 example data type "int256" should encode "0" (type "number") 1`] = `"92df05a78cb59efa9932e6f413a3ac303b2277ff40968e8a21bd96c6e085f7290000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "int256" should encode "0" (type "string") 1`] = `"92df05a78cb59efa9932e6f413a3ac303b2277ff40968e8a21bd96c6e085f7290000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "int256" should encode "0x0" (type "string") 1`] = `"92df05a78cb59efa9932e6f413a3ac303b2277ff40968e8a21bd96c6e085f7290000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "int256" should encode "9007199254740991" (type "number") 1`] = `"92df05a78cb59efa9932e6f413a3ac303b2277ff40968e8a21bd96c6e085f729000000000000000000000000000000000000000000000000001fffffffffffff"`; + +exports[`TypedDataUtils.encodeData V4 example data type "int256" should encode array of all int256 example data 1`] = `"49bbb3a2417df7595b381726082b4d105bdacd79d8e3d4936b8f2aae95d9e26edb561d5e1d1b52adaa4c13e82c4cf8eb7b434f9cdf00afca99876cdb9a41fd8b"`; + +exports[`TypedDataUtils.encodeData V4 example data type "string" should encode "0xabcd" (type "string") 1`] = `"cddf41b07426e1a761f3da57e35474ae3deaa5b596306531f651c6dc1321e4fd77b446f7f7431b79d3ee0ee3faafefd90f1f8cc91b5c88cf21bac16ac0c8590b"`; + +exports[`TypedDataUtils.encodeData V4 example data type "string" should encode "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" (type "string") 1`] = `"cddf41b07426e1a761f3da57e35474ae3deaa5b596306531f651c6dc1321e4fd27aef794f1afdd9a6773306ef8f29c344d0552ebe46aae1268c55a683c37e68e"`; + +exports[`TypedDataUtils.encodeData V4 example data type "string" should encode "10" (type "number") 1`] = `"cddf41b07426e1a761f3da57e35474ae3deaa5b596306531f651c6dc1321e4fd0ef9d8f8804d174666011a394cab7901679a8944d24249fd148a6a36071151f8"`; + +exports[`TypedDataUtils.encodeData V4 example data type "string" should encode "Hello!" (type "string") 1`] = `"cddf41b07426e1a761f3da57e35474ae3deaa5b596306531f651c6dc1321e4fd6cdba77591a790691c694fa0be937f835b8a589095e427022aa1035e579ee596"`; + +exports[`TypedDataUtils.encodeData V4 example data type "string" should encode "😁" (type "string") 1`] = `"cddf41b07426e1a761f3da57e35474ae3deaa5b596306531f651c6dc1321e4fdefd5e893bdf9a51aa4d52297a64d0f7b1091407c347ca2eb8c02657e50717843"`; + +exports[`TypedDataUtils.encodeData V4 example data type "string" should encode array of all string example data 1`] = `"164981f89fce9e79b32d9ba340130ac688927a8f06271379c98ec1dc07f640c0446c3d672744ab2d474513bfe40dafcd40e9026a1a2c9d65fdd268aa5c80dc21"`; + +exports[`TypedDataUtils.encodeData V4 example data type "uint" should encode "0" (type "number") 1`] = `"8648acc768404f6d212f46260e326812d31b253b3963e2482f8bba6a0ca7fef10000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "uint" should encode "0" (type "string") 1`] = `"8648acc768404f6d212f46260e326812d31b253b3963e2482f8bba6a0ca7fef10000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "uint" should encode "0x0" (type "string") 1`] = `"8648acc768404f6d212f46260e326812d31b253b3963e2482f8bba6a0ca7fef10000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "uint" should encode "9007199254740991" (type "number") 1`] = `"8648acc768404f6d212f46260e326812d31b253b3963e2482f8bba6a0ca7fef1000000000000000000000000000000000000000000000000001fffffffffffff"`; + +exports[`TypedDataUtils.encodeData V4 example data type "uint" should encode array of all uint example data 1`] = `"f0165070b5df224705b23b1e1c0f90a919132c2ba1a147a7bc5ae3f10b07b17e466f8762ff33f5d78b80f620538cd343b1823cc87cd806412f5d280cfad3b799"`; + +exports[`TypedDataUtils.encodeData V4 example data type "uint8" should encode "0" (type "number") 1`] = `"997a0c895f7d046e9d4bcfa5de41b03f33ca7fa213cb1325edd0cad1e9c3864c0000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "uint8" should encode "0" (type "string") 1`] = `"997a0c895f7d046e9d4bcfa5de41b03f33ca7fa213cb1325edd0cad1e9c3864c0000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "uint8" should encode "0x0" (type "string") 1`] = `"997a0c895f7d046e9d4bcfa5de41b03f33ca7fa213cb1325edd0cad1e9c3864c0000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "uint8" should encode "255" (type "number") 1`] = `"997a0c895f7d046e9d4bcfa5de41b03f33ca7fa213cb1325edd0cad1e9c3864c00000000000000000000000000000000000000000000000000000000000000ff"`; + +exports[`TypedDataUtils.encodeData V4 example data type "uint8" should encode array of all uint8 example data 1`] = `"f515e568fc9efe827acaa374898c1ce18080cbf5246ed3c0498992505cf0b60b88bd1b5590273cfe86bc0567a197ff76a62140538fb65b94d501f4e8bdb93cbd"`; + +exports[`TypedDataUtils.encodeData V4 example data type "uint256" should encode "0" (type "number") 1`] = `"313eafedfe20c8366f87086b9ac5b8b0ad47b49842a8eb76a8a746dfea3ff8d10000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "uint256" should encode "0" (type "string") 1`] = `"313eafedfe20c8366f87086b9ac5b8b0ad47b49842a8eb76a8a746dfea3ff8d10000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "uint256" should encode "0x0" (type "string") 1`] = `"313eafedfe20c8366f87086b9ac5b8b0ad47b49842a8eb76a8a746dfea3ff8d10000000000000000000000000000000000000000000000000000000000000000"`; + +exports[`TypedDataUtils.encodeData V4 example data type "uint256" should encode "9007199254740991" (type "number") 1`] = `"313eafedfe20c8366f87086b9ac5b8b0ad47b49842a8eb76a8a746dfea3ff8d1000000000000000000000000000000000000000000000000001fffffffffffff"`; + +exports[`TypedDataUtils.encodeData V4 example data type "uint256" should encode array of all uint256 example data 1`] = `"cdf19ca88de01fa689a36bc72e26bca5dcb8b87b50500b28ff442503c5dff8eb466f8762ff33f5d78b80f620538cd343b1823cc87cd806412f5d280cfad3b799"`; + +exports[`TypedDataUtils.encodeData V4 should encode data when given extraneous types 1`] = `"cddf41b07426e1a761f3da57e35474ae3deaa5b596306531f651c6dc1321e4fd6cdba77591a790691c694fa0be937f835b8a589095e427022aa1035e579ee596"`; + +exports[`TypedDataUtils.encodeData V4 should encode data with a custom data type array 1`] = `"077b2e5169bfc57ed1b6acf858d27ae9b8311db1ccf71df99dfcf9efe8eec43856cacfdc07c6f697bc1bc978cf38559d5c729ed1cd1177e047df929e19dc2a2e8548546251a0cc6d0005e1a792e00f85feed5056e580102ed1afa615f87bb130b5aadf3154a261abdd9086fc627b61efca26ae5702701d05cd2305f7c52a2fc8"`; + +exports[`TypedDataUtils.encodeData V4 should encode data with a custom type property set to null 1`] = `"a0cedeb2dc280ba39b857546d74f5549c3a1d7bdc2dd96bf881f76108e23dac2fc71e5fa27ff56c350aa531bc129ebdf613b772b6604664f5d8dbe21b85eb0c80000000000000000000000000000000000000000000000000000000000000000b5aadf3154a261abdd9086fc627b61efca26ae5702701d05cd2305f7c52a2fc8"`; + +exports[`TypedDataUtils.encodeData V4 should encode data with a custom type property set to undefined 1`] = `"a0cedeb2dc280ba39b857546d74f5549c3a1d7bdc2dd96bf881f76108e23dac2fc71e5fa27ff56c350aa531bc129ebdf613b772b6604664f5d8dbe21b85eb0c80000000000000000000000000000000000000000000000000000000000000000b5aadf3154a261abdd9086fc627b61efca26ae5702701d05cd2305f7c52a2fc8"`; + +exports[`TypedDataUtils.encodeData V4 should encode data with a dynamic property set to null 1`] = `"a0cedeb2dc280ba39b857546d74f5549c3a1d7bdc2dd96bf881f76108e23dac2fc71e5fa27ff56c350aa531bc129ebdf613b772b6604664f5d8dbe21b85eb0c8cd54f074a4af31b4411ff6a60c9719dbd559c221c8ac3492d9d872b041d703d1c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"`; + +exports[`TypedDataUtils.encodeData V4 should encode data with a recursive data type 1`] = `"66658e9662034bcd21df657297dab8ba47f0ae05dd8aa253cc935d9aacfd9d10fc71e5fa27ff56c350aa531bc129ebdf613b772b6604664f5d8dbe21b85eb0c8cd54f074a4af31b4411ff6a60c9719dbd559c221c8ac3492d9d872b041d703d1b5aadf3154a261abdd9086fc627b61efca26ae5702701d05cd2305f7c52a2fc8161abe35f76debc1e0496baa54308eb1f1331218276bf01c4af34ee637780b25"`; + +exports[`TypedDataUtils.encodeData V4 should encode data with custom type 1`] = `"a0cedeb2dc280ba39b857546d74f5549c3a1d7bdc2dd96bf881f76108e23dac2fc71e5fa27ff56c350aa531bc129ebdf613b772b6604664f5d8dbe21b85eb0c8cd54f074a4af31b4411ff6a60c9719dbd559c221c8ac3492d9d872b041d703d1b5aadf3154a261abdd9086fc627b61efca26ae5702701d05cd2305f7c52a2fc8"`; diff --git a/src/index.test.ts b/src/index.test.ts index 890e016d..223af1d1 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -1,6 +1,1431 @@ import * as ethUtil from 'ethereumjs-util'; import * as sigUtil from '.'; +const encodeDataExamples = { + // dynamic types supported by EIP-712: + bytes: [10, '10', '0x10', Buffer.from('10', 'utf8')], + string: [ + 'Hello!', + '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', + '0xabcd', + '😁', + 10, + ], + // atomic types supported by EIP-712: + address: [ + '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', + '0x0', + 10, + 'bBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', + Number.MAX_SAFE_INTEGER, + ], + bool: [true, false, 'true', 'false', 0, 1, -1, Number.MAX_SAFE_INTEGER], + bytes1: [ + '0x10', + 10, + 0, + 1, + -1, + Number.MAX_SAFE_INTEGER, + Buffer.from('10', 'utf8'), + ], + bytes32: [ + '0x10', + 10, + 0, + 1, + -1, + Number.MAX_SAFE_INTEGER, + Buffer.from('10', 'utf8'), + ], + int8: [0, '0', '0x0', 255, -255], + int256: [0, '0', '0x0', Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER], + uint8: [0, '0', '0x0', 255], + uint256: [0, '0', '0x0', Number.MAX_SAFE_INTEGER], + // atomic types not supported by EIP-712: + int: [0, '0', '0x0', Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER], // interpreted as `int256` by `ethereumjs-abi` + uint: [0, '0', '0x0', Number.MAX_SAFE_INTEGER], // interpreted as `uint256` by `ethereumjs-abi` + // `fixed` and `ufixed` types omitted because their encoding in `ethereumjs-abi` is very broken at the moment. + // `function` type omitted because it is not supported by `ethereumjs-abi`. +}; + +const encodeDataErrorExamples = { + address: [ + { + input: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB0', + errorMessage: 'Supplied uint exceeds width: 160 vs 164', + }, + ], + int8: [{ input: '256', errorMessage: 'Supplied int exceeds width: 8 vs 9' }], + uint: [{ input: -1, errorMessage: 'Supplied uint is negative' }], + uint8: [{ input: -1, errorMessage: 'Supplied uint is negative' }], + uint256: [{ input: -1, errorMessage: 'Supplied uint is negative' }], + bytes1: [ + { input: 'a', errorMessage: 'Cannot convert string to buffer' }, + { input: 'test', errorMessage: 'Cannot convert string to buffer' }, + ], + bytes32: [ + { input: 'a', errorMessage: 'Cannot convert string to buffer' }, + { input: 'test', errorMessage: 'Cannot convert string to buffer' }, + ], +}; + +// Union of all types from both sets of examples +const allExampleTypes = [ + ...new Set( + Object.keys(encodeDataExamples).concat( + Object.keys(encodeDataErrorExamples), + ), + ), +]; + +describe('TypedDataUtils.encodeData', function () { + // The `TypedDataUtils.encodeData` function accepts most Solidity data types, as well as custom + // data types defined by the types provided. The supported Solidity data types are divided into + // two types: atomic and dynamic. Atomic types are of a fixed size (e.g. `int8`), whereas dynamic + // types can vary in size (e.g. strings, bytes). We also test arrays of each of these types. + // + // The tests below test all boundary conditions of each Solidity type. These tests are + // automatically constructed using the example data above ("encodeDataExamples" and + // "encodeDataErrorExamples"). The behaviour for `null` and `undefined` inputs does vary between + // atomic, dynamic, and custom types though, so each of these three categories is tested + // separately with `null` and `undefined` input. Lastly, there are more tests for various other + // edge cases. + // + // The behavior differs between V3 and V4, so each test has been run for each version. We also + // have a block of tests to verify that signatures that match between V3 and V4 remain identical, + // and that signatures that differ between V3 and V4 remain different. + // + // To make reading and maintaining these tests easier, the order will be the same throughout all + // 4 of these test suites. Here is a table showing that order, as well as the compatibility of + // each input type with V3 and V4 `encodeData`. The table also shows whether the signature is + // identical between versions in the cases where the input can be encoded in both versions. + // + // | Input type | V3 | V4 | Matching Signatures | + // | ---------------------------------------------------- | -- | -- | ------------------- | + // | Auto-generated tests from the example data | Y | Y | Y | + // | Arrays using the example data | N | Y | | + // | Custom type | Y | Y | Y | + // | Recursive custom type | Y | Y | N | + // | Custom type array | N | Y | | + // | Custom type with extra properties | Y | Y | Y | + // | Atomic type with `null` input | N | N | | + // | Atomic type with `undefined` input | Y | N | | + // | Dynamic type with `null` input | Y | Y | Y | + // | Dynamic type with `undefined` input | Y | N | | + // | Custom type with `null` input | N | Y | | + // | Custom type with `undefined` input | Y | Y | N | + // | Functions | N | N | | + // | Unrecognized primary type | N | N | | + // | Unrecognized non-primary type | N | N | | + // | Extra type specified that isn't used by primary type | Y | Y | Y | + + describe('V3', function () { + describe('example data', function () { + // Reassigned to silence "no-loop-func" ESLint rule + // It was complaining because it saw that `it` and `expect` as "modified variables from the outer scope" + // which can be dangerous to reference in a loop. But they aren't modified in this case, just invoked. + const _expect = expect; + const _it = it; + + for (const type of allExampleTypes) { + describe(`type "${type}"`, function () { + // Test all examples that do not crash + const inputs = encodeDataExamples[type] || []; + for (const input of inputs) { + const inputType = input instanceof Buffer ? 'Buffer' : typeof input; + _it(`should encode "${input}" (type "${inputType}")`, function () { + const types = { + Message: [{ name: 'data', type }], + }; + const message = { data: input }; + + _expect( + sigUtil.TypedDataUtils.encodeData( + 'Message', + message, + types, + 'V3', + ).toString('hex'), + ).toMatchSnapshot(); + }); + } + + // Test all examples that crash + const errorInputs = encodeDataErrorExamples[type] || []; + for (const { input, errorMessage } of errorInputs) { + const inputType = input instanceof Buffer ? 'Buffer' : typeof input; + _it( + `should fail to encode "${input}" (type "${inputType}")`, + function () { + const types = { + Message: [{ name: 'data', type }], + }; + const message = { data: input }; + + _expect(() => + sigUtil.TypedDataUtils.encodeData( + 'Message', + message, + types, + 'V3', + ).toString('hex'), + ).toThrow(errorMessage); + }, + ); + } + + _it( + `should fail to encode array of all ${type} example data`, + function () { + const types = { + Message: [{ name: 'data', type: `${type}[]` }], + }; + const message = { data: inputs }; + _expect(() => + sigUtil.TypedDataUtils.encodeData( + 'Message', + message, + types, + 'V3', + ).toString('hex'), + ).toThrow( + 'Arrays are unimplemented in encodeData; use V4 extension', + ); + }, + ); + }); + } + }); + + it('should encode data with custom type', function () { + const types = { + Person: [ + { name: 'name', type: 'string' }, + { name: 'wallet', type: 'address' }, + ], + Mail: [ + { name: 'from', type: 'Person' }, + { name: 'to', type: 'Person' }, + { name: 'contents', type: 'string' }, + ], + }; + const primaryType = 'Mail'; + const message = { + from: { + name: 'Cow', + wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', + }, + to: { + name: 'Bob', + wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', + }, + contents: 'Hello, Bob!', + }; + + expect( + sigUtil.TypedDataUtils.encodeData( + primaryType, + message, + types, + 'V3', + ).toString('hex'), + ).toMatchSnapshot(); + }); + + it('should encode data with a recursive data type', function () { + const types = { + Person: [ + { name: 'name', type: 'string' }, + { name: 'wallet', type: 'address' }, + ], + Mail: [ + { name: 'from', type: 'Person' }, + { name: 'to', type: 'Person' }, + { name: 'contents', type: 'string' }, + { name: 'replyTo', type: 'Mail' }, + ], + }; + const primaryType = 'Mail'; + const message = { + from: { + name: 'Cow', + wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', + }, + to: { + name: 'Bob', + wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', + }, + contents: 'Hello, Bob!', + replyTo: { + to: { + name: 'Cow', + wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', + }, + from: { + name: 'Bob', + wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', + }, + contents: 'Hello!', + }, + }; + + expect( + sigUtil.TypedDataUtils.encodeData( + primaryType, + message, + types, + 'V3', + ).toString('hex'), + ).toMatchSnapshot(); + }); + + it('should throw an error when trying to encode a custom type array', function () { + const types = { + Message: [{ name: 'data', type: 'string[]' }], + }; + const message = { data: ['1', '2', '3'] }; + + expect(() => + sigUtil.TypedDataUtils.encodeData( + 'Message', + message, + types, + 'V3', + ).toString('hex'), + ).toThrow('Arrays are unimplemented in encodeData; use V4 extension'); + }); + + it('should ignore extra unspecified message properties', function () { + const types = { + Person: [ + { name: 'name', type: 'string' }, + { name: 'wallet', type: 'address' }, + ], + Mail: [ + { name: 'from', type: 'Person' }, + { name: 'to', type: 'Person' }, + { name: 'contents', type: 'string' }, + ], + }; + const primaryType = 'Mail'; + const message = { + from: { + name: 'Cow', + wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', + }, + to: { + name: 'Bob', + wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', + }, + contents: 'Hello, Bob!', + }; + + const originalSignature = sigUtil.TypedDataUtils.encodeData( + primaryType, + message, + types, + 'V3', + ).toString('hex'); + const messageWithExtraProperties = { ...message, foo: 'bar' }; + const signatureWithExtraProperties = sigUtil.TypedDataUtils.encodeData( + primaryType, + messageWithExtraProperties, + types, + 'V3', + ).toString('hex'); + + expect(originalSignature).toBe(signatureWithExtraProperties); + }); + + it('should throw an error when an atomic property is set to null', function () { + const types = { + Person: [ + { name: 'name', type: 'string' }, + { name: 'wallet', type: 'address' }, + ], + Mail: [ + { name: 'from', type: 'Person' }, + { name: 'to', type: 'Person' }, + { name: 'contents', type: 'string' }, + { name: 'length', type: 'int32' }, + ], + }; + const primaryType = 'Mail'; + const message = { + from: { + name: 'Cow', + wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', + }, + to: { + name: 'Bob', + wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', + }, + contents: 'Hello!', + length: null, + }; + + expect(() => + sigUtil.TypedDataUtils.encodeData( + primaryType, + message, + types, + 'V3', + ).toString('hex'), + ).toThrow(`Cannot read property 'toArray' of null`); + }); + + it('should encode data with an atomic property set to undefined', function () { + const types = { + Person: [ + { name: 'name', type: 'string' }, + { name: 'wallet', type: 'address' }, + ], + Mail: [ + { name: 'from', type: 'Person' }, + { name: 'to', type: 'Person' }, + { name: 'contents', type: 'string' }, + { name: 'length', type: 'int32' }, + ], + }; + const primaryType = 'Mail'; + const message = { + from: { + name: 'Cow', + wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', + }, + to: { + name: 'Bob', + wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', + }, + contents: 'Hello!', + length: undefined, + }; + + expect( + sigUtil.TypedDataUtils.encodeData( + primaryType, + message, + types, + 'V3', + ).toString('hex'), + ).toMatchSnapshot(); + }); + + it('should encode data with a dynamic property set to null', function () { + const types = { + Person: [ + { name: 'name', type: 'string' }, + { name: 'wallet', type: 'address' }, + ], + Mail: [ + { name: 'from', type: 'Person' }, + { name: 'to', type: 'Person' }, + { name: 'contents', type: 'string' }, + ], + }; + const primaryType = 'Mail'; + const message = { + from: { + name: 'Cow', + wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', + }, + to: { + name: 'Bob', + wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', + }, + contents: null, + }; + + expect( + sigUtil.TypedDataUtils.encodeData( + primaryType, + message, + types, + 'V3', + ).toString('hex'), + ).toMatchSnapshot(); + }); + + it('should encode data with a dynamic property set to undefined', function () { + const types = { + Person: [ + { name: 'name', type: 'string' }, + { name: 'wallet', type: 'address' }, + ], + Mail: [ + { name: 'from', type: 'Person' }, + { name: 'to', type: 'Person' }, + { name: 'contents', type: 'string' }, + ], + }; + const primaryType = 'Mail'; + const message = { + from: { + name: 'Cow', + wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', + }, + to: { + name: 'Bob', + wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', + }, + contents: undefined, + }; + + expect( + sigUtil.TypedDataUtils.encodeData( + primaryType, + message, + types, + 'V3', + ).toString('hex'), + ).toMatchSnapshot(); + }); + + it('should throw an error when a custom type property is set to null', function () { + const types = { + Person: [ + { name: 'name', type: 'string' }, + { name: 'wallet', type: 'address' }, + ], + Mail: [ + { name: 'from', type: 'Person' }, + { name: 'to', type: 'Person' }, + { name: 'contents', type: 'string' }, + ], + }; + const primaryType = 'Mail'; + const message = { + to: null, + from: { + name: 'Cow', + wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', + }, + contents: 'Hello, Bob!', + }; + + expect(() => + sigUtil.TypedDataUtils.encodeData( + primaryType, + message, + types, + 'V3', + ).toString('hex'), + ).toThrow(`Cannot read property 'name' of null`); + }); + + it('should encode data with a custom type property set to undefined', function () { + const types = { + Person: [ + { name: 'name', type: 'string' }, + { name: 'wallet', type: 'address' }, + ], + Mail: [ + { name: 'from', type: 'Person' }, + { name: 'to', type: 'Person' }, + { name: 'contents', type: 'string' }, + ], + }; + const primaryType = 'Mail'; + const message = { + from: { + name: 'Cow', + wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', + }, + contents: 'Hello, Bob!', + }; + + expect( + sigUtil.TypedDataUtils.encodeData( + primaryType, + message, + types, + 'V3', + ).toString('hex'), + ).toMatchSnapshot(); + }); + + it('should throw an error when trying to encode a function', function () { + const types = { + Message: [{ name: 'data', type: 'function' }], + }; + const message = { data: 'test' }; + + expect(() => + sigUtil.TypedDataUtils.encodeData( + 'Message', + message, + types, + 'V3', + ).toString('hex'), + ).toThrow('Unsupported or invalid type: function'); + }); + + it('should throw an error when trying to encode with a missing primary type definition', function () { + const types = {}; + const message = { data: 'test' }; + + expect(() => + sigUtil.TypedDataUtils.encodeData( + 'Message', + message, + types, + 'V3', + ).toString('hex'), + ).toThrow('No type definition specified: Message'); + }); + + it('should throw an error when trying to encode an unrecognized type', function () { + const types = { + Message: [{ name: 'data', type: 'foo' }], + }; + const message = { data: 'test' }; + + expect(() => + sigUtil.TypedDataUtils.encodeData( + 'Message', + message, + types, + 'V3', + ).toString('hex'), + ).toThrow('Unsupported or invalid type: foo'); + }); + + it('should encode data when given extraneous types', function () { + const types = { + Message: [{ name: 'data', type: 'string' }], + Extra: [{ name: 'data', type: 'string' }], + }; + const message = { data: 'Hello!' }; + + expect( + sigUtil.TypedDataUtils.encodeData( + 'Message', + message, + types, + 'V3', + ).toString('hex'), + ).toMatchSnapshot(); + }); + }); + + // This test suite should include all expected V4 behavior except the example + // data encoding, whcih is covered in the "V3/V4 encoding similarities" test + // suite + describe('V4', function () { + describe('example data', function () { + // Reassigned to silence "no-loop-func" ESLint rule + // It was complaining because it saw that `it` and `expect` as "modified variables from the outer scope" + // which can be dangerous to reference in a loop. But they aren't modified in this case, just invoked. + const _expect = expect; + const _it = it; + + for (const type of allExampleTypes) { + describe(`type "${type}"`, function () { + // Test all examples that do not crash + const inputs = encodeDataExamples[type] || []; + for (const input of inputs) { + const inputType = input instanceof Buffer ? 'Buffer' : typeof input; + _it(`should encode "${input}" (type "${inputType}")`, function () { + const types = { + Message: [{ name: 'data', type }], + }; + const message = { data: input }; + + _expect( + sigUtil.TypedDataUtils.encodeData( + 'Message', + message, + types, + 'V4', + ).toString('hex'), + ).toMatchSnapshot(); + }); + } + + // Test all examples that crash + const errorInputs = encodeDataErrorExamples[type] || []; + for (const { input, errorMessage } of errorInputs) { + const inputType = input instanceof Buffer ? 'Buffer' : typeof input; + _it( + `should fail to encode "${input}" (type "${inputType}")`, + function () { + const types = { + Message: [{ name: 'data', type }], + }; + const message = { data: input }; + + _expect(() => + sigUtil.TypedDataUtils.encodeData( + 'Message', + message, + types, + 'V4', + ).toString('hex'), + ).toThrow(errorMessage); + }, + ); + } + + _it(`should encode array of all ${type} example data`, function () { + const types = { + Message: [{ name: 'data', type: `${type}[]` }], + }; + const message = { data: inputs }; + _expect( + sigUtil.TypedDataUtils.encodeData( + 'Message', + message, + types, + 'V4', + ).toString('hex'), + ).toMatchSnapshot(); + }); + }); + } + }); + + it('should encode data with custom type', function () { + const types = { + Person: [ + { name: 'name', type: 'string' }, + { name: 'wallet', type: 'address' }, + ], + Mail: [ + { name: 'from', type: 'Person' }, + { name: 'to', type: 'Person' }, + { name: 'contents', type: 'string' }, + ], + }; + const primaryType = 'Mail'; + const message = { + from: { + name: 'Cow', + wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', + }, + to: { + name: 'Bob', + wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', + }, + contents: 'Hello, Bob!', + }; + + expect( + sigUtil.TypedDataUtils.encodeData( + primaryType, + message, + types, + 'V4', + ).toString('hex'), + ).toMatchSnapshot(); + }); + + it('should encode data with a recursive data type', function () { + const types = { + Person: [ + { name: 'name', type: 'string' }, + { name: 'wallet', type: 'address' }, + ], + Mail: [ + { name: 'from', type: 'Person' }, + { name: 'to', type: 'Person' }, + { name: 'contents', type: 'string' }, + { name: 'replyTo', type: 'Mail' }, + ], + }; + const primaryType = 'Mail'; + const message = { + from: { + name: 'Cow', + wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', + }, + to: { + name: 'Bob', + wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', + }, + contents: 'Hello, Bob!', + replyTo: { + to: { + name: 'Cow', + wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', + }, + from: { + name: 'Bob', + wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', + }, + contents: 'Hello!', + }, + }; + + expect( + sigUtil.TypedDataUtils.encodeData( + primaryType, + message, + types, + 'V4', + ).toString('hex'), + ).toMatchSnapshot(); + }); + + it('should encode data with a custom data type array', function () { + const types = { + Person: [ + { name: 'name', type: 'string' }, + { name: 'wallet', type: 'address[]' }, + ], + Mail: [ + { name: 'from', type: 'Person' }, + { name: 'to', type: 'Person[]' }, + { name: 'contents', type: 'string' }, + ], + }; + const primaryType = 'Mail'; + const message = { + from: { + name: 'Cow', + wallet: [ + '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', + '0xDD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', + ], + }, + to: [ + { + name: 'Bob', + wallet: ['0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB'], + }, + ], + contents: 'Hello, Bob!', + }; + + expect( + sigUtil.TypedDataUtils.encodeData( + primaryType, + message, + types, + 'V4', + ).toString('hex'), + ).toMatchSnapshot(); + }); + + it('should ignore extra unspecified message properties', function () { + const types = { + Person: [ + { name: 'name', type: 'string' }, + { name: 'wallet', type: 'address' }, + ], + Mail: [ + { name: 'from', type: 'Person' }, + { name: 'to', type: 'Person' }, + { name: 'contents', type: 'string' }, + ], + }; + const primaryType = 'Mail'; + const message = { + from: { + name: 'Cow', + wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', + }, + to: { + name: 'Bob', + wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', + }, + contents: 'Hello, Bob!', + }; + + const originalSignature = sigUtil.TypedDataUtils.encodeData( + primaryType, + message, + types, + 'V4', + ).toString('hex'); + const messageWithExtraProperties = { ...message, foo: 'bar' }; + const signatureWithExtraProperties = sigUtil.TypedDataUtils.encodeData( + primaryType, + messageWithExtraProperties, + types, + 'V4', + ).toString('hex'); + + expect(originalSignature).toBe(signatureWithExtraProperties); + }); + + it('should throw an error when an atomic property is set to null', function () { + const types = { + Person: [ + { name: 'name', type: 'string' }, + { name: 'wallet', type: 'address' }, + ], + Mail: [ + { name: 'from', type: 'Person' }, + { name: 'to', type: 'Person' }, + { name: 'contents', type: 'string' }, + { name: 'length', type: 'int32' }, + ], + }; + const primaryType = 'Mail'; + const message = { + from: { + name: 'Cow', + wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', + }, + to: { + name: 'Bob', + wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', + }, + contents: 'Hello!', + length: null, + }; + + expect(() => + sigUtil.TypedDataUtils.encodeData( + primaryType, + message, + types, + 'V4', + ).toString('hex'), + ).toThrow(`Cannot read property 'toArray' of null`); + }); + + it('should throw an error when an atomic property is set to undefined', function () { + const types = { + Person: [ + { name: 'name', type: 'string' }, + { name: 'wallet', type: 'address' }, + ], + Mail: [ + { name: 'from', type: 'Person' }, + { name: 'to', type: 'Person' }, + { name: 'contents', type: 'string' }, + { name: 'length', type: 'int32' }, + ], + }; + const primaryType = 'Mail'; + const message = { + from: { + name: 'Cow', + wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', + }, + to: { + name: 'Bob', + wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', + }, + contents: 'Hello!', + length: undefined, + }; + + expect(() => + sigUtil.TypedDataUtils.encodeData( + primaryType, + message, + types, + 'V4', + ).toString('hex'), + ).toThrow('missing value for field length of type int32'); + }); + + it('should encode data with a dynamic property set to null', function () { + const types = { + Person: [ + { name: 'name', type: 'string' }, + { name: 'wallet', type: 'address' }, + ], + Mail: [ + { name: 'from', type: 'Person' }, + { name: 'to', type: 'Person' }, + { name: 'contents', type: 'string' }, + ], + }; + const primaryType = 'Mail'; + const message = { + from: { + name: 'Cow', + wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', + }, + to: { + name: 'Bob', + wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', + }, + contents: null, + }; + + expect( + sigUtil.TypedDataUtils.encodeData( + primaryType, + message, + types, + 'V4', + ).toString('hex'), + ).toMatchSnapshot(); + }); + + it('should throw an error when a dynamic property is set to undefined', function () { + const types = { + Person: [ + { name: 'name', type: 'string' }, + { name: 'wallet', type: 'address' }, + ], + Mail: [ + { name: 'from', type: 'Person' }, + { name: 'to', type: 'Person' }, + { name: 'contents', type: 'string' }, + ], + }; + const primaryType = 'Mail'; + const message = { + from: { + name: 'Cow', + wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', + }, + to: { + name: 'Bob', + wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', + }, + contents: undefined, + }; + + expect(() => + sigUtil.TypedDataUtils.encodeData( + primaryType, + message, + types, + 'V4', + ).toString('hex'), + ).toThrow('missing value for field contents of type string'); + }); + + it('should encode data with a custom type property set to null', function () { + const types = { + Person: [ + { name: 'name', type: 'string' }, + { name: 'wallet', type: 'address' }, + ], + Mail: [ + { name: 'from', type: 'Person' }, + { name: 'to', type: 'Person' }, + { name: 'contents', type: 'string' }, + ], + }; + const primaryType = 'Mail'; + const message = { + to: null, + from: { + name: 'Cow', + wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', + }, + contents: 'Hello, Bob!', + }; + + expect( + sigUtil.TypedDataUtils.encodeData( + primaryType, + message, + types, + 'V4', + ).toString('hex'), + ).toMatchSnapshot(); + }); + + it('should encode data with a custom type property set to undefined', function () { + const types = { + Person: [ + { name: 'name', type: 'string' }, + { name: 'wallet', type: 'address' }, + ], + Mail: [ + { name: 'from', type: 'Person' }, + { name: 'to', type: 'Person' }, + { name: 'contents', type: 'string' }, + ], + }; + const primaryType = 'Mail'; + const message = { + from: { + name: 'Cow', + wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', + }, + contents: 'Hello, Bob!', + }; + + expect( + sigUtil.TypedDataUtils.encodeData( + primaryType, + message, + types, + 'V4', + ).toString('hex'), + ).toMatchSnapshot(); + }); + + it('should throw an error when trying to encode a function', function () { + const types = { + Message: [{ name: 'data', type: 'function' }], + }; + const message = { data: 'test' }; + + expect(() => + sigUtil.TypedDataUtils.encodeData( + 'Message', + message, + types, + 'V4', + ).toString('hex'), + ).toThrow('Unsupported or invalid type: function'); + }); + + it('should throw an error when trying to encode with a missing primary type definition', function () { + const types = {}; + const message = { data: 'test' }; + + expect(() => + sigUtil.TypedDataUtils.encodeData( + 'Message', + message, + types, + 'V4', + ).toString('hex'), + ).toThrow('No type definition specified: Message'); + }); + + it('should throw an error when trying to encode an unrecognized type', function () { + const types = { + Message: [{ name: 'data', type: 'foo' }], + }; + const message = { data: 'test' }; + + expect(() => + sigUtil.TypedDataUtils.encodeData( + 'Message', + message, + types, + 'V4', + ).toString('hex'), + ).toThrow('Unsupported or invalid type: foo'); + }); + + it('should encode data when given extraneous types', function () { + const types = { + Message: [{ name: 'data', type: 'string' }], + Extra: [{ name: 'data', type: 'string' }], + }; + const message = { data: 'Hello!' }; + + expect( + sigUtil.TypedDataUtils.encodeData( + 'Message', + message, + types, + 'V4', + ).toString('hex'), + ).toMatchSnapshot(); + }); + }); + + // This test suite covers all cases where data should be encoded identically + // on V3 and V4 + describe('V3/V4 identical encodings', function () { + describe('example data', function () { + // Reassigned to silence "no-loop-func" ESLint rule + // It was complaining because it saw that `it` and `expect` as "modified variables from the outer scope" + // which can be dangerous to reference in a loop. But they aren't modified in this case, just invoked. + const _expect = expect; + const _it = it; + + for (const type of allExampleTypes) { + describe(`type "${type}"`, function () { + // Test all examples that do not crash + const inputs = encodeDataExamples[type] || []; + for (const input of inputs) { + const inputType = input instanceof Buffer ? 'Buffer' : typeof input; + _it(`should encode "${input}" (type "${inputType}")`, function () { + const types = { + Message: [{ name: 'data', type }], + }; + const message = { data: input }; + + const v3Signature = sigUtil.TypedDataUtils.encodeData( + 'Message', + message, + types, + 'V3', + ).toString('hex'); + const v4Signature = sigUtil.TypedDataUtils.encodeData( + 'Message', + message, + types, + 'V4', + ).toString('hex'); + + _expect(v3Signature).toBe(v4Signature); + }); + } + }); + } + }); + + it('should encode data with custom type', function () { + const types = { + Person: [ + { name: 'name', type: 'string' }, + { name: 'wallet', type: 'address' }, + ], + Mail: [ + { name: 'from', type: 'Person' }, + { name: 'to', type: 'Person' }, + { name: 'contents', type: 'string' }, + ], + }; + const primaryType = 'Mail'; + const message = { + from: { + name: 'Cow', + wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', + }, + to: { + name: 'Bob', + wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', + }, + contents: 'Hello, Bob!', + }; + + const v3Signature = sigUtil.TypedDataUtils.encodeData( + primaryType, + message, + types, + 'V3', + ).toString('hex'); + const v4Signature = sigUtil.TypedDataUtils.encodeData( + primaryType, + message, + types, + 'V4', + ).toString('hex'); + + expect(v3Signature).toBe(v4Signature); + }); + + it('should ignore extra unspecified message properties', function () { + const types = { + Person: [ + { name: 'name', type: 'string' }, + { name: 'wallet', type: 'address' }, + ], + Mail: [ + { name: 'from', type: 'Person' }, + { name: 'to', type: 'Person' }, + { name: 'contents', type: 'string' }, + ], + }; + const primaryType = 'Mail'; + const message = { + from: { + name: 'Cow', + wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', + }, + to: { + name: 'Bob', + wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', + }, + contents: 'Hello, Bob!', + }; + + const originalV3Signature = sigUtil.TypedDataUtils.encodeData( + primaryType, + message, + types, + 'V3', + ).toString('hex'); + const originalV4Signature = sigUtil.TypedDataUtils.encodeData( + primaryType, + message, + types, + 'V4', + ).toString('hex'); + const messageWithExtraProperties = { ...message, foo: 'bar' }; + const v3signatureWithExtraProperties = sigUtil.TypedDataUtils.encodeData( + primaryType, + messageWithExtraProperties, + types, + 'V3', + ).toString('hex'); + const v4signatureWithExtraProperties = sigUtil.TypedDataUtils.encodeData( + primaryType, + messageWithExtraProperties, + types, + 'V4', + ).toString('hex'); + + expect(originalV3Signature).toBe(originalV4Signature); + expect(v3signatureWithExtraProperties).toBe( + v4signatureWithExtraProperties, + ); + }); + + it('should encode data with a dynamic property set to null', function () { + const types = { + Person: [ + { name: 'name', type: 'string' }, + { name: 'wallet', type: 'address' }, + ], + Mail: [ + { name: 'from', type: 'Person' }, + { name: 'to', type: 'Person' }, + { name: 'contents', type: 'string' }, + ], + }; + const primaryType = 'Mail'; + const message = { + from: { + name: 'Cow', + wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', + }, + to: { + name: 'Bob', + wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', + }, + contents: null, + }; + + const v3Signature = sigUtil.TypedDataUtils.encodeData( + primaryType, + message, + types, + 'V3', + ).toString('hex'); + const v4Signature = sigUtil.TypedDataUtils.encodeData( + primaryType, + message, + types, + 'V4', + ).toString('hex'); + + expect(v3Signature).toBe(v4Signature); + }); + + it('should encode data when given extraneous types', function () { + const types = { + Message: [{ name: 'data', type: 'string' }], + Extra: [{ name: 'data', type: 'string' }], + }; + const message = { data: 'Hello!' }; + + const v3Signature = sigUtil.TypedDataUtils.encodeData( + 'Message', + message, + types, + 'V3', + ).toString('hex'); + const v4Signature = sigUtil.TypedDataUtils.encodeData( + 'Message', + message, + types, + 'V4', + ).toString('hex'); + + expect(v3Signature).toBe(v4Signature); + }); + }); + + // This test suite covers all cases where data should be encoded differently + // on V3 and V4 + describe('V3/V4 encoding differences', () => { + // Recursive data structures are encoded differently because V4 encodes + // missing custom typed properties as 0 byte32 rather than omitting it, + // and all recursive data structures must include a missing custom typed + // property (the recursive one), or they'd be infinitely large or cyclic. + // And cyclic data structures are not supported. + it('should encode data with recursive data differently', function () { + const types = { + Person: [ + { name: 'name', type: 'string' }, + { name: 'wallet', type: 'address' }, + ], + Mail: [ + { name: 'from', type: 'Person' }, + { name: 'to', type: 'Person' }, + { name: 'contents', type: 'string' }, + { name: 'replyTo', type: 'Mail' }, + ], + }; + const primaryType = 'Mail'; + const message = { + from: { + name: 'Cow', + wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', + }, + to: { + name: 'Bob', + wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', + }, + contents: 'Hello, Bob!', + replyTo: { + to: { + name: 'Cow', + wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', + }, + from: { + name: 'Bob', + wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', + }, + contents: 'Hello!', + }, + }; + + const v3Signature = sigUtil.TypedDataUtils.encodeData( + primaryType, + message, + types, + 'V3', + ).toString('hex'); + const v4Signature = sigUtil.TypedDataUtils.encodeData( + primaryType, + message, + types, + 'V4', + ).toString('hex'); + + expect(v3Signature).not.toBe(v4Signature); + }); + + // Missing custom type properties are omitted in V3, but encoded as 0 (bytes32) in V4 + it('should encode missing custom type properties differently', function () { + const types = { + Person: [ + { name: 'name', type: 'string' }, + { name: 'wallet', type: 'address' }, + ], + Mail: [ + { name: 'from', type: 'Person' }, + { name: 'to', type: 'Person' }, + { name: 'contents', type: 'string' }, + ], + }; + const primaryType = 'Mail'; + const message = { + from: { + name: 'Cow', + wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', + }, + contents: 'Hello, Bob!', + }; + + const v3Signature = sigUtil.TypedDataUtils.encodeData( + primaryType, + message, + types, + 'V3', + ).toString('hex'); + const v4Signature = sigUtil.TypedDataUtils.encodeData( + primaryType, + message, + types, + 'V4', + ).toString('hex'); + + expect(v3Signature).not.toBe(v4Signature); + }); + }); +}); + it('normalize address lower cases', function () { const initial = '0xA06599BD35921CfB5B71B4BE3869740385b0B306'; const result = sigUtil.normalize(initial); @@ -474,18 +1899,6 @@ it('signedTypeData', function () { expect(ethUtil.bufferToHex(utils.hashType('Mail', typedData.types))).toBe( '0xa0cedeb2dc280ba39b857546d74f5549c3a1d7bdc2dd96bf881f76108e23dac2', ); - expect( - ethUtil.bufferToHex( - utils.encodeData( - typedData.primaryType, - typedData.message, - typedData.types, - 'V3', - ), - ), - ).toBe( - '0xa0cedeb2dc280ba39b857546d74f5549c3a1d7bdc2dd96bf881f76108e23dac2fc71e5fa27ff56c350aa531bc129ebdf613b772b6604664f5d8dbe21b85eb0c8cd54f074a4af31b4411ff6a60c9719dbd559c221c8ac3492d9d872b041d703d1b5aadf3154a261abdd9086fc627b61efca26ae5702701d05cd2305f7c52a2fc8', - ); expect( ethUtil.bufferToHex( utils.hashStruct( @@ -568,18 +1981,6 @@ it('signedTypeData with bytes', function () { expect( ethUtil.bufferToHex(utils.hashType('Mail', typedDataWithBytes.types)), ).toBe('0x43999c52db673245777eb64b0330105de064e52179581a340a9856c32372528e'); - expect( - ethUtil.bufferToHex( - utils.encodeData( - typedDataWithBytes.primaryType, - typedDataWithBytes.message, - typedDataWithBytes.types, - 'V3', - ), - ), - ).toBe( - '0x43999c52db673245777eb64b0330105de064e52179581a340a9856c32372528efc71e5fa27ff56c350aa531bc129ebdf613b772b6604664f5d8dbe21b85eb0c8cd54f074a4af31b4411ff6a60c9719dbd559c221c8ac3492d9d872b041d703d1b5aadf3154a261abdd9086fc627b61efca26ae5702701d05cd2305f7c52a2fc8fac776d21ae071a32c362d4c20ba6586779708a56cad3a78d01b37ecb5744298', - ); expect( ethUtil.bufferToHex( utils.hashStruct( @@ -676,39 +2077,12 @@ it('signedTypeData_v4', function () { '0xfabfe1ed996349fc6027709802be19d047da1aa5d6894ff5f6486d92db2e6860', ); - expect( - ethUtil.bufferToHex( - utils.encodeData('Person', typedData.message.from, typedData.types, 'V4'), - ), - ).toBe( - `0x${[ - 'fabfe1ed996349fc6027709802be19d047da1aa5d6894ff5f6486d92db2e6860', - '8c1d2bd5348394761719da11ec67eedae9502d137e8940fee8ecd6f641ee1648', - '8a8bfe642b9fc19c25ada5dadfd37487461dc81dd4b0778f262c163ed81b5e2a', - ].join('')}`, - ); expect( ethUtil.bufferToHex( utils.hashStruct('Person', typedData.message.from, typedData.types, 'V4'), ), ).toBe('0x9b4846dd48b866f0ac54d61b9b21a9e746f921cefa4ee94c4c0a1c49c774f67f'); - expect( - ethUtil.bufferToHex( - utils.encodeData( - 'Person', - typedData.message.to[0], - typedData.types, - 'V4', - ), - ), - ).toBe( - `0x${[ - 'fabfe1ed996349fc6027709802be19d047da1aa5d6894ff5f6486d92db2e6860', - '28cac318a86c8a0a6a9156c2dba2c8c2363677ba0514ef616592d81557e679b6', - 'd2734f4c86cc3bd9cabf04c3097589d3165d95e4648fc72d943ed161f651ec6d', - ].join('')}`, - ); expect( ethUtil.bufferToHex( utils.hashStruct( @@ -726,23 +2100,6 @@ it('signedTypeData_v4', function () { expect(ethUtil.bufferToHex(utils.hashType('Mail', typedData.types))).toBe( '0x4bd8a9a2b93427bb184aca81e24beb30ffa3c747e2a33d4225ec08bf12e2e753', ); - expect( - ethUtil.bufferToHex( - utils.encodeData( - typedData.primaryType, - typedData.message, - typedData.types, - 'V4', - ), - ), - ).toBe( - `0x${[ - '4bd8a9a2b93427bb184aca81e24beb30ffa3c747e2a33d4225ec08bf12e2e753', - '9b4846dd48b866f0ac54d61b9b21a9e746f921cefa4ee94c4c0a1c49c774f67f', - 'ca322beec85be24e374d18d582a6f2997f75c54e7993ab5bc07404ce176ca7cd', - 'b5aadf3154a261abdd9086fc627b61efca26ae5702701d05cd2305f7c52a2fc8', - ].join('')}`, - ); expect( ethUtil.bufferToHex( utils.hashStruct( @@ -841,39 +2198,12 @@ it('signedTypeData_v4', function () { '0xfabfe1ed996349fc6027709802be19d047da1aa5d6894ff5f6486d92db2e6860', ); - expect( - ethUtil.bufferToHex( - utils.encodeData('Person', typedData.message.from, typedData.types, 'V4'), - ), - ).toBe( - `0x${[ - 'fabfe1ed996349fc6027709802be19d047da1aa5d6894ff5f6486d92db2e6860', - '8c1d2bd5348394761719da11ec67eedae9502d137e8940fee8ecd6f641ee1648', - '8a8bfe642b9fc19c25ada5dadfd37487461dc81dd4b0778f262c163ed81b5e2a', - ].join('')}`, - ); expect( ethUtil.bufferToHex( utils.hashStruct('Person', typedData.message.from, typedData.types, 'V4'), ), ).toBe('0x9b4846dd48b866f0ac54d61b9b21a9e746f921cefa4ee94c4c0a1c49c774f67f'); - expect( - ethUtil.bufferToHex( - utils.encodeData( - 'Person', - typedData.message.to[0], - typedData.types, - 'V4', - ), - ), - ).toBe( - `0x${[ - 'fabfe1ed996349fc6027709802be19d047da1aa5d6894ff5f6486d92db2e6860', - '28cac318a86c8a0a6a9156c2dba2c8c2363677ba0514ef616592d81557e679b6', - 'd2734f4c86cc3bd9cabf04c3097589d3165d95e4648fc72d943ed161f651ec6d', - ].join('')}`, - ); expect( ethUtil.bufferToHex( utils.hashStruct( @@ -891,23 +2221,6 @@ it('signedTypeData_v4', function () { expect(ethUtil.bufferToHex(utils.hashType('Mail', typedData.types))).toBe( '0x4bd8a9a2b93427bb184aca81e24beb30ffa3c747e2a33d4225ec08bf12e2e753', ); - expect( - ethUtil.bufferToHex( - utils.encodeData( - typedData.primaryType, - typedData.message, - typedData.types, - 'V4', - ), - ), - ).toBe( - `0x${[ - '4bd8a9a2b93427bb184aca81e24beb30ffa3c747e2a33d4225ec08bf12e2e753', - '9b4846dd48b866f0ac54d61b9b21a9e746f921cefa4ee94c4c0a1c49c774f67f', - 'ca322beec85be24e374d18d582a6f2997f75c54e7993ab5bc07404ce176ca7cd', - 'b5aadf3154a261abdd9086fc627b61efca26ae5702701d05cd2305f7c52a2fc8', - ].join('')}`, - ); expect( ethUtil.bufferToHex( utils.hashStruct( @@ -990,23 +2303,6 @@ it('signedTypeData_v4 with recursive types', function () { '0x7c5c8e90cb92c8da53b893b24962513be98afcf1b57b00327ae4cc14e3a64116', ); - expect( - ethUtil.bufferToHex( - utils.encodeData( - 'Person', - typedData.message.mother, - typedData.types, - 'V4', - ), - ), - ).toBe( - `0x${[ - '7c5c8e90cb92c8da53b893b24962513be98afcf1b57b00327ae4cc14e3a64116', - 'afe4142a2b3e7b0503b44951e6030e0e2c5000ef83c61857e2e6003e7aef8570', - '0000000000000000000000000000000000000000000000000000000000000000', - '88f14be0dd46a8ec608ccbff6d3923a8b4e95cdfc9648f0db6d92a99a264cb36', - ].join('')}`, - ); expect( ethUtil.bufferToHex( utils.hashStruct( @@ -1018,23 +2314,6 @@ it('signedTypeData_v4 with recursive types', function () { ), ).toBe('0x9ebcfbf94f349de50bcb1e3aa4f1eb38824457c99914fefda27dcf9f99f6178b'); - expect( - ethUtil.bufferToHex( - utils.encodeData( - 'Person', - typedData.message.father, - typedData.types, - 'V4', - ), - ), - ).toBe( - `0x${[ - '7c5c8e90cb92c8da53b893b24962513be98afcf1b57b00327ae4cc14e3a64116', - 'b2a7c7faba769181e578a391a6a6811a3e84080c6a3770a0bf8a856dfa79d333', - '0000000000000000000000000000000000000000000000000000000000000000', - '02cc7460f2c9ff107904cff671ec6fee57ba3dd7decf999fe9fe056f3fd4d56e', - ].join('')}`, - ); expect( ethUtil.bufferToHex( utils.hashStruct( @@ -1046,23 +2325,6 @@ it('signedTypeData_v4 with recursive types', function () { ), ).toBe('0xb852e5abfeff916a30cb940c4e24c43cfb5aeb0fa8318bdb10dd2ed15c8c70d8'); - expect( - ethUtil.bufferToHex( - utils.encodeData( - typedData.primaryType, - typedData.message, - typedData.types, - 'V4', - ), - ), - ).toBe( - `0x${[ - '7c5c8e90cb92c8da53b893b24962513be98afcf1b57b00327ae4cc14e3a64116', - 'e8d55aa98b6b411f04dbcf9b23f29247bb0e335a6bc5368220032fdcb9e5927f', - '9ebcfbf94f349de50bcb1e3aa4f1eb38824457c99914fefda27dcf9f99f6178b', - 'b852e5abfeff916a30cb940c4e24c43cfb5aeb0fa8318bdb10dd2ed15c8c70d8', - ].join('')}`, - ); expect( ethUtil.bufferToHex( utils.hashStruct( @@ -1145,23 +2407,6 @@ it('signedTypeMessage V4 with recursive types', function () { '0x7c5c8e90cb92c8da53b893b24962513be98afcf1b57b00327ae4cc14e3a64116', ); - expect( - ethUtil.bufferToHex( - utils.encodeData( - 'Person', - typedData.message.mother, - typedData.types, - 'V4', - ), - ), - ).toBe( - `0x${[ - '7c5c8e90cb92c8da53b893b24962513be98afcf1b57b00327ae4cc14e3a64116', - 'afe4142a2b3e7b0503b44951e6030e0e2c5000ef83c61857e2e6003e7aef8570', - '0000000000000000000000000000000000000000000000000000000000000000', - '88f14be0dd46a8ec608ccbff6d3923a8b4e95cdfc9648f0db6d92a99a264cb36', - ].join('')}`, - ); expect( ethUtil.bufferToHex( utils.hashStruct( @@ -1173,23 +2418,6 @@ it('signedTypeMessage V4 with recursive types', function () { ), ).toBe('0x9ebcfbf94f349de50bcb1e3aa4f1eb38824457c99914fefda27dcf9f99f6178b'); - expect( - ethUtil.bufferToHex( - utils.encodeData( - 'Person', - typedData.message.father, - typedData.types, - 'V4', - ), - ), - ).toBe( - `0x${[ - '7c5c8e90cb92c8da53b893b24962513be98afcf1b57b00327ae4cc14e3a64116', - 'b2a7c7faba769181e578a391a6a6811a3e84080c6a3770a0bf8a856dfa79d333', - '0000000000000000000000000000000000000000000000000000000000000000', - '02cc7460f2c9ff107904cff671ec6fee57ba3dd7decf999fe9fe056f3fd4d56e', - ].join('')}`, - ); expect( ethUtil.bufferToHex( utils.hashStruct( @@ -1201,23 +2429,6 @@ it('signedTypeMessage V4 with recursive types', function () { ), ).toBe('0xb852e5abfeff916a30cb940c4e24c43cfb5aeb0fa8318bdb10dd2ed15c8c70d8'); - expect( - ethUtil.bufferToHex( - utils.encodeData( - typedData.primaryType, - typedData.message, - typedData.types, - 'V4', - ), - ), - ).toBe( - `0x${[ - '7c5c8e90cb92c8da53b893b24962513be98afcf1b57b00327ae4cc14e3a64116', - 'e8d55aa98b6b411f04dbcf9b23f29247bb0e335a6bc5368220032fdcb9e5927f', - '9ebcfbf94f349de50bcb1e3aa4f1eb38824457c99914fefda27dcf9f99f6178b', - 'b852e5abfeff916a30cb940c4e24c43cfb5aeb0fa8318bdb10dd2ed15c8c70d8', - ].join('')}`, - ); expect( ethUtil.bufferToHex( utils.hashStruct(