UNPKG

@ledgerhq/hw-app-eth

Version:
187 lines (168 loc) • 15 kB
import nock from "nock"; import { BigNumber } from "@ethersproject/bignumber"; import { AddressZero } from "@ethersproject/constants"; import { type Transaction } from "@ethersproject/transactions"; import SignatureCALEth from "../fixtures/SignatureCALEth"; import { UNISWAP_EXECUTE_SELECTOR, UNISWAP_UNIVERSAL_ROUTER_ADDRESS, } from "../../src/modules/Uniswap/constants"; import { getCommandsAndTokensFromUniswapCalldata, isSupported, loadInfosForUniswap, } from "../../src/modules/Uniswap"; nock.disableNetConnect(); jest.mock("@ledgerhq/cryptoassets-evm-signatures/data/evm/index", () => ({ get signatures() { return { 1: SignatureCALEth, }; }, })); describe("Uniswap", () => { describe("index", () => { describe("isSupported", () => { it("should return false for a non-Uniswap transaction", () => { expect(isSupported("0x", AddressZero, 1, [])).toBe(false); }); it("should return false for a Uniswap transaction with an invalid selector", () => { expect(isSupported("0x123456", UNISWAP_UNIVERSAL_ROUTER_ADDRESS, 1, [])).toBe(false); }); it("should return false for a Uniswap transaction with no commands", () => { expect(isSupported(UNISWAP_EXECUTE_SELECTOR, UNISWAP_UNIVERSAL_ROUTER_ADDRESS, 1, [])).toBe( false, ); }); it("should return false for a transaction of multiple hops with different pool versions", () => { expect( isSupported(UNISWAP_EXECUTE_SELECTOR, UNISWAP_UNIVERSAL_ROUTER_ADDRESS, 1, [ ["V2_SWAP_EXACT_IN", ["0x1", "0x2"]], ["V3_SWAP_EXACT_IN", ["0x2", "0x3"]], ]), ).toBe(false); }); it("should return false for a transaction of multiple hops with non chained assets", () => { expect( isSupported(UNISWAP_EXECUTE_SELECTOR, UNISWAP_UNIVERSAL_ROUTER_ADDRESS, 1, [ ["V2_SWAP_EXACT_IN", ["0x0A", "0x0B"]], ["V2_SWAP_EXACT_IN", ["0x0A", "0x0C"]], ]), ).toBe(false); }); it("should return false for a transaction of multiple hops with non chained assets", () => { expect( isSupported(UNISWAP_EXECUTE_SELECTOR, UNISWAP_UNIVERSAL_ROUTER_ADDRESS, 1, [ ["V2_SWAP_EXACT_IN", ["0x0A", "0x0B"]], ["V2_SWAP_EXACT_IN", ["0x0A", "0x0C"]], ]), ).toBe(false); }); it("should return true for a valid Uniswap transaction", () => { expect( isSupported(UNISWAP_EXECUTE_SELECTOR, UNISWAP_UNIVERSAL_ROUTER_ADDRESS, 1, [ ["V2_SWAP_EXACT_IN", ["0x0A", "0x0B"]], ["V2_SWAP_EXACT_IN", ["0x0B", "0x0C"]], ]), ).toBe(true); expect( isSupported(UNISWAP_EXECUTE_SELECTOR, UNISWAP_UNIVERSAL_ROUTER_ADDRESS, 1, [ ["V3_SWAP_EXACT_IN", ["0x0A", "0x0B"]], ["V3_SWAP_EXACT_IN", ["0x0B", "0x0C"]], ]), ).toBe(true); expect( isSupported(UNISWAP_EXECUTE_SELECTOR, UNISWAP_UNIVERSAL_ROUTER_ADDRESS, 1, [ ["V3_SWAP_EXACT_IN", ["0x0A", "0x0B"]], ["V3_SWAP_EXACT_OUT", ["0x0B", "0x0C"]], ]), ).toBe(true); expect( isSupported(UNISWAP_EXECUTE_SELECTOR, UNISWAP_UNIVERSAL_ROUTER_ADDRESS, 1, [ ["V2_SWAP_EXACT_IN", ["0x0A", "0x0B"]], ["V2_SWAP_EXACT_OUT", ["0x0B", "0x0C"]], ]), ).toBe(true); }); }); describe("getCommandsAndTokensFromUniswapCalldata", () => { it("should return the commands and tokens from a Uniswap calldata", () => { // see tx 0xc4df7ccc0527541d0e80856a8f38deedc48c84825e9355469ba02d873502ce2f const calldata = "0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000669b9ec100000000000000000000000000000000000000000000000000000000000000030a010c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000016000000000000000000000000055747be9f9f5beb232ad59fe7af013b81d95fd5e000000000000000000000000ffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000066c32b0d0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b00000000000000000000000000000000000000000000000000000000669b9ec100000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000410d756f55acf289e9754faf91bba0a704b5c7c0aa4b1dfd551115ccbe4c7f290234e1a14265e1da0bc872a23627d997fe37a689c290d519f7b8c9bdde1b79108e1b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000030ba49cbff5a00000000000000000000000000000000000000000000000089677c957272141800000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc200271055747be9f9f5beb232ad59fe7af013b81d95fd5e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000030ba49cbff5a000"; expect(getCommandsAndTokensFromUniswapCalldata(calldata, 1)).toEqual([ ["PERMIT2_PERMIT", []], [ "V3_SWAP_EXACT_OUT", [ "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", "0x55747be9f9f5beb232ad59fe7af013b81d95fd5e", ], ], ["UNWRAP_ETH", ["0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"]], ]); }); it("should return an undefined command for unsupported commands by the Uniswap plugin", () => { // see tx 0xc0668eb799ba8b73a396529a183b67e7905c0f70143680915ee5802b3036257b const calldata = "0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000669b9f4700000000000000000000000000000000000000000000000000000000000000030b000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000004fdf8403a58c8000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000ff436c9cd1052265be510e00a661f432c539080000000000000000000000000000000000000000000000000004fdf8403a58c80000000000000000000000000000000000000000000ac736c3566d2e76b2c5978300000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc20027103ffeea07a27fab7ad1df5297fa75e77a43cb5790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f0279540eed3fb666e8aaa4571a47e7478b6e9d000000000000000000000000000000000000000000000000000ce8a624ca9800"; expect(getCommandsAndTokensFromUniswapCalldata(calldata, 1)).toEqual([ ["WRAP_ETH", ["0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"]], [ "V3_SWAP_EXACT_IN", [ "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", "0x3ffeea07a27fab7ad1df5297fa75e77a43cb5790", ], ], [undefined, []], ]); }); it("should return an empty array for an invalid selector", () => { const calldata = "0x123456000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000669b9ec100000000000000000000000000000000000000000000000000000000000000030a010c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000016000000000000000000000000055747be9f9f5beb232ad59fe7af013b81d95fd5e000000000000000000000000ffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000066c32b0d0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b00000000000000000000000000000000000000000000000000000000669b9ec100000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000410d756f55acf289e9754faf91bba0a704b5c7c0aa4b1dfd551115ccbe4c7f290234e1a14265e1da0bc872a23627d997fe37a689c290d519f7b8c9bdde1b79108e1b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000030ba49cbff5a00000000000000000000000000000000000000000000000089677c957272141800000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc200271055747be9f9f5beb232ad59fe7af013b81d95fd5e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000030ba49cbff5a000"; expect(getCommandsAndTokensFromUniswapCalldata(calldata, 1)).toEqual([]); }); }); describe("loadInfosForUniswap", () => { it("should return ERC20 & plugin descriptors for a valid Uniswap transaction", async () => { // see tx 0x88a065f47c82545b0620378d6cb2231713464dd58c0a2b8d6e9485740807b573 const calldata = "0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000669bad2800000000000000000000000000000000000000000000000000000000000000040a08060c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000bdaa645097ef80f9d475f341d0d107a45b3a000000000000000000000000ffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000687ce06c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b00000000000000000000000000000000000000000000000000000000687ce06c00000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000004142794d71565541a435d1bc910db84510c4d31ad35ff8c046222b2c232fcd99a6256a8f1abe7d42a44f3d92d65f9232db76df2fbef3dfa76eca64b034ed4df5321c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000001bffcca36d953d12266cb000000000000000000000000000000000000000000000000027c3dea3f90dafd00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000bdaa645097ef80f9d475f341d0d107a45b3a000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000000000000000060000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006eb940753b4b52fbec8d33c418133fdb0d4405e6000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000400000000000000000000000001dc813a4ee4410f144ae2122051c1cfc436f24a00000000000000000000000000000000000000000000000000275e122c92b911e"; const transaction: Transaction = { to: UNISWAP_UNIVERSAL_ROUTER_ADDRESS, data: calldata, gasLimit: BigNumber.from(21_000), nonce: 0, value: BigNumber.from(0), chainId: 1, }; const res = await loadInfosForUniswap(transaction, 1); expect(res).toEqual({ pluginData: Buffer.from( "07556e69737761703fc91a3afd70395cd496c647d5a6cc9d4b2b7fad3593564c3044022014391e8f355867a57fe88f6a5a4dbcb8bf8f888a9db3ff3449caf72d120396bd02200c13d9c3f79400fe0aa0434ac54d59b79503c9964a4abc3e8cd22763e0242935", "hex", ), tokenDescriptors: [ Buffer.from( "0457455448c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000012000000013045022100b47ee8551c15a2cf681c649651e987d7e527c481d27c38da1f971a8242792bd3022069c3f688ac5493a23dab5798e3c9b07484765069e1d4be14321aae4d92cb8cbe", "hex", ), ], }); }); it("should return an empty object for an unsupported Uniswap transaction", async () => { const transaction: Transaction = { to: AddressZero, data: "0x", gasLimit: BigNumber.from(21_000), nonce: 0, value: BigNumber.from(0), chainId: 1, }; const res = await loadInfosForUniswap(transaction, 1); expect(res).toEqual({}); }); }); }); });