mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-06-21 11:31:02 +00:00
Emerge Yul recompiler (#1)
Provide a modified (and incomplete) version of ZKSync zksolc that can compile the most basic contracts
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
preset: "ts-jest",
|
||||
testEnvironment: "node",
|
||||
};
|
||||
+3812
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "cli-tests",
|
||||
"version": "1.0.0",
|
||||
"title": "zksolc CLI Tests",
|
||||
"description": "Auto tests for verifying zksolc CLI",
|
||||
"repository": "https://github.com/matter-labs/era_compiler-solidity",
|
||||
"main": "index.js",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"test": "npx jest --verbose --testPathPattern="
|
||||
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "Matter Labs",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/jest": "^29.5.11",
|
||||
"@types/shelljs": "^0.8.15",
|
||||
"jest": "^29.7.0",
|
||||
"shelljs": "^0.8.5",
|
||||
"ts-jest": "^29.1.1",
|
||||
"typescript": "^5.3.3"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
pragma solidity >=0.0;
|
||||
contract C {}
|
||||
@@ -0,0 +1,54 @@
|
||||
object "Test" {
|
||||
code {
|
||||
{
|
||||
mstore(64, 128)
|
||||
if callvalue() { revert(0, 0) }
|
||||
let _1 := datasize("Test_deployed")
|
||||
codecopy(0, dataoffset("Test_deployed"), _1)
|
||||
return(0, _1)
|
||||
}
|
||||
}
|
||||
object "Test_deployed" {
|
||||
code {
|
||||
{
|
||||
mstore(64, 128)
|
||||
if iszero(lt(calldatasize(), 4))
|
||||
{
|
||||
let _1 := 0
|
||||
switch shr(224, calldataload(_1))
|
||||
case 0x3df4ddf4 {
|
||||
if callvalue() { revert(_1, _1) }
|
||||
if slt(add(calldatasize(), not(3)), _1) { revert(_1, _1) }
|
||||
let memPos := allocate_memory(_1)
|
||||
mstore(memPos, 0x2a)
|
||||
return(memPos, 32)
|
||||
}
|
||||
case 0x5a8ac02d {
|
||||
if callvalue() { revert(_1, _1) }
|
||||
if slt(add(calldatasize(), not(3)), _1) { revert(_1, _1) }
|
||||
let memPos_1 := allocate_memory(_1)
|
||||
return(memPos_1, sub(abi_encode_uint256(memPos_1, 0x63), memPos_1))
|
||||
}
|
||||
}
|
||||
revert(0, 0)
|
||||
}
|
||||
function abi_encode_uint256(headStart, value0) -> tail
|
||||
{
|
||||
tail := add(headStart, 32)
|
||||
mstore(headStart, value0)
|
||||
}
|
||||
function allocate_memory(size) -> memPtr
|
||||
{
|
||||
memPtr := mload(64)
|
||||
let newFreePtr := add(memPtr, and(add(size, 31), not(31)))
|
||||
if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr))
|
||||
{
|
||||
mstore(0, shl(224, 0x4e487b71))
|
||||
mstore(4, 0x41)
|
||||
revert(0, 0x24)
|
||||
}
|
||||
mstore(64, newFreePtr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
.text
|
||||
.file "main"
|
||||
.globl __entry
|
||||
__entry:
|
||||
.func_begin0:
|
||||
sub.s! 0, r2, r1
|
||||
jump.eq @.BB0_2
|
||||
add 32, r0, r1
|
||||
st.1 r0, r1
|
||||
st.1 r1, r0
|
||||
add @CPI0_1[0], r0, r1
|
||||
ret.ok.to_label r1, @DEFAULT_FAR_RETURN
|
||||
.BB0_2:
|
||||
add 42, r0, r1
|
||||
st.1 r0, r1
|
||||
add @CPI0_0[0], r0, r1
|
||||
ret.ok.to_label r1, @DEFAULT_FAR_RETURN
|
||||
.func_end0:
|
||||
|
||||
.note.GNU-stack
|
||||
.rodata
|
||||
CPI0_0:
|
||||
.cell 2535301200456458802993406410752
|
||||
CPI0_1:
|
||||
.cell 5070602400912917605986812821504
|
||||
@@ -0,0 +1,31 @@
|
||||
import * as path from 'path';
|
||||
|
||||
const outputDir = 'artifacts';
|
||||
const binExtension = ':C.zbin';
|
||||
const asmExtension = ':C.zasm';
|
||||
const contractSolFilename = 'contract.sol';
|
||||
const contractYulFilename = 'contract.yul';
|
||||
const contractZkasmFilename = 'contract.zkasm';
|
||||
const pathToOutputDir = path.join( __dirname, '..', outputDir);
|
||||
const pathToContracts = path.join( __dirname, '..', 'src', 'contracts');
|
||||
const pathToBasicYulContract = path.join(pathToContracts, 'yul', contractYulFilename);
|
||||
const pathToBasicZkasmContract = path.join(pathToContracts, 'zkasm', contractZkasmFilename);
|
||||
const pathToBasicSolContract = path.join(pathToContracts, 'solidity', contractSolFilename);
|
||||
const pathToSolBinOutputFile = path.join(pathToOutputDir, contractSolFilename + binExtension);
|
||||
const pathToSolAsmOutputFile = path.join(pathToOutputDir, contractSolFilename + asmExtension);
|
||||
|
||||
export const paths = {
|
||||
outputDir: outputDir,
|
||||
binExtension: binExtension,
|
||||
asmExtension: asmExtension,
|
||||
contractSolFilename: contractSolFilename,
|
||||
contractZkasmFilename: contractZkasmFilename,
|
||||
contractYulFilename: contractYulFilename,
|
||||
pathToOutputDir: pathToOutputDir,
|
||||
pathToContracts: pathToContracts,
|
||||
pathToBasicZkasmContract: pathToBasicZkasmContract,
|
||||
pathToBasicSolContract: pathToBasicSolContract,
|
||||
pathToBasicYulContract: pathToBasicYulContract,
|
||||
pathToSolBinOutputFile: pathToSolBinOutputFile,
|
||||
pathToSolAsmOutputFile: pathToSolAsmOutputFile,
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
import * as shell from 'shelljs';
|
||||
import * as fs from 'fs';
|
||||
|
||||
interface CommandResult {
|
||||
output: string;
|
||||
exitCode: number;
|
||||
}
|
||||
|
||||
export const executeCommand = (command: string): CommandResult => {
|
||||
const result = shell.exec(command, {async: false});
|
||||
return {
|
||||
exitCode: result.code,
|
||||
output: result.stdout.trim() || result.stderr.trim(),
|
||||
};
|
||||
};
|
||||
|
||||
export const isFolderExist = (folder: string): boolean => {
|
||||
return shell.test('-d', folder);
|
||||
};
|
||||
|
||||
export const isFileExist = (pathToFileDir: string, fileName: string, fileExtension:string): boolean => {
|
||||
return shell.ls(pathToFileDir).stdout.includes(fileName + fileExtension);
|
||||
};
|
||||
|
||||
export const isFileEmpty = (file: string): boolean => {
|
||||
if (fs.existsSync(file)) {
|
||||
return (fs.readFileSync(file).length === 0);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,39 @@
|
||||
import {executeCommand} from "../src/helper";
|
||||
import { paths } from '../src/entities';
|
||||
|
||||
|
||||
//id1746
|
||||
describe("Run with --asm by default", () => {
|
||||
const command = `zksolc ${paths.pathToBasicSolContract} --asm`;
|
||||
const result = executeCommand(command);
|
||||
const commandInvalid = 'zksolc --asm';
|
||||
const resultInvalid = executeCommand(commandInvalid);
|
||||
|
||||
it("Valid command exit code = 0", () => {
|
||||
expect(result.exitCode).toBe(0);
|
||||
});
|
||||
|
||||
it("--asm output is presented", () => {
|
||||
expect(result.output).toMatch(/(__entry:)/i);
|
||||
});
|
||||
|
||||
|
||||
it("solc exit code == zksolc exit code", () => {
|
||||
const command = `solc ${paths.pathToBasicSolContract} --asm`;
|
||||
const solcResult = executeCommand(command);
|
||||
expect(solcResult.exitCode).toBe(result.exitCode);
|
||||
});
|
||||
|
||||
it("run invalid: zksolc --asm", () => {
|
||||
expect(resultInvalid.output).toMatch(/(No input sources specified|Compilation aborted)/i);
|
||||
});
|
||||
it("Invalid command exit code = 1", () => {
|
||||
expect(resultInvalid.exitCode).toBe(1);
|
||||
});
|
||||
|
||||
it("Invalid solc exit code == Invalid zksolc exit code", () => {
|
||||
const command = 'solc --asm';
|
||||
const solcResult = executeCommand(command);
|
||||
expect(solcResult.exitCode).toBe(resultInvalid.exitCode);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,78 @@
|
||||
import {executeCommand, isFolderExist, isFileExist, isFileEmpty} from "../src/helper";
|
||||
import { paths } from '../src/entities';
|
||||
|
||||
|
||||
//id1762
|
||||
describe("Run zksolc without any options", () => {
|
||||
const command = 'zksolc';
|
||||
const result = executeCommand(command);
|
||||
|
||||
it("Info with help is presented", () => {
|
||||
expect(result.output).toMatch(/(No input sources specified|Error(s) found.)/i);
|
||||
});
|
||||
|
||||
it("Exit code = 1", () => {
|
||||
expect(result.exitCode).toBe(1);
|
||||
});
|
||||
|
||||
it("solc exit code == zksolc exit code", () => {
|
||||
const command = 'solc';
|
||||
const solcResult = executeCommand(command);
|
||||
expect(solcResult.exitCode).toBe(result.exitCode);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
//#1713
|
||||
describe("Default run a command from the help", () => {
|
||||
|
||||
const command = `zksolc ${paths.pathToBasicSolContract} -O3 --bin --output-dir "${paths.pathToOutputDir}"`; // potential issue on zksolc with full path on Windows cmd
|
||||
const result = executeCommand(command);
|
||||
|
||||
it("Compiler run successful", () => {
|
||||
expect(result.output).toMatch(/(Compiler run successful.)/i);
|
||||
});
|
||||
it("Exit code = 0", () => {
|
||||
expect(result.exitCode).toBe(0);
|
||||
});
|
||||
it("Output dir is created", () => {
|
||||
expect(isFolderExist(paths.pathToOutputDir)).toBe(true);
|
||||
});
|
||||
xit("Output file is created", () => { // a bug on windows
|
||||
expect(isFileExist(paths.pathToOutputDir, paths.contractSolFilename, paths.binExtension)).toBe(true);
|
||||
});
|
||||
it("the output file is not empty", () => {
|
||||
expect(isFileEmpty(paths.pathToSolBinOutputFile)).toBe(false);
|
||||
});
|
||||
it("No 'Error'/'Warning'/'Fail' in the output", () => {
|
||||
expect(result.output).not.toMatch(/([Ee]rror|[Ww]arning|[Ff]ail)/i);
|
||||
});
|
||||
});
|
||||
|
||||
//#1818
|
||||
describe("Default run a command from the help", () => {
|
||||
|
||||
const command = `zksolc ${paths.pathToBasicSolContract} -O3 --bin --asm --output-dir "${paths.pathToOutputDir}"`; // potential issue on zksolc with full path on Windows cmd
|
||||
const result = executeCommand(command);
|
||||
|
||||
it("Compiler run successful", () => {
|
||||
expect(result.output).toMatch(/(Compiler run successful.)/i);
|
||||
});
|
||||
it("Exit code = 0", () => {
|
||||
expect(result.exitCode).toBe(0);
|
||||
});
|
||||
it("Output dir is created", () => {
|
||||
expect(isFolderExist(paths.pathToOutputDir)).toBe(true);
|
||||
});
|
||||
xit("Output files are created", () => { // a bug on windows
|
||||
expect(isFileExist(paths.pathToOutputDir, paths.contractSolFilename, paths.binExtension)).toBe(true);
|
||||
expect(isFileExist(paths.pathToOutputDir, paths.contractSolFilename, paths.asmExtension)).toBe(true);
|
||||
});
|
||||
it("the output files are not empty", () => {
|
||||
expect(isFileEmpty(paths.pathToSolBinOutputFile)).toBe(false);
|
||||
expect(isFileEmpty(paths.pathToSolAsmOutputFile)).toBe(false);
|
||||
});
|
||||
it("No 'Error'/'Warning'/'Fail' in the output", () => {
|
||||
expect(result.output).not.toMatch(/([Ee]rror|[Ww]arning|[Ff]ail)/i);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,40 @@
|
||||
import {executeCommand} from "../src/helper";
|
||||
import { paths } from '../src/entities';
|
||||
|
||||
|
||||
//id1743
|
||||
describe("Run with --yul by default", () => {
|
||||
const command = `zksolc ${paths.pathToBasicYulContract} --yul`;
|
||||
const result = executeCommand(command);
|
||||
const commandInvalid = 'zksolc --yul';
|
||||
const resultInvalid = executeCommand(commandInvalid);
|
||||
|
||||
it("Valid command exit code = 0", () => {
|
||||
expect(result.exitCode).toBe(0);
|
||||
});
|
||||
|
||||
it("--yul output is presented", () => {
|
||||
expect(result.output).toMatch(/(Compiler run successful)/i);
|
||||
expect(result.output).toMatch(/(No output requested)/i);
|
||||
});
|
||||
|
||||
|
||||
xit("solc exit code == zksolc exit code", () => { // unknown solc issue for datatype of the contract
|
||||
const command = `solc ${paths.pathToBasicSolContract} --yul`;
|
||||
const solcResult = executeCommand(command);
|
||||
expect(solcResult.exitCode).toBe(result.exitCode);
|
||||
});
|
||||
|
||||
it("run invalid: zksolc --yul", () => {
|
||||
expect(resultInvalid.output).toMatch(/(The input file is missing)/i);
|
||||
});
|
||||
it("Invalid command exit code = 1", () => {
|
||||
expect(resultInvalid.exitCode).toBe(1);
|
||||
});
|
||||
|
||||
it("Invalid solc exit code == Invalid zksolc exit code", () => {
|
||||
const command = 'solc --yul';
|
||||
const solcResult = executeCommand(command);
|
||||
expect(solcResult.exitCode).toBe(resultInvalid.exitCode);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,18 @@
|
||||
import {executeCommand} from "../src/helper";
|
||||
import { paths } from '../src/entities';
|
||||
|
||||
|
||||
//id1745
|
||||
describe("Run with --zkasm by default", () => {
|
||||
const command = `zksolc ${paths.pathToBasicZkasmContract} --zkasm`;
|
||||
const result = executeCommand(command);
|
||||
|
||||
it("Valid command exit code = 0", () => {
|
||||
expect(result.exitCode).toBe(0);
|
||||
});
|
||||
|
||||
it("--zkasm output is presented", () => {
|
||||
expect(result.output).toMatch(/(Compiler run successful)/i);
|
||||
expect(result.output).toMatch(/(No output requested)/i);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES6",
|
||||
"module": "CommonJS",
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user