diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..6fddca0d --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,7 @@ +version: 2 +updates: + # Maintain dependencies for GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/workflows/docker-release.yml b/.github/workflows/docker-release.yml new file mode 100644 index 00000000..fba2cf51 --- /dev/null +++ b/.github/workflows/docker-release.yml @@ -0,0 +1,39 @@ +name: Docker CI Release + +on: + release: + types: [published] + +env: + DOCKER_IMAGE: thehubbleproject/node + DOCKER_IMAGE_SHA: ${{ env.DOCKER_IMAGE }}:${{ github.sha }} + DOCKER_IMAGE_TAG: ${{ env.DOCKER_IMAGE }}:${{ github.event.release.tag_name }} + DOCKER_IMAGE_LATEST: ${{ env.DOCKER_IMAGE }}:latest + +jobs: + pull-tag-push: + runs-on: ubuntu-latest + needs: images + + steps: + - uses: actions/checkout@v2 + - + name: Login to DockerHub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - + name: Pull image for git sha + run: docker pull ${{ env.DOCKER_IMAGE_SHA }} + - + name: Tag image with release + run: docker tag ${{ env.DOCKER_IMAGE_SHA }} ${{ env.DOCKER_IMAGE_TAG }} + - + name: Tag image with latest + if: ${{ github.event.release.prerelease == 'false' }} + run: docker tag ${{ env.DOCKER_IMAGE_SHA }} ${{ env.DOCKER_IMAGE_LATEST }} + - + name: Push tagged image(s) + # Pushing the image name without a tag will push all new tags. + run: docker push ${{ env.DOCKER_IMAGE }} diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 00000000..b7a44778 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,43 @@ +name: Docker CI + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +env: + DOCKER_IMAGE: thehubbleproject/node + +jobs: + build-push: + runs-on: ubuntu-latest + steps: + - + name: Set up QEMU + uses: docker/setup-qemu-action@v1 + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + - + name: Login to DockerHub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - + name: Build and push git sha + id: docker_build + uses: docker/build-push-action@v2 + with: + file: docker/Dockerfile + push: true + tags: ${{ env.DOCKER_IMAGE }}:${{ github.sha }} + # Consider using GitHub local cache in the future + # https://docs.docker.com/ci-cd/github-actions/#optimizing-the-workflow + # https://github.com/docker/build-push-action/blob/master/docs/advanced/cache.md#github-cache + cache-from: type=registry,ref=${{ env.DOCKER_IMAGE }}:latest + cache-to: type=inline + - + name: Image digest + run: echo ${{ steps.docker_build.outputs.digest }} diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 146fcd68..33cf37f2 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -1,42 +1,74 @@ # This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions +# TODO On master/release, test all valid NodeJS versions +# https://github.com/thehubbleproject/hubble-contracts/issues/567 +# +# strategy: +# matrix: +# node-version: [10.x, 12.x, 14.x, 16.x] + name: Node.js CI on: push: branches: [ master ] pull_request: - branches: [ master, develop ] + branches: [ master ] -jobs: - build: +env: + NODEJS_VERSION: 10.x +jobs: + lint-bench: runs-on: ubuntu-latest - strategy: - matrix: - node-version: [10.x] - steps: - uses: actions/checkout@v2 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 + - + uses: actions/setup-node@v2 with: - node-version: ${{ matrix.node-version }} - + node-version: ${{ env.NODEJS_VERSION }} - run: npm ci - - run: npm run lint && npm run solhint + + - run: npm run lint + - run: npm run solhint - run: npm run generate - run: npm run keyless:check -- --offline + - run: npm run bench + + test-fast-client: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - + uses: actions/setup-node@v2 + with: + node-version: ${{ env.NODEJS_VERSION }} + - run: npm ci + + - run: npm run generate - run: npm run test -- test/fast/* - run: npm run test -- test/client/* + + test-slow-integration: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - + uses: actions/setup-node@v2 + with: + node-version: ${{ env.NODEJS_VERSION }} + - run: npm ci + + - run: npm run generate - run: npm run test -- test/slow/* - run: npm run test -- test/integration.test.ts - - run: npm run bench cloc: - needs: build + needs: [lint-bench, test-fast-client, test-slow-integration] runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 diff --git a/.gitignore b/.gitignore index 5d5fe795..3ffefed4 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ types/ethers-contracts/ cache/ artifacts/ build/ +docker/testData diff --git a/README.md b/README.md index 94393250..e6b7fdd2 100644 --- a/README.md +++ b/README.md @@ -1,49 +1,55 @@ -# Hubble Optimistic Rollup Contracts +# Hubble Optimistic Rollup Contracts & NodeJS TypeScript Client (Node) ![Node.js CI](https://github.com/thehubbleproject/RedditHubble/workflows/Node.js%20CI/badge.svg) ## About Hubble -Hubble is a token transfer solution to improve Ethereum throughput from 20 transactions per second to 2600. +Hubble is an [ERC-20](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/) token transfer solution that improves Ethereum throughput from 20 transactions per second to ~2700. -### How it work +### How it works -People sumit transfers to a coordinator, who then submits transactions and the state root of the balances update to a Ethereum contract. +Accounts submit transfers to a coordinator node who then submits transactions and the state root of the balance updates to an Ethereum smart contract ([Rollup.sol](./contracts/rollup/Rollup.sol)). -### Why can that improve the throughput +### How does this improve throughput? -The contract does not validate either the correctness of the balances update or the authenticity of the sender. +The contract does not validate either the correctness of the balance updates or the authenticity of the sender. -### What if the coordinator submit incorrect balances update? +### What if the coordinator submits incorrect balance updates? -Anyone can trigger the dispute methods of the contract and penalize the coordinator by burning the assets they staked beforehand. The contract rolls back to the last state when the balance was correct. +Anyone can trigger the dispute methods of the contract and penalize the coordinator by burning the assets they staked beforehand. The contract rolls back to the last state when the balances were correct. -### How is it different from these projects +### How is it different from other Layer 2 (L2) Ethereum projects? -- Optimism: Hubble does not support virtual machine, ... yet. -- ZK rollups: Both improve throughput but Hubble is ZK free. No zero-knowledge moon math, only boring EVM at work. +- [Optimism](https://optimism.io/): Hubble does not support the EVM virtual machine, ... yet. +- [ZK (zero knowledge proof) rollups](https://docs.ethhub.io/ethereum-roadmap/layer-2-scaling/zk-rollups/): Both improve throughput but Hubble is ZK free. No zero-knowledge moon math, only boring EVM at work. - ZK optimistic rollups: Hubble does not address privacy. -Hubble has the highest throughput compared with all above applications, since +Hubble has the highest throughput compared with the above, since: -- We use BLS signature aggregation to reduce the size to store data on chain -- We optimize for simple transfer +- Hubble use BLS signature aggregation to reduce the size to store data on chain. +- We optimize for simple token transfers. ### What else can Hubble do -- Mass Migration: Users can migrate their tokens to other layer 2 solutions without withdraw to and deposit from layer 1 again. -- Create2Transfer: Users can onboard Hubble without going through layer 1. The coordinator can register pubkeys for them and they can acquire tokens from holders who are already in Hubble. +#### Mass Migration +Users can migrate their tokens to other L2 solutions without withdrawing to and depositing from Layer 1 (L1) again. -## Getting Started +#### Create2Transfer -```sh -npm install -npm run generate -``` +Users can onboard accounts to Hubble without going through L1. The coordinator can register their public keys and then they can acquire tokens from holders who are already in the Hubble L2. + +## Local Development -## Testing +See [Setup](./SETUP.md) instructions + +## Docker + +https://hub.docker.com/r/thehubbleproject/node ```sh -npm run test +docker pull thehubbleproject/node:latest +# or for a specific release, ...:v0.x.y ``` + +See [Docker](./docker/README.md) instructions. diff --git a/SETUP.md b/SETUP.md new file mode 100644 index 00000000..462a50cb --- /dev/null +++ b/SETUP.md @@ -0,0 +1,160 @@ +# Setup for Local Development + +## Deps + +- [Geth](https://geth.ethereum.org/docs/install-and-build/installing-geth) +- [NodeJS](https://nodejs.org/en/download/) +- (Recommended instead of NodeJS) [nvm](https://github.com/nvm-sh/nvm#installing-and-updating) + +## Geth + +### run + +```sh +geth --datadir dev-chain/ --http --dev --dev.period=14 --rpc.allow-unprotected-txs +``` + +### fund deployer + +Use `Account #0` + +```txt +Account #0: 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266 (10000 ETH) +Private Key: 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 +``` + +In shell: +```sh +geth attach ./dev-chain/geth.ipc +``` + +Then in geth console: +```sh +eth.coinbase +account = "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266" +eth.sendTransaction({from:eth.coinbase, to:account, value: web3.toWei(10000, "ether")}) +``` + +## Deploy Contracts + +### install + +```sh +npm install +``` + +### (recommended) configure BurnAuction.sol + +Before we deploy contracts we recommend you shorten the slot time of the [burn auction contract](./contracts/proposers/BurnAuction.sol) to make iteration faster. + +```diff +diff --git a/contracts/proposers/BurnAuction.sol b/contracts/proposers/BurnAuction.sol +index 479b34d..963b30a 100644 +--- a/contracts/proposers/BurnAuction.sol ++++ b/contracts/proposers/BurnAuction.sol +@@ -7,8 +7,8 @@ import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; + contract BurnAuction is Chooser { + using SafeMath for uint256; + +- uint32 public constant BLOCKS_PER_SLOT = 100; +- uint32 public constant DELTA_BLOCKS_INITIAL_SLOT = 1000; ++ uint32 public constant BLOCKS_PER_SLOT = 10; ++ uint32 public constant DELTA_BLOCKS_INITIAL_SLOT = 20; + + // donation numerator and demoninator are used to calculate donation amount + uint256 public constant DONATION_DENOMINATOR = 10000; + + +``` + +### generate + +Compiles [Solidity](https://soliditylang.org/) contracts and [TypeChain](https://github.com/ethereum-ts/Typechain) [TypeScript](https://www.typescriptlang.org/) bindings. +```sh +npm run generate +``` + +### deploy + +``` +npm run deploy -- \ +--key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \ +--root 0xbfef011dd64abe7707cee7b3b74a00b86689c8451f548371073ce3c935e09984 \ +--numPubkeys 32 +``` + +This should generate a `genesis.json` file that looks like: + +```json +{ + "parameters": { + "MAX_DEPTH": 32, + "MAX_DEPOSIT_SUBTREE_DEPTH": 2, + "STAKE_AMOUNT": "100000000000000000", + "BLOCKS_TO_FINALISE": 40320, + "MIN_GAS_LEFT": 10000, + "MAX_TXS_PER_COMMIT": 32, + "USE_BURN_AUCTION": true, + "DONATION_ADDRESS": "0x00000000000000000000000000000000000000d0", + "DONATION_NUMERATOR": 7500, + "GENESIS_STATE_ROOT": "0xbfef011dd64abe7707cee7b3b74a00b86689c8451f548371073ce3c935e09984" + }, + "addresses": { + "frontendGeneric": "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9", + "frontendTransfer": "0x5FC8d32690cc91D4c39d9d3abcBD16989F875707", + "frontendMassMigration": "0x0165878A594ca255338adfa4d48449f69242Eb8F", + "frontendCreate2Transfer": "0xa513E6E4b8f2a923D98304ec87F64353C4D5C853", + "blsAccountRegistry": "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318", + "tokenRegistry": "0x610178dA211FEF7D417bC0e6FeD39F05609AD788", + "transfer": "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0", + "massMigration": "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e", + "create2Transfer": "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82", + "burnAuction": "0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6", + "exampleToken": "0x9A676e781A523b5d0C0e43731313A708CB607508", + "spokeRegistry": "0x9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE", + "vault": "0x68B1D87F95878fE05B998F19b66F4baba5De1aed", + "depositManager": "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c", + "rollup": "0xc6e7DF5E7b4f2A278906862b61205850344D4e7d", + "withdrawManager": "0x322813Fd9A801c5507c9de605d63CEA4f2CE6c44" + }, + "auxiliary": { + "domain": "0x4ea7799478a7af2a47ba555f04aec4ae4ba240bf410d7c859c34c310f0413892", + "genesisEth1Block": 306, + "version": "20539ad4d99b3d3e4810de24c14ba41cdd89ea2c" + } +} +``` + +The client will be parameterized using this file. + +## Run Client (Node) + +```sh +npx ts-node ./scripts/simulate.ts --proposer +``` + +### repl (Hubble console) + +```sh +npm run repl +``` + +Then in repl console, run a transfer: + +```sh +hubble.transfer(0, 1, 1, 1) +``` + +## Run Tests + +Note: Full test suite run currently fails due to test state leak + +```sh +npm run test +``` + +### fast/slow/client + +```sh +npm run test -- test/fast/* # slow/client/etc. +``` \ No newline at end of file diff --git a/docker/.dockerignore b/docker/.dockerignore new file mode 100644 index 00000000..ca617e9f --- /dev/null +++ b/docker/.dockerignore @@ -0,0 +1 @@ +**/testData diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 00000000..f03025aa --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,51 @@ +# https://docs.docker.com/develop/develop-images/multistage-build/ + +######################### +# Transpiles typescript # +######################### +FROM node:10-alpine as builder + +WORKDIR /app + +COPY ./package.json ./package-lock.json ./ +RUN npm ci + +# compile contracts and generate typescript bindings +COPY ./hardhat.config.ts ./ +COPY ./contracts ./contracts +RUN npm run generate + +# typescript transpile +COPY tsconfig.json ./ +COPY ./scripts ./scripts +COPY ./ts ./ts +RUN npm run tsc + +##################################### +# Installs only production npm deps # +##################################### +FROM node:10-alpine as prod-deps + +WORKDIR /deps + +COPY ./package.json ./package-lock.json ./ +RUN npm ci --only=production + +#################### +# Production image # +#################### +FROM node:10-alpine + +ENV PORT 3000 +EXPOSE ${PORT} + +# common TLS certs (SSL/HTTPS) +RUN apk --no-cache add ca-certificates + +WORKDIR /app + +# Bring in assets from other intermediate build stages +COPY --from=prod-deps /deps/node_modules ./node_modules +COPY --from=builder /app/build ./build + +CMD ["node", "/app/build/scripts/simulate.js"] diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 00000000..2bd54705 --- /dev/null +++ b/docker/README.md @@ -0,0 +1,40 @@ +# Docker Image + +## Deps + +- [Docker](https://docs.docker.com/engine/install/) +- [Docker Compose](https://docs.docker.com/compose/install/) For ease of using locally. + +## Setup + +See [Local Development Setup](../SETUP.md) instructions. + +## Build + +From this (`docker`) directory + +### docker + +```sh +docker build .. -f ./Dockerfile +``` + +### docker-compose + +```sh +docker-compose build hubble +``` + +## Run + +From this (`docker`) directory: +```sh +mkdir -p testData/dev-chain +cp ../genesis.json ./testData/genesis.json + +docker-compose up -d geth +sleep 10 +docker-compose up hubble +``` + +Note that the hubble node will current crash (`exit 1`) until https://github.com/thehubbleproject/hubble-contracts/issues/557 is completed. diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 00000000..db6493b1 --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,21 @@ +version: "3.8" + +services: + geth: + image: ethereum/client-go:v1.9.25 + ports: + - "8545:8545" + volumes: + - "./testData/dev-chain:/dev-chain" + command: --datadir dev-chain/ --http --dev --dev.period=14 + + hubble: + depends_on: + - geth + build: + context: .. + dockerfile: ./docker/Dockerfile + ports: + - "3000:3000" + volumes: + - "./testData/genesis.json:/app/genesis.json" diff --git a/package-lock.json b/package-lock.json index 1a6cf3fa..fc6b9cce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -755,6 +755,12 @@ "integrity": "sha512-RaE0B+14ToE4l6UqdarKPnXwVDuigfFv+5j9Dze/Nqr23yyuqdNvzcZi3xB+3Agvi5R4EOgAksfv3lXX4vBt9w==", "dev": true }, + "@types/minimist": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.1.tgz", + "integrity": "sha512-fZQQafSREFyuZcdWFAExYjBiCL7AUCdgsk80iO0q4yihYYdcIiH28CcuPTGFgLOCC8RlW49GSQxdHwZP+I7CNg==", + "dev": true + }, "@types/mocha": { "version": "8.2.2", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.2.tgz", @@ -3093,8 +3099,7 @@ "minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, "mkdirp": { "version": "0.5.5", diff --git a/package.json b/package.json index b6e84b1e..115495f3 100644 --- a/package.json +++ b/package.json @@ -37,12 +37,12 @@ "@types/chai": "^4.2.18", "@types/chai-as-promised": "^7.1.4", "@types/lodash": "^4.14.170", + "@types/minimist": "^1.2.1", "@types/mocha": "^8.2.2", "@types/node": "^14.17.3", "chai": "^4.3.4", "chai-as-promised": "^7.1.1", "hardhat": "^2.3.2", - "minimist": "^1.2.5", "prettier": "^1.19.1", "prettier-plugin-solidity": "1.0.0-beta.11", "solhint": "^3.3.6", @@ -56,6 +56,7 @@ "ethers": "5.3.1", "fastify": "^3.17.0", "lodash": "^4.17.21", - "mcl-wasm": "0.4.5" + "mcl-wasm": "0.4.5", + "minimist": "^1.2.5" } } diff --git a/scripts/deploy.ts b/scripts/deploy.ts index 6d7c4e4b..6c33aaa9 100644 --- a/scripts/deploy.ts +++ b/scripts/deploy.ts @@ -1,4 +1,5 @@ import { ethers } from "ethers"; +import minimist from "minimist"; import { deployAndWriteGenesis } from "../ts/deploy"; import { DeploymentParameters } from "../ts/interfaces"; import fs from "fs"; @@ -6,25 +7,20 @@ import { PRODUCTION_PARAMS } from "../ts/constants"; import { StateTree } from "../ts/stateTree"; import { Group } from "../ts/factory"; -const { - url, - root, - key, - input, - output, - numPubkeys, - pubkeyMnemonic -} = require("minimist")(process.argv.slice(2), { - string: [ - "url", - "root", - "key", - "input", - "output", - "numPubkeys", - "pubkeyMnemonic" - ] -}); +const { url, root, key, input, output, numPubkeys, pubkeyMnemonic } = minimist( + process.argv.slice(2), + { + string: [ + "url", + "root", + "key", + "input", + "output", + "numPubkeys", + "pubkeyMnemonic" + ] + } +); /* Note separate pubkeys with commas > npm run deploy -- --url http://localhost:8545 \ diff --git a/scripts/deposit.ts b/scripts/deposit.ts index 280cf86f..9edbcf27 100644 --- a/scripts/deposit.ts +++ b/scripts/deposit.ts @@ -1,6 +1,7 @@ +import minimist from "minimist"; import { Hubble } from "../ts/hubble"; -const argv = require("minimist")(process.argv.slice(2), { +const argv = minimist(process.argv.slice(2), { string: ["url", "tokenID", "pubkeys", "amount"] }); diff --git a/scripts/keyless.ts b/scripts/keyless.ts index e248e850..bff1302a 100644 --- a/scripts/keyless.ts +++ b/scripts/keyless.ts @@ -1,4 +1,5 @@ import { ethers, providers } from "ethers"; +import minimist from "minimist"; import { calculateAddresses, deployerBytecode, @@ -8,7 +9,7 @@ import { import { deployKeyless } from "../ts/deployment/deploy"; import { KeylessDeployer } from "../ts/deployment/keylessDeployment"; -const argv = require("minimist")(process.argv.slice(2), { +const argv = minimist(process.argv.slice(2), { string: ["url", "root"], boolean: ["check", "deploy", "offline"] }); @@ -82,4 +83,9 @@ async function checkKeylessDeploymentSetup( // TODO: report deployment status. } -main(); +main() + .then(() => process.exit(0)) + .catch(error => { + console.error(error); + process.exit(1); + }); diff --git a/scripts/mineBlocks.ts b/scripts/mineBlocks.ts index 6d89f165..e3844a2a 100644 --- a/scripts/mineBlocks.ts +++ b/scripts/mineBlocks.ts @@ -1,7 +1,8 @@ -import { mineBlocks } from "../ts/utils"; import { ethers } from "ethers"; +import minimist from "minimist"; +import { mineBlocks } from "../ts/utils"; -const argv = require("minimist")(process.argv.slice(2)); +const argv = minimist(process.argv.slice(2)); // Assuming a node is already running `npm run node` // npx ts-node ./scripts/mineBlocks.ts -n 5 diff --git a/scripts/repl.ts b/scripts/repl.ts index f2178946..bc649546 100644 --- a/scripts/repl.ts +++ b/scripts/repl.ts @@ -11,4 +11,9 @@ async function startRepl() { local.context.ethers = ethers; } -startRepl(); +startRepl() + .then(() => process.exit(0)) + .catch(error => { + console.error(error); + process.exit(1); + }); diff --git a/scripts/simulate.ts b/scripts/simulate.ts index 414591ed..3dccbaac 100644 --- a/scripts/simulate.ts +++ b/scripts/simulate.ts @@ -1,10 +1,11 @@ import { AbortController } from "abort-controller"; import { BigNumber } from "ethers"; +import minimist from "minimist"; import { NodeType } from "../ts/client/constants"; import { HubbleNode } from "../ts/client/node"; import { sleep } from "../ts/utils"; -const argv = require("minimist")(process.argv.slice(2), { +const argv = minimist(process.argv.slice(2), { boolean: ["proposer"] }); diff --git a/test/fast/burnAuction.test.ts b/test/fast/burnAuction.test.ts index 0d0d8149..d02414e2 100644 --- a/test/fast/burnAuction.test.ts +++ b/test/fast/burnAuction.test.ts @@ -2,7 +2,8 @@ import { assert, expect } from "chai"; import { BigNumber, ContractReceipt, Signer } from "ethers"; import { ethers } from "hardhat"; -import { expectRevert, toWei } from "../../ts/utils"; +import { toWei } from "../../ts/utils"; +import { expectRevert } from "../../test/utils"; import { MockRollup, MockRollup__factory, diff --git a/test/fast/frontends.test.ts b/test/fast/frontends.test.ts index 3690cff6..388935ff 100644 --- a/test/fast/frontends.test.ts +++ b/test/fast/frontends.test.ts @@ -1,7 +1,8 @@ import { ethers } from "hardhat"; import { User } from "../../ts/factory"; import { TxCreate2Transfer, TxMassMigration, TxTransfer } from "../../ts/tx"; -import { expectCallRevert, hexToUint8Array, randHex } from "../../ts/utils"; +import { hexToUint8Array, randHex } from "../../ts/utils"; +import { expectCallRevert } from "../../test/utils"; import * as mcl from "../../ts/mcl"; import { deployKeyless } from "../../ts/deployment/deploy"; import { diff --git a/test/fast/pairingGasCostEstimator.test.ts b/test/fast/pairingGasCostEstimator.test.ts index 87ae5d57..1384f20e 100644 --- a/test/fast/pairingGasCostEstimator.test.ts +++ b/test/fast/pairingGasCostEstimator.test.ts @@ -4,7 +4,7 @@ import { BNPairingPrecompileCostEstimator__factory } from "../../types/ethers-contracts"; import { assert } from "chai"; -import { expectRevert } from "../../ts/utils"; +import { expectRevert } from "../../test/utils"; const BigNumber = ethers.BigNumber; diff --git a/test/slow/rollup.massMigration.test.ts b/test/slow/rollup.massMigration.test.ts index df4c1b77..703b573f 100644 --- a/test/slow/rollup.massMigration.test.ts +++ b/test/slow/rollup.massMigration.test.ts @@ -11,7 +11,8 @@ import chaiAsPromised from "chai-as-promised"; import { getGenesisProof, MassMigrationCommitment } from "../../ts/commitments"; import { CommonToken } from "../../ts/decimal"; import { Result } from "../../ts/interfaces"; -import { expectRevert, hexToUint8Array, mineBlocks } from "../../ts/utils"; +import { hexToUint8Array, mineBlocks } from "../../ts/utils"; +import { expectRevert } from "../../test/utils"; import { Group, txMassMigrationFactory } from "../../ts/factory"; import { deployKeyless } from "../../ts/deployment/deploy"; import { handleNewBatch } from "../../ts/client/batchHandler"; diff --git a/test/utils.ts b/test/utils.ts new file mode 100644 index 00000000..0a7afd0f --- /dev/null +++ b/test/utils.ts @@ -0,0 +1,34 @@ +import { ContractTransaction } from "ethers"; +import { assert, expect } from "chai"; + +export async function expectRevert( + tx: Promise, + revertReason: string +) { + await tx.then( + () => { + assert.fail(`Expect tx to fail with reason: ${revertReason}`); + }, + error => { + expect(error.message).to.have.string(revertReason); + } + ); +} + +export async function expectCallRevert( + tx: Promise, + revertReason: string | null +) { + await tx.then( + () => { + assert.fail(`Expect tx to fail with reason: ${revertReason}`); + }, + error => { + if (revertReason === null) { + assert.isNull(error.reason); + } else { + expect(error.reason).to.have.string(revertReason); + } + } + ); +} diff --git a/ts/utils.ts b/ts/utils.ts index a6903610..b23ffb46 100644 --- a/ts/utils.ts +++ b/ts/utils.ts @@ -9,7 +9,6 @@ import { getAddress } from "ethers/lib/utils"; import { Vacant, Wei } from "./interfaces"; -import { assert, expect } from "chai"; import { Rollup } from "../types/ethers-contracts/Rollup"; export const FIELD_ORDER = BigNumber.from( @@ -90,38 +89,6 @@ export async function mineBlocks( } } -export async function expectRevert( - tx: Promise, - revertReason: string -) { - await tx.then( - () => { - assert.fail(`Expect tx to fail with reason: ${revertReason}`); - }, - error => { - expect(error.message).to.have.string(revertReason); - } - ); -} - -export async function expectCallRevert( - tx: Promise, - revertReason: string | null -) { - await tx.then( - () => { - assert.fail(`Expect tx to fail with reason: ${revertReason}`); - }, - error => { - if (revertReason === null) { - assert.isNull(error.reason); - } else { - expect(error.reason).to.have.string(revertReason); - } - } - ); -} - export async function getBatchID(rollup: Rollup): Promise { return Number(await rollup.nextBatchID()) - 1; }