solc-js icon indicating copy to clipboard operation
solc-js copied to clipboard

asm.js build of soljson 0.4.25 fails on node.js 14+

Open Troublor opened this issue 3 years ago • 9 comments

It seems that legacy version 0.4.25 does not work for any contracts.

My code:

const path = require('path');
const fs = require('fs');
const solc = require('solc');
solc.loadRemoteVersion('v0.4.25+commit.59dbf8f1', function(err, solcSnapshot) {
    if (err) {
        console.error(err);
    } else {
        const input = {
            language: 'Solidity',
            sources: {
                'test.sol': {
                    content: fs.readFileSync(path.join(__dirname, 'testContract.sol'), {encoding: 'utf-8'}),
                }
            },
            settings: {
                outputSelection: {
                    '*': {
                        '*': ['*']
                    }
                }
            }
        };
        const output = JSON.parse(solcSnapshot.compile(JSON.stringify(input)));
        console.log(output);
    }
});

The contract is as simple as this:

pragma solidity ^0.4.25;

contract C{}

Output:

RangeError: Maximum call stack size exceeded
    at Object.$db [as dynCall_viiiiii] (soljson-v0.4.25+commit.59dbf8f1.js:12:120931)
    at invoke_viiiiii (soljson-v0.4.25+commit.59dbf8f1.js:1:1118207)
    at Array.pva (soljson-v0.4.25+commit.59dbf8f1.js:13:29030)
    at Object.M9a [as dynCall_vi] (soljson-v0.4.25+commit.59dbf8f1.js:12:99033)
    at invoke_vi (soljson-v0.4.25+commit.59dbf8f1.js:1:1115011)
    at Array.xta (soljson-v0.4.25+commit.59dbf8f1.js:10:704784)
    at Object.Dfb [as dynCall_iii] (soljson-v0.4.25+commit.59dbf8f1.js:12:130740)
    at invoke_iii (soljson-v0.4.25+commit.59dbf8f1.js:1:1119442)
    at Array.vta (soljson-v0.4.25+commit.59dbf8f1.js:10:703080)
    at Object.Yfb [as dynCall_iiiiii] (soljson-v0.4.25+commit.59dbf8f1.js:12:131900)

There is a similar issue #496. But the problem is not solved at all. That issue is closed only because the creator changed the compiler version. But this walkaround solution is not applicable to me. I am reproducing verified contracts on Etherscan and need to compile the contract using the exactly the same compiler version as required in the contract verification.

Troublor avatar Jul 14 '21 14:07 Troublor

I can confirm the problem on 0.4.25, though I'm getting a different stack trace:

(node:366095) V8: soljson-v0.4.25+commit.59dbf8f1.js:3 Invalid asm.js: Invalid member of stdlib
    at Object.compileFunction (node:vm:352:18)
    at wrapSafe (node:internal/modules/cjs/loader:1025:15)
    at Module._compile (node:internal/modules/cjs/loader:1059:27)
    at requireFromString (/tmp/x/node_modules/require-from-string/index.js:28:4)
    at IncomingMessage.<anonymous> (/tmp/x/node_modules/solc/wrapper.js:338:35)
    at IncomingMessage.emit (node:events:406:35)
    at endReadableNT (node:internal/streams/readable:1329:12)
    at processTicksAndRejections (node:internal/process/task_queues:83:21)

Interestingly, it happens only on newer node.js versions (tried v16.4.2 and v14.16.0). No error on v12.22.0.

Also, the wasm 0.4.25 binary does not have this problem. I recommend using this binary over the asm.js one anyway.

Not sure if there's anything we can do to fix this particular asm.js binary for newer node.js. At least we should update loadRemoteVersion() to download the wasm one when available.

cameel avatar Jul 15 '21 23:07 cameel

Interestingly, it happens only on newer node.js versions (tried v16.4.2 and v14.16.0). No error on v12.22.0.

@cameel Thanks for pinpointing the problem. FYI, my node version is v16.3.0. I will try to use wasm binary instead.

Troublor avatar Jul 26 '21 02:07 Troublor

More binaries might be affected by this: (Invalid asm.js: Invalid member of stdlib) while trying to compile solidity 0.4.17.

cameel avatar Dec 17 '21 00:12 cameel

FYI @cameel, I just noticed a similar error for 0.4.18+commit.9cf6e910.js @truffle/fetch-and-compile test suite

(node:4047479) V8: /home/amal/.config/truffle-nodejs/compilers/node_modules/soljson-v0.4.18+commit.9cf6e910.js:3 Invalid asm.js: Invalid member of stdlib

Node v16.14.2 and soljson-v0.4.18+commit.9cf6e910.js Stacktrace
(node:4047597) V8: /home/amal/.config/truffle-nodejs/compilers/node_modules/soljson-v0.4.18+commit.9cf6e910.js:3 Invalid asm.js: Invalid member of stdlib
    at compileFunction (<anonymous>)
    at Object.compileFunction (node:vm:352:18)
    at wrapSafe (node:internal/modules/cjs/loader:1032:15)
    at Module._compile (node:internal/modules/cjs/loader:1067:27)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1157:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Module.require (node:internal/modules/cjs/loader:1005:19)
    at Object.require (node:internal/modules/cjs/helpers:102:18)
    at VersionRange.getCachedSolcByFileName (/home/amal/work/truffle/packages/compile-solidity/src/compilerSupplier/loadingStrategies/VersionRange.ts:94:38)
    at VersionRange.getCachedSolcByVersionRange (/home/amal/work/truffle/packages/compile-solidity/src/compilerSupplier/loadingStrategies/VersionRange.ts:114:17)
    at VersionRange.<anonymous> (/home/amal/work/truffle/packages/compile-solidity/src/compilerSupplier/loadingStrategies/VersionRange.ts:42:19)
    at Generator.next (<anonymous>)
    at /home/amal/work/truffle/packages/compile-solidity/dist/compilerSupplier/loadingStrategies/VersionRange.js:8:71
    at new Promise (<anonymous>)
    at __awaiter (/home/amal/work/truffle/packages/compile-solidity/dist/compilerSupplier/loadingStrategies/VersionRange.js:4:12)
    at VersionRange.load (/home/amal/work/truffle/packages/compile-solidity/dist/compilerSupplier/loadingStrategies/VersionRange.js:44:16)
    at CompilerSupplier.<anonymous> (/home/amal/work/truffle/packages/compile-solidity/src/compilerSupplier/index.ts:69:35)
    at Generator.next (<anonymous>)
    at /home/amal/work/truffle/packages/compile-solidity/dist/compilerSupplier/index.js:8:71
    at new Promise (<anonymous>)
    at __awaiter (/home/amal/work/truffle/packages/compile-solidity/dist/compilerSupplier/index.js:4:12)
    at CompilerSupplier.load (/home/amal/work/truffle/packages/compile-solidity/dist/compilerSupplier/index.js:41:16)
    at /home/amal/work/truffle/packages/compile-solidity/src/run.js:230:32
    at Generator.next (<anonymous>)
    at /home/amal/work/truffle/packages/compile-solidity/dist/run.js:7:71
    at new Promise (<anonymous>)
    at __awaiter (/home/amal/work/truffle/packages/compile-solidity/dist/run.js:3:12)
    at invokeCompiler (/home/amal/work/truffle/packages/compile-solidity/dist/run.js:187:12)
    at /home/amal/work/truffle/packages/compile-solidity/src/run.js:46:49
    at Generator.next (<anonymous>)
    at /home/amal/work/truffle/packages/compile-solidity/dist/run.js:7:71
    at new Promise (<anonymous>)
    at __awaiter (/home/amal/work/truffle/packages/compile-solidity/dist/run.js:3:12)
    at run (/home/amal/work/truffle/packages/compile-solidity/dist/run.js:19:12)
    at Object.<anonymous> (/home/amal/work/truffle/packages/compile-solidity/src/index.js:62:33)
    at Generator.next (<anonymous>)
    at /home/amal/work/truffle/packages/compile-solidity/dist/index.js:7:71
    at new Promise (<anonymous>)
    at __awaiter (/home/amal/work/truffle/packages/compile-solidity/dist/index.js:3:12)
    at Object.sources (/home/amal/work/truffle/packages/compile-solidity/dist/index.js:54:16)
    at /home/amal/work/truffle/packages/fetch-and-compile/lib/fetch.ts:145:37
    at Generator.next (<anonymous>)
    at fulfilled (/home/amal/work/truffle/packages/fetch-and-compile/lib/fetch.ts:5:58)

cds-amal avatar Apr 27 '22 22:04 cds-amal

Thanks for the report! Honestly, I'm not sure what to do about this issue. It looks more like a node.js issue, especially given that these binaries used to work.

I did some searching and found an old thread about the same error happening in Remix. This comment from @axic seems the most relevant:

According to https://bugs.chromium.org/p/chromium/issues/detail?id=771563:

If you are getting this "Invalid member of stdlib" message, it means that your module is not validating, and it is going through the normal JS pipeline. Does your module verify without problems on Firefox?

It seems it maybe a V8 (Chrome, Node) issue. Though that thread says it should work, albeit slowly.

So to move this forward we'd probably need to report it upstream.

cameel avatar Apr 28 '22 09:04 cameel

@cds-amal Also, any reason you're still using the asm.js binaries? We have equivalent wasm builds and these should really be preferred since they're also faster. This issue is pretty low on the priority list mostly because of this - wasm builds do not have that problem and should be better in all respects so switching to them is not just a workaround, it's the right solution here.

cameel avatar Apr 28 '22 09:04 cameel

Hi @cameel, Truffle sources solc.js from the two endpoints below (in order).

  • https://solc-bin.ethereum.org/bin/,
  • https://ethereum.github.io/solc-bin/bin/

How can I identify a wasm build? The following file doesn't have the string Module["wasmBinary"] that others seem to have.

curl https://solc-bin.ethereum.org/bin/soljson-v0.4.18+commit.9cf6e910.js 

cds-amal avatar Apr 28 '22 18:04 cds-amal

See https://github.com/trufflesuite/truffle/issues/4425

Basically, if you use https://binaries.soliditylang.org/emscripten-wasm32/ you'll get only wasm binaries. You can use https://binaries.soliditylang.org/emscripten-asmjs/ as a fallback.

If you want to detect the wasm ones on your own, presence of var wasmBinaryFile="data:application/octet-stream;base64,AGFzbQEA is a heuristic I used in the past but I can't guarantee that it's foolproof. Emscripten could easily change some detail in a future version making it slightly different. It should be more reliable to just use the right dir.

cameel avatar Apr 28 '22 19:04 cameel

I'm not too sure how to go about replacing the asm.js by the wasm one, but in my case increasing the stack-size got it to pass (for node 16).

node --stack-size=2000 index.js

Default size was 984 on my system:

node --v8-options | grep -B0 -A1 stack-size
  --stack-size (default size of stack region v8 is allowed to use (in kBytes))
        type: int  default: 984

AndreMiras avatar Oct 26 '22 13:10 AndreMiras