Add support for ERC-721 and ERC-1155 (v3) (#218)
* First draft for erc721 token allowance * Split ui and provide parameters into their own files * Print txtype when not supported * fix compilation for erc721 * Use pluginType * Add debug statement in compound plugin * add debug error msg in plugin error * Add parameter parsing for all methods * Remove debug logs * Add SET_APPROVAL_FOR_ALL; Add correct parsing method on contract init * Add dst_size parameter to copy functions * Add query contract id code * format * Add UIs * update ethapp.asc * Change setExternalPlugin to setPlugin; Add support for ERC721 * clang-format * Fix typo Unconsistent -> Inconsistent * Add support for 721; use extraInfo * Add extraInfo to ethpluginQueryConractUI * Rename extraInfo to item * Add txFromEtherscan to tests * Add nft key and temp padding * Remove comments around HAVE_BYPASS_SIGNATURES * Rename TESTING_KEY to NFT_TESTING_KEY * Add comments regarding value of queryContractUI->item * Fix comment regarding method selector * Rename provideToken to provideInfo; Update plugin doc * fix caps of eth_plugin_prepare_provide_info * fix caps of handle_provide_info * Use verificationFn insead of hardcoded cx_ecdsa_verify * Add comments about nftInfo_t and tokenDefinition_t * Add erc721 test * Remove comment from plugin interface version * Fix network_ticker duplicate * Add setPlugin and provideNFTInfo to doc.asc * Add back setExternalPlugin; implement new setPlugin * Update plugin sdk * Call setPlugin instead of setExternalPlugin * setPlugin work without checking sig * Remove printf of displayed fees * Add working 721 test * Finalize ERC721 and add simple test * Display NFT address on set approval and operator * Support set approval for all for erc721 * Finish UI for set approval for all erc721 * Move copy_parameter and copy_address to eth_plugin_internal; Add tests for erc721 * update plugin sdk * Add erc1155 plugin and 1155 tests placeholder * Add restriction for AWS key and setPlugin * Add NOT_OLD_INTERNAL variant; Add erc_1155_plugin_call * Fixed compilation warnings (function pointer casting) Co-authored-by: pscott <scott.piriou@ledger.fr>
This commit is contained in:
27
tests/src/erc1155.test .js
Normal file
27
tests/src/erc1155.test .js
Normal file
@@ -0,0 +1,27 @@
|
||||
import "core-js/stable";
|
||||
import "regenerator-runtime/runtime";
|
||||
import { waitForAppScreen, zemu, txFromEtherscan } from './test.fixture';
|
||||
import { TransportStatusError } from "@ledgerhq/errors";
|
||||
|
||||
// -------------------
|
||||
// TODO: Actually write the tests
|
||||
|
||||
test.skip('[Nano S] Transfer 1155', zemu("nanos", async (sim, eth) => {
|
||||
|
||||
const rawTx = ""
|
||||
const serializedTx = txFromEtherscan(rawTx);
|
||||
|
||||
// with ETH need to test
|
||||
// const serializedTx = txFromEtherscan("0x02f901350182022f8459682f0085246ad7eb3182de2994424db67b40b15ed85475c3f29dedf601b6ee75b283424242b8c4f242432a000000000000000000000000dcdb88f3754b2841093d9348a2d02df8cf06314c000000000000000000000000df9fb2eff1f2871caeeb94bf262ffba84efddddc0000000000000000000000000000000000000000000000000000000000000007000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000c001a0c4283f86dc852e43e9fd1077b448c63fec76bdeb44dfac977730725e41fa3676a0543b2d2f99f65fb20cd548964eee94b1c1865919f4574c7089d8b95678b667c2");
|
||||
|
||||
const tx = eth.signTransaction(
|
||||
"44'/60'/1'/0/0",
|
||||
serializedTx,
|
||||
);
|
||||
|
||||
await waitForAppScreen(sim);
|
||||
await sim.navigateAndCompareSnapshots('.', 'nanos_erc721_transfer_ethereum', [12, 0]);
|
||||
|
||||
await expect(tx).resolves.toEqual({
|
||||
});
|
||||
}));
|
||||
130
tests/src/erc721.test.js
Normal file
130
tests/src/erc721.test.js
Normal file
@@ -0,0 +1,130 @@
|
||||
import "core-js/stable";
|
||||
import "regenerator-runtime/runtime";
|
||||
import { waitForAppScreen, zemu, txFromEtherscan } from './test.fixture';
|
||||
|
||||
test('[Nano S] Transfer erc721', zemu("nanos", async (sim, eth) => {
|
||||
|
||||
// https://etherscan.io/tx/0x73cec4fc07de3a24ba42e8756e13b7ddfa9bd449126c37640881195e8ea9e679
|
||||
// Modified to put a bigger token id
|
||||
const rawTx = "0x02f8d101058459682f0085233da9943e8301865b94bd3531da5cf5857e7cfaa92426877b022e612cf880b86423b872dd0000000000000000000000004cc568b73c0dcf8e90db26d7fd3a6cfadca108a3000000000000000000000000d4c9b20950c3eca38fc1f33f54bdf9694e488799ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc080a094c8632fe7277aa8c54cea9d81a15911cfa4970a2bf7356d14d04cc5afbcdab7a013a77b8c79e5d9b2b35edb3c44db3bb41b92f5c463ff126bf19d213b2b9ba8b5"
|
||||
const serializedTx = txFromEtherscan(rawTx);
|
||||
|
||||
const tx = eth.signTransaction(
|
||||
"44'/60'/1'/0/0",
|
||||
serializedTx,
|
||||
);
|
||||
|
||||
await waitForAppScreen(sim);
|
||||
await sim.navigateAndCompareSnapshots('.', 'nanos_erc721_transfer', [12, 0]);
|
||||
|
||||
await expect(tx).resolves.toEqual({
|
||||
"r": "59f6a9769cff66eed8be8716c44d39808d1e43f3aa0bb97538e124dba4bc4565",
|
||||
"s": "662990a841c663a165ba9a83e5cc95c03a999b851e0bd6d296aa70a0f7c96c1a",
|
||||
"v": "01",
|
||||
});
|
||||
}));
|
||||
|
||||
test('[Nano S] Transfer erc721 with attached ETH', zemu("nanos", async (sim, eth) => {
|
||||
|
||||
const rawTx = "0x02f8d601058459682f0085233da9943e8301865b94bd3531da5cf5857e7cfaa92426877b022e612cf8854242424242b86423b872dd0000000000000000000000004cc568b73c0dcf8e90db26d7fd3a6cfadca108a3000000000000000000000000d4c9b20950c3eca38fc1f33f54bdf9694e4887990000000000000000000000000000000000000000000000000000000000000f21c080a094c8632fe7277aa8c54cea9d81a15911cfa4970a2bf7356d14d04cc5afbcdab7a013a77b8c79e5d9b2b35edb3c44db3bb41b92f5c463ff126bf19d213b2b9ba8b5"
|
||||
const serializedTx = txFromEtherscan(rawTx);
|
||||
|
||||
|
||||
const tx = eth.signTransaction(
|
||||
"44'/60'/1'/0/0",
|
||||
serializedTx,
|
||||
);
|
||||
|
||||
await waitForAppScreen(sim);
|
||||
await sim.navigateAndCompareSnapshots('.', 'nanos_erc721_transfer_with_eth', [13, 0]);
|
||||
|
||||
await expect(tx).resolves.toEqual({
|
||||
"r": "9c42e10b49f3ee315ab2d5f7ad96f1068c75578734b66504716cc279ead27d47",
|
||||
"s": "45dde78470ad75ffdb27a799b87e4934e2e10e98dbc6f88bc4a9bc19c4de86bc",
|
||||
"v": "00",
|
||||
});
|
||||
}));
|
||||
|
||||
test('[Nano S] set approval for all erc721', zemu("nanos", async (sim, eth) => {
|
||||
|
||||
// https://etherscan.io/tx/0x86b936db53c19fddf26b8d145f165e1c7fdff3c0f8b14b7758a38f0400cfd93f
|
||||
const rawTx = "0x02f8b0010c8459682f00852cfbb00ee682b54294d4e4078ca3495de5b1d4db434bebc5a98619778280b844a22cb4650000000000000000000000002efcb1e8d4472d35356b9747bea8a051eac2e3f50000000000000000000000000000000000000000000000000000000000000001c001a0c5b8c024c15ca1452ce8a13eacfcdc25f1c6f581bb3ce570e82f08f1b792b3aca03be4dba0302ae190618a72eb1202ce3af3e17afd7d8a94345a48cae5cad15541";
|
||||
const serializedTx = txFromEtherscan(rawTx);
|
||||
|
||||
|
||||
const tx = eth.signTransaction(
|
||||
"44'/60'/1'/0/0",
|
||||
serializedTx,
|
||||
);
|
||||
|
||||
await waitForAppScreen(sim);
|
||||
await sim.navigateAndCompareSnapshots('.', 'nanos_erc721_approval_for_all', [12, 0]);
|
||||
|
||||
await expect(tx).resolves.toEqual({
|
||||
"r": "8b6a70a1fe76d8e9b1250531a17eb1e367936732d4dfb9befc81a5031b271dc8",
|
||||
"s": "7658d7151bba0d8504cea2013bead64cb8407dc6be1fca829bb9594b56f679af",
|
||||
"v": "00",
|
||||
});
|
||||
}));
|
||||
|
||||
// NOT DONE
|
||||
test.skip('[Nano S] approval erc721', zemu("nanos", async (sim, eth) => {
|
||||
|
||||
// INCORRECT, need to find / create an approval tx
|
||||
const rawTx = "";
|
||||
const serializedTx = txFromEtherscan(rawTx);
|
||||
|
||||
|
||||
const tx = eth.signTransaction(
|
||||
"44'/60'/1'/0/0",
|
||||
serializedTx,
|
||||
);
|
||||
|
||||
await waitForAppScreen(sim);
|
||||
await sim.navigateAndCompareSnapshots('.', 'nanos_erc721_approval', [12, 0]);
|
||||
|
||||
await expect(tx).resolves.toEqual({
|
||||
});
|
||||
}));
|
||||
|
||||
test('[Nano S] safe transfer erc721', zemu("nanos", async (sim, eth) => {
|
||||
|
||||
// https://etherscan.io/tx/0x1ee6ce9be1c9fe6f030ff124ba8c88a410223c022816547e4b3fedd3a4d2dc1e
|
||||
const rawTx = "0xf8cc82028585077359400083061a8094d4e4078ca3495de5b1d4db434bebc5a98619778280b86442842e0e000000000000000000000000c352b534e8b987e036a93539fd6897f53488e56a0000000000000000000000000a9287d9339c175cd3ea0ad4228f734a9f75ee6200000000000000000000000000000000000000000000000000000000000000621ca08250f4b2c8f28c5e4ef621dba4682990d1faf930c8cb6d032c6e7278e8951d92a03c1e1f6d63ed339041f69f24c6c0968ba26f244f779cb4fa7a468f3ba3d3e06e";
|
||||
const serializedTx = txFromEtherscan(rawTx);
|
||||
|
||||
|
||||
const tx = eth.signTransaction(
|
||||
"44'/60'/1'/0/0",
|
||||
serializedTx,
|
||||
);
|
||||
|
||||
await waitForAppScreen(sim);
|
||||
await sim.navigateAndCompareSnapshots('.', 'nanos_erc721_safe_transfer', [10, 0]);
|
||||
|
||||
await expect(tx).resolves.toEqual({
|
||||
"r": "b936684d5d0e99e09701021fb73ae9403f2ec79414d822d42c5bd1c0a2118f1a",
|
||||
"s": "23e517c6cac998f392d179be2fe7c3225f0e0a165b1af85548da5d6acaa73c4f",
|
||||
"v": "25",
|
||||
});
|
||||
}));
|
||||
|
||||
// NOT DONE
|
||||
test.skip('[Nano S] safe transfer with data erc721', zemu("nanos", async (sim, eth) => {
|
||||
|
||||
// need to find or create a safe transfer with data on etherscan?
|
||||
const rawTx = "";
|
||||
const serializedTx = txFromEtherscan(rawTx);
|
||||
|
||||
|
||||
const tx = eth.signTransaction(
|
||||
"44'/60'/1'/0/0",
|
||||
serializedTx,
|
||||
);
|
||||
|
||||
await waitForAppScreen(sim);
|
||||
await sim.navigateAndCompareSnapshots('.', 'nanos_erc721_safe_transfer_with_data', [12, 0]);
|
||||
|
||||
await expect(tx).resolves.toEqual({
|
||||
});
|
||||
}));
|
||||
@@ -1,5 +1,6 @@
|
||||
import Zemu from '@zondax/zemu';
|
||||
import Eth from '@ledgerhq/hw-app-eth';
|
||||
import {RLP} from "ethers/lib/utils";
|
||||
|
||||
const transactionUploadDelay = 60000;
|
||||
|
||||
@@ -36,6 +37,35 @@ const NANOX_CLONE_ELF_PATH = Resolve("elfs/ethereum_classic_nanox.elf");
|
||||
|
||||
const TIMEOUT = 1000000;
|
||||
|
||||
// Generates a serializedTransaction from a rawHexTransaction copy pasted from etherscan.
|
||||
function txFromEtherscan(rawTx) {
|
||||
// Remove 0x prefix
|
||||
rawTx = rawTx.slice(2);
|
||||
|
||||
let txType = rawTx.slice(0, 2);
|
||||
if (txType == "02" || txType == "01") {
|
||||
// Remove "02" prefix
|
||||
rawTx = rawTx.slice(2);
|
||||
} else {
|
||||
txType = "";
|
||||
}
|
||||
|
||||
let decoded = RLP.decode("0x" + rawTx);
|
||||
if (txType != "") {
|
||||
decoded = decoded.slice(0, decoded.length - 3); // remove v, r, s
|
||||
} else {
|
||||
decoded[decoded.length - 1] = "0x"; // empty
|
||||
decoded[decoded.length - 2] = "0x"; // empty
|
||||
decoded[decoded.length - 3] = "0x01"; // chainID 1
|
||||
}
|
||||
|
||||
// Encode back the data, drop the '0x' prefix
|
||||
let encoded = RLP.encode(decoded).slice(2);
|
||||
|
||||
// Don't forget to prepend the txtype
|
||||
return txType + encoded;
|
||||
}
|
||||
|
||||
function zemu(device, func) {
|
||||
return async () => {
|
||||
jest.setTimeout(TIMEOUT);
|
||||
@@ -71,5 +101,6 @@ module.exports = {
|
||||
NANOX_CLONE_ELF_PATH,
|
||||
sim_options_nanos,
|
||||
sim_options_nanox,
|
||||
TIMEOUT
|
||||
TIMEOUT,
|
||||
txFromEtherscan,
|
||||
}
|
||||
Reference in New Issue
Block a user