Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

loadRemoteVersion is not working with jest test #724

Open
Damantino opened this issue Jan 10, 2024 · 3 comments
Open

loadRemoteVersion is not working with jest test #724

Damantino opened this issue Jan 10, 2024 · 3 comments

Comments

@Damantino
Copy link

Damantino commented Jan 10, 2024

I have made a verification service which verifies smart contracts. I have and endpoint that I'm trying to test. It receives all the solidity files and a few settings and outputs if it matches with code on mainnet.

While doing tests everything was fine until I could not load the remote version, I cannot mock that, it need to be the snapshot.

Here is the code for the test:

it('/verify (POST)', async () => {
    const contractsDir = path.join(__dirname, './contracts');
    const testFolders = fs.readdirSync(contractsDir);

    for (const folder of testFolders) {
      const folderPath = path.join(contractsDir, folder);
      const files = fs.readdirSync(folderPath);

      const req = request(app.getHttpServer()).post('/contracts/verify').set('accept', '*/*').set('Content-Type', 'multipart/form-data');

      let settings: any;

      await Promise.all(
        files.map(async (file) => {
          const ext = path.extname(file);
          const filePath = path.join(folderPath, file);
          if (ext === '.sol') {
            req.attach('files', filePath);
          } else if (ext === '.json') {
            settings = JSON.parse(await fs.promises.readFile(filePath, 'utf-8'));
          }
        }),
      );

      req.field('contractAddress', settings.address);
      req.field('chain', '1');
      req.field('evmVersion', settings.evmVersion);
      req.field('optimizationEnabled', settings.optimizer.enabled);
      req.field('optimizationRuns', settings.optimizer.runs);
      req.field('viaIr', settings.viaIR ?? false);

      const response = await req;
      expect(response.status).toEqual(200);
    }
  });

This works until I arrive to my service, I have a function to load asynchronously the solc snaphot.

async loadSolc(version: string): Promise<any> {
    return await new Promise((resolve, reject) => {
      if (solcCache[version] !== undefined) resolve(solcCache[version]);
      // You may need to adjust the import statement based on your environment
      else {
        loadRemoteVersion(`v${version}`, (error: any, soljson: any) => {
          solcCache[version] = soljson;
          return error ? reject(error) : resolve(soljson);
        });
      }
    });
  }

This is used then on the compile:

async compile(version: string, solcJsonInput: any, forceEmscripten = false): Promise<any> {
    const solc = await this.loadSolc(version);
    const compiledOutput = JSON.parse(solc.compile(JSON.stringify(solcJsonInput)));

    return compiledOutput;
  }

It keeps on loadSolC forever.

Any help would be appreciated.

PD: I have on package json:

"jest": {
    "moduleFileExtensions": [
      "js",
      "json",
      "ts"
    ],
    "rootDir": ".",
    "testRegex": ".*\\.spec\\.ts$",
    "transform": {
      "^.+\\.(t|j)s$": "ts-jest"
    },
    "moduleNameMapper": {
      "^src/(.*)$": "<rootDir>/src/$1"
    },
    "collectCoverageFrom": [
      "**/*.(t|j)s"
    ],
    "coverageDirectory": "../coverage",
    "testEnvironment": "node"
  }

EDIT: md format

@kuzdogan
Copy link
Member

Hey just came across this. Sourcify is also an open-source verification service. We specifically have a plug-and-play package for that called lib-sourcify https://github.com/ethereum/sourcify/tree/staging/packages/lib-sourcify

It's a bit difficult to understand from your excerpt but maybe our code would help, or even you can use the package as a whole. Right now the standard usage assumes you have a metadata.json file for your contracts but you should be able to use the functions there or just look at the code and infer things. It's not browser compatible yet.

Happy to help if you want to use the package or help as much as I can. If your repo is public, can you please share?

@Damantino
Copy link
Author

Hey @kuzdogan . yeah I first reach out to you guys (to you specifically), but I've been trying to verify without the need of uploading metadata.

What I'm trying to do is:

I have a set of folders inside contracts/ folder. Each folder has all the solidity files for a smart contract and a settings.json.

I call the endpoint with the files and the settings. Because it's still in development I must be sure that new changes don't break contracts that I was already verifying.

I would like to automatise the process therefore I need to test my endpoint, If you have any clue on how to test loadRemoteVersion on js/typescript or more specifically on a nestjs project I would be very grateful.

@kuzdogan
Copy link
Member

Hmm we don't use the loadRemote method but instead download the compiler versions ourself or just mount a folder with all compiler versions.

https://github.com/ethereum/sourcify/blob/129ba96f13246fb2642e8d79d461adbf9e529ff5/services/server/src/server/services/compiler/local/solidityCompiler.ts#L303-L323

In your case I think you can either use the compiler as we do or maybe intercept the call the solc-js makes to the remote solc repo (if it does) with something like nock. For example here we intercept the call to the Sourcify server and return an already set response. You can return a local compiler with by intercepting the call

https://github.com/ethereum/sourcify/blob/1a620f5d9b13713be3e61b14b6c274c7eacab583/services/monitor/test/Monitor.test.js#L105-L110

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants